· 2 мин чтения
SM-2 и границы суток: почему расписание хранится датами
Как flashcards-sm2 и habit-tracker избегают сдвигов от часовых поясов и перехода на летнее время: даты вместо меток времени и сдвиг границы суток.
Интервальное повторение живёт в днях: «повторить через 6 дней». Если хранить момент времени, перелёт в другой пояс или переход на летнее время сдвинет карточку на день.
Даты, а не моменты
В flashcards-sm2 поля due, last и firstDay это локальные дни YYYY-MM-DD, у новой карточки null. «Сегодня» это календарная дата устройства. Расписание не знает про часы, поэтому смещение пояса его не трогает. Границу суток можно перенести на 03:00–05:00 в настройках, чтобы вечерний сеанс после полуночи считался вчерашним.
Алгоритм
Оценка q от 0 до 5, кнопки «Снова» = 1, «Трудно» = 3, «Хорошо» = 4, «Легко» = 5.
EF' = EF + 0.1 − (5−q)(0.08 + (5−q)·0.02), старт 2.5, нижняя граница 1.3.- Успех (q ≥ 3): 1 день, затем 6 дней, дальше
max(prev+1, round(prev·EF')), предел 3650 дней. - Провал: серия сбрасывается, интервал 1, карточка возвращается в конец сессии, EF не меняется.
Отличия от оригинала описаны: интервал строго растёт, добавлен graduating interval 4 дня для «Легко», просрочка не влияет на интервал.
Тот же приём в трекере привычек
В habit-tracker день хранится строкой в поясе пользователя на момент отметки, арифметика идёт через UTC-полночь. Поэтому перелёты и переход на летнее время историю не меняют.
Проверка и границы
30 тестов vitest, часть на fast-check. Это концепты: синхронизации между устройствами нет, данные живут в IndexedDB браузера.