понедельник, 24 ноября 2008 г.

Как распознать тип отдельно взятой временной метки

Это перевод How to recognize different types of timestamps from quite a long way away. Автор: Реймонд Чен. Примечание: в отличие от других постов, этот пост сильно отличается от оригинала. Произведено множество замен от C к Delphi.

Одной из хороших сторон меток времени является количество их форматов, из которых мы можем выбирать. Иногда во время отладки (или при чтении неполной документации) вы можете наткнуться на значение метки времени и задуматься, как перевести его во что-нибудь читабельное. Вот несколько подсказок.

Ниже в примерах мы будем использовать время 26 ноября 2002, 19:25 по PST.

Номер 1: метки времени UNIX
Временные метки UNIX (любое 32-х битное целое в Delphi) записываются числом секунд, прошедших с 1 января 1970 по UTC. Это число записывается в 32-х битное целое. Пожалуй, это единственный сколь-либо распространённый формат метки времени, в котором используются 32-х битные числа.

26 ноября 2002, 19:25 PST = $3DE43B0C.

Если 32-х битное значение начинается с "3" или с "4", то есть вероятность, что это значение является меткой времени в формате времени UNIX (эра цифры "3" начинается в 1995 и заканчивается в 2004).

Чтобы перевести эти значения во что-нибудь читабельное, вы можете воспользоваться модулем JclDateTime из библиотеки JCL. В этом модуле есть функции для перевода меток времени в формате UNIX в формат Win32 FILETIME и в родной формат Delphi TDateTime (DateTimeToUnixTime/UnixTimeToDateTime и FileTimeToUnixTime/UnixTimeToFileTime). Или же, начиная, кажется, с Delphi 6, в стандартном модуле DateUtils есть DateTimeToUnix и UnixToDateTime.

Этот формат времени используется библиотеками C (в C runtime library это тип time_t) и службой событий Windows NT (Windows NT event log).

Номер 2: Win32 FILETIME
Значения FILETIME (тип TFileTime в Delphi) в Win32 показывают число 100-наносекундных интервалов с 1 января 1600 по UTC. Эти значения записываются в 64-х битное число.

26 ноября 2002, 19:25 PST = $01C295C4:91150E00.

Если 64-х битное значение начинается с "01" и последующей буквы, то есть вероятность, что это значение представляет собой метку времени в формате FILETIME из Win32 (эра "01A" начинается в 1972, а эра "01F" заканчивается в 2057).

Для конвертации этих значений в читабельный вид, вы можете использовать DateTimeToFileTime/FileTimeToDateTime из JclDateTime. Стандартными средствами использование возможно только в обход - например, с помощью промежуточной конвертации в TSystemTime через FileTimeToSystemTime/SystemTimeToFileTime (одновременно с использованием FileTimeToLocalFileTime/LocalFileTimeToFileTime), а уж затем в TDateTime через SystemTimeToDateTime/DateTimeToSystemTime (все функции находятся в модулях Windows и SysUtils).

Номер 3: System.DateTime из CLR
Предупреждение: это самый настоящий материал по .NET (извините меня).
Тип CLR System.DateTime содержит число 100-наносекундных интервалов, начиная с 1 января 1 года по UTC. Это значение записывается в 64-х битное число. Этот формат пока используется не очень часто.

26 ноября 2002, 19:25 PST = $08C462CB:FCED3800? (кто-нибудь, проверьте мои вычисления)

Если 64-х битное значение начинается с "08" и буквы, то это, вероятно, время в формате CLR System.DateTime (эра "08A" начинается в 1970, а эра "08F" заканчивается в 2056).

Для конвертации можно использовать тип TDateTime в Delphi .NET. Там он объявлен как запись с перегруженными операторами. В частности, есть оператор приведения типов, в том числе и от System.DateTime. Т.е. конвертация осуществляется простым приведением типа от System.DateTime к TDateTime в Delphi .NET.

Номер 4: формат времени DOS
Формат метки времени DOS представляет собой битовую маску. С младших к старшим битам: 5 бит - секунды, 6 бит - минуты, 5 бит - час (т.е. время занимает младшие 16 бит), 5 бит - день, 4 бита - месяц, 7 бит - год (т.е. дата занимает старшие 16 бит). Год хранится как смещение от 1980-го. Секунды хранятся двух-секундными интервалами (т.е. если поле "секунды" равно 15, то секунд на самом деле 30).

Эти значения записываются по местному времени.

26 ноября 2002, 19:25 PST = $2D7A9B20.

Чтобы перевести эти значения в читабельный вид, можно воспользоваться DateTimeToDosDateTime/DosDateTimeToDateTime из JCL. А для стандартной реализации проще всего воспользоваться системными функциями DosDateTimeToFileTime/FileTimeToDosDateTime для конвертации их в TFileTime, а затем уже конвертировать TFileTime как и ранее. Кроме того, для прямой конвертации в TDateTime есть функции FileDateToDateTime/DateTimeToFileDate - они также работают с временем в формате DOS, хотя их имена об этом и не говорят.

Примечание: этот формат используют некоторые устаревшие функции Delphi, пришедшие в неё ещё из Турбо Паскаля. Например, FileAge или TSearchRec.Time. Вместо таких функций рекомендуется использовать их современные аналоги (для нашего примера это перегруженный FileAge и TSearchRec.FindData.ftLastWriteTime).

Номер 5: формат OLE Automation
Формат метки времени OLE (тип TDateTime в Delphi) представляет собой число с плавающей точкой, содержащее число дней с полуночи 30 декабря 1899. Часы и минуты представляются как дробное число дней. Этот формат соответствует родному типу времени в Delphi - TDateTime.

Перевод между форматами
Если вы используете только голые Delphi, то часто нет прямого способа перевести метку времени из одного формата в другой. В этом случае нужно использовать промежуточный формат (как это было в примере с TFileTime). Хотя модуль JclDateTime из JCL определяет все возможные случаи для упоминаемых форматов (кроме System.DateTime).

Другие форматы времени
В JScript конструктор объекта Date может создавать объект с integer-а, представляющего миллисекунды с 1970-го. Этот формат почти эквивалентен времени UNIX, просто умноженному на 1000.

Системный тип SYSTEMTIME из Win32 (TSystemTime в Delphi) по сути является простой записью. Этот тип используется в некоторых функциях WinAPI. Стандартными средствами Delphi его можно конвертировать в TFileTime и TDateTime.

См. также:

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.