Клиент хотел определить специальное значение FILETIME, которое всегда будет считаться большим по сравнению с другим FILETIME. Иными словами, CompareFileTime всегда должен говорить, что это сигнальное значение позже. Какое значение для этого подойдёт?
Строго согласно определению, FILETIME состоит из тиков, прошедших с 1 января 1601 года, и является беззнаковым значением, поэтому наибольшее значение, предположительно, 0xFFFFFFFFFFFFFFFF.
С другой стороны, документация по FILETIME отмечает, что некоторые функции считают значение 0xFFFFFFFFFFFFFFFF имеющим специальное значение. Например, функция SetFileTime рассматривает это значение как «не обновлять время для этого дескриптора».
Любые значения больше 0x7FFFFFFFFFFFFFFF тоже будут создавать проблемы, потому что такие функции, как CreateWaitableTimer, трактуют FILETIME с установленным старшим битом как представление отрицательного относительного интервала, а не абсолютного момента времени. Кроме того, некоторые программы считают такие значения временем до 1 января 1601 года.
Есть и функции вроде FileTimeToSystemTime, которые отвергают значения FILETIME, большие чем 0x7FFFFFFFFFFFFFFF. Так что, вероятно, лучше не превышать 0x7FFFFFFFFFFFFFFF.
Но подождите: возможно, вам также стоит подумать о коде, который выполняет корректировки часового пояса или операции вроде «на один день позже». Если вы зададите значение на краю допустимого диапазона, такая корректировка может вызвать переполнение в отрицательное значение. Это нормально? В конце концов, вы пытались выйти за максимальное значение. Всё зависит от того, для чего вы используете это сигнальное значение.
Интересно, что FileTimeToSystemTime может преобразовать 0x7FFFFFFFFFFFFFFF в SYSTEMTIME и выдаст дату в 30828 году, но если попытаться преобразовать её обратно, SystemTimeToFileTime не сможет — он завершается с ошибкой. Он может отдать такое значение, но не может принять его обратно.
Функция SystemTimeToFileTime поддерживает даты только до конца 30827 года. Если попытаться получить последний миллисекунд этого года, вы получите некоторое значение, но точное число будет зависеть от того, сколько високосных секунд хранится в базе данных високосных секунд.
Между тем, CLR System.DateTime ограничен концом 9999 года. А некоторые календари, например ChineseLunisolarCalendar, имеют ещё более низкий максимально поддерживаемый предел. (Для ChineseLunisolarCalendar максимальная поддерживаемая дата находится где-то в начале 2101 года, потому что таблицы идут только до этого.) Другие языки программирования имеют свои собственные ограничения на диапазон дат.
Итак, какое же значение вам следует использовать?
Это зависит от того, для чего вы его применяете.
Если вам нужен просто номер, который при сравнении через CompareFileTime будет больше любого другого значения, вы можете использовать 0xFFFFFFFFFFFFFFFF — это наибольшее значение, поддерживаемое CompareFileTime.
Однако не давайте этому значению выходить за пределы вашего кода, который понимает особый семантический смысл этого сигнала. Если вы позволите этому очень большому значению «утечь», кто‑то может сделать преобразование часового пояса, или сказать «Отлично, поставлю будильник на +1 день», или попытаться конвертировать его в C# System.DateTime и столкнуться с переполнением.
Если вам нужно специальное значение для использования вне вашего кода, лучше найти иной способ обозначить этот «особый» случай, например std::optional для C++ или Nullable
Raymond участвует в развитии Windows более 30 лет. В 2003 году он начал веб‑сайт, известный как The Old New Thing, который стал значительно популярнее, чем он ожидал, что до сих пор вызывает у него лёгкое беспокойство. Этот сайт породил книгу с тем же названием (Addison Wesley 2007). Иногда он появляется в аккаунте Windows Dev Docs в Твиттере, чтобы рассказать истории, не передающие полезной информации.
Обсуждение закрыто. Для редактирования/удаления существующих комментариев требуется вход в систему.
Здесь, возможно, есть некоторая ирония: пока мы все обсуждаем лучшие битовые шаблоны для представления абстрактной даты в далёком будущем, срок действия сертификата devblogs.microsoft.com истёк.
9999 лет должно быть достаточно для любого человека.
Звучит забавно, но это правда. Этот период настолько далёк, что его можно безопасно использовать как постоянный таймаут. Моё собственное приложение использует 9999 как означающее «постоянная разблокировка». Навряд ли кто‑то из моих пользователей доживёт до 10000 года, чтобы пожаловаться, что это больше не работает. 🙂
Краткая история сочетаний клавиш полос прокрутки в Windows
При работе с Win32 FILETIME не забывайте, что у вас есть std::chrono.
