в связи с очередными прошедшими игрищами со временем и его зональностью, обнаружилось мною тотальное лажание и неотработка перехода "в-ночь-на-26-е" как на операционных системах, так и собственно на программах. С операционками - малоинтересно, а вот про среды исполнения - следующее:
JAVA - переход не обрабатывает-с. Включая новейший релиз 8u25. До тех пор, пока не скачаешь отдельной ссылкой некий jar-архив, корректирующий tzdata и не поправишь им все виртуальные машины вручную.
.NET - обработка перехода напрямую зависит от обновлений исполняющей среды. В частности, намекаю на работу на неподдерживаемых операционных системах, типа несуществующей Windows XP - поскольку обновлений для этой ОС нет и не будет, программы .net будут лажать с временем и его промежутками гарантированно. Да, ручная установка соседней зоны не спасет. Лажают все старые версии MONO, которые imho никто корректировать и обновлять не собирается. Например, то что установлено на Debian 6.
Где это проявляется?
- если собрались посчитать количество реально прошедших секунд между например 2014.10.23 00:00:00 и 2104.10.30 00:00:00
- при попытке заценить время создания/модификации файла на файловой системе ОС
- при переводах unix timestamp в локальное время и локального времени обратно в unix timestamp. Что мне, собственно, и попалось.
А вот теперь самое интересное по тематике. free pascal с его rtl.
собираемся гонять timestampы следующими функциями:
- Код: Выделить всё
function DateTimeToUnixTicks(d:TDateTime):int64;
begin
Result:=DateTimeToUnix(LocalTimeToUniversal(d))
end;
function UnixTicksToDate(unixdate:int64):TDateTime;
begin
Result:=UniversalTimeToLocal(UnixToDateTime(unixdate));
end;
и обнаруживаем, что срабатывает все это преобразование верно при единственном условии: все даты и таймштампы должны находиться в пределах после последних изменений параметров временной зоны. Т.е. для 1 ноября 2014, скажем, это все будет обработано правильно, для 23 октября 2014 - неправильно. Естественно, если у нас корректно патчена операционная система, в ином случае будет все что угодно.
Если начать вчитываться в реализацию RTL, проблема оказывается в функциях UniversalTimeToLocal и LocalTimeToUniversal.
Зайдя внутрь, можно обнаружить, что упомянутые функции не знают о временных зонах ничего. И их врожденная стеснительность не позволяет запрашивать у операционной системы ничего, кроме смещения текущей зоны относительно UTC на текущий момент исполнения программного кода. В дальнейшем это смещение добавляется к дате в UTC, и получается результат. Не учитывающий никаких переходов и "летнего времени".
Imho, эта прекрасная особенность скорее всего не будет исправлена никогда, потому что путей у RTL два - либо "везти на себе" всю работу с временными зонами, как это сделано в Яве, либо полностью полагаться только на операционную систему и работать через нее. Ни то, ни другое скорее всего делаться не будет, тем более подозреваю, что подобная реализация вообще является исторической фичей со времен ДОС и царя Гороха, на которую ничего не стоит случайно наступить и намертво в ней увязнуть.
Так что, будьте внимательны. Со временем RTL freepascalя работать корректно не умеет.