· 2 мин чтения

SM-2 и границы суток: почему расписание хранится датами

Как flashcards-sm2 и habit-tracker избегают сдвигов от часовых поясов и перехода на летнее время: даты вместо меток времени и сдвиг границы суток.

Проект: flashcards-sm2

Интервальное повторение живёт в днях: «повторить через 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 браузера.