TTL без платформенных часов
Проверить точную границу истечения в commonMain
Реализуй ExpiringValue для общего кода. Часы внедряются интерфейсом и возвращают монотонные миллисекунды. Отсчёт начинается при создании. Значение доступно, пока elapsed < ttlMillis; ровно на границе оно уже истекло. TTL=0 означает немедленное истечение, отрицательный TTL запрещён.
Условия: один последовательный владелец; часы не идут назад; разность показаний помещается в Long. Долговременное сохранение этой временной отметки между запусками не требуется.
Проверки fake clock: старт 100, TTL=10 → на 100 и 109 вернуть value, на 110 и 111 вернуть null; нулевой TTL; отрицательный TTL. Нельзя обращаться к java.*, Android Context или системным часам внутри класса.
Кейс расширяет идею интерфейсной платформенной границы из KMP-блока draft/faq500.md.
Сохранённый код превышает предел редактора. Скачай его перед сбросом; исходная запись сохранена.
Зависимость передана экземпляром, поэтому два теста могут использовать разные fake clock без замены actual-реализации. Сравнение строгое: на границе TTL значение уже не выдаётся. Неравенство проверяет длительность в заданной системе отсчёта. Expect/actual и интерфейсы.
В приложении адаптер можно построить на TimeSource.Monotonic, сохранив единицы и общий origin; календарные часы для этого договора не подходят. Монотонную отметку нельзя трактовать как дату или переносить между процессами. Kotlin: TimeSource.
Для nullable T результат null не отличает истечение от сохранённого null — если это требуется, верните отдельный sealed-результат. Решение не запускалось на JVM/Native.