Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Функция DosDateTimeToVariantTime в Windows API: описание и примеры использования в Delphi и Pascal

Delphi , Синтаксис , Дата и Время

 

Введение

При работе с датами в Windows API разработчики часто сталкиваются с функцией DosDateTimeToVariantTime, которая преобразует дату и время в формате DOS (16-битные значения) в формат Variant Time (8-байтное значение с плавающей точкой). Однако при использовании этой функции в Delphi и Free Pascal возникают нюансы, связанные с несоответствием типов данных. В этой статье мы разберем проблему и предложим решения для корректной работы с функцией.

Проблема определения функции

В модуле activex.pp (часть Free Pascal) функция объявлена следующим образом:

function DosDateTimeToVariantTime(
  wDosDate: ushort; 
  wDosTime: ushort;
  pvtime: pdouble
): longint; stdcall; external oleaut32dll name 'DosDateTimeToVariantTime';

Официальная документация Microsoft показывает аналогичное определение на C:

INT DosDateTimeToVariantTime(
  [in]  USHORT wDosDate,
  [in]  USHORT wDosTime,
  [out] DOUBLE *pvtime
);

Однако в описании функции указано:

"The function returns TRUE on success and FALSE otherwise."

Возникает противоречие:
1. В Pascal-реализации используется longint
2. В документации C-объявление использует INT
3. Фактическое поведение соответствует булевому типу (BOOL)

Анализ дизассемблированного кода

Исследование машинного кода функции показывает:

.text:100169FF                 xor     eax, eax
.text:10016A01                 jmp     short loc_100169EE

Функция явно возвращает 1 при успехе и 0 при ошибке, что соответствует поведению булевого типа.

Почему возникла проблема?

Исторические причины:
1. В старых версиях C/C++ тип BOOL был макросом для longint
2. Значения TRUE и FALSE определялись как 1 и 0 соответственно
3. Windows API сохраняет обратную совместимость, используя INT в заголовках

Как отмечает участник обсуждения Thaddy:

"This stems from C(++) compilers interpreting false as zero and anything else a valid true. Predates compilers with _Bool."

Решения для Pascal-разработчиков

Вариант 1: Сравнение с нулем (рекомендуется)

Самый простой и совместимый способ:

var
  DosDate, DosTime: Word;
  VTime: Double;
  Res: Longint;
begin
  // Преобразование даты и времени в DOS-формат
  DosDate := ...;
  DosTime := ...;

  Res := DosDateTimeToVariantTime(DosDate, DosTime, @VTime);

  if Res <> 0 then
    ShowMessage('Успешное преобразование: ' + FloatToStr(VTime))
  else
    ShowMessage('Ошибка преобразования');
end;

Вариант 2: Создание обертки с правильным типом

Для повышения семантической корректности:

function CorrectDosDateTimeToVariantTime(
  wDosDate: Word;
  wDosTime: Word;
  out VTime: Double
): Boolean;
var
  Res: Longint;
begin
  Res := DosDateTimeToVariantTime(wDosDate, wDosTime, @VTime);
  Result := Res <> 0;
end;

// Использование:
var
  Success: Boolean;
  VTime: Double;
begin
  Success := CorrectDosDateTimeToVariantTime(DosDate, DosTime, VTime);
  if Success then
    // Действия при успехе
end;

Альтернативное решение: прямая работа с API

Для полного контроля можно использовать прямое объявление:

function DosDateTimeToVariantTime(
  wDosDate: Word;
  wDosTime: Word;
  pvtime: PDouble
): LongBool; stdcall; external 'oleaut32.dll';

// Использование с правильным типом:
var
  VTime: Double;
begin
  if DosDateTimeToVariantTime(DosDate, DosTime, @VTime) then
    // Успешное выполнение
  else
    // Обработка ошибки
end;

Важно! При таком подходе необходимо учитывать: 1. Размер типа LongBool (4 байта) 2. Совместимость с существующим кодом 3. Поведение на разных версиях Windows

Рекомендации по работе с Windows API в Pascal

  1. Всегда проверяйте фактическое поведение функций через:
    Официальную документацию Microsoft
    Дизассемблирование (если необходимо)
    Эмпирическое тестирование
  2. Используйте правильные типы сравнений:
    // Неправильно:
    if DosDateTimeToVariantTime(...) then ...

    // Правильно:
    if DosDateTimeToVariantTime(...) <> 0 then ... 
  3. Для критически важных функций создавайте обертки с проверкой ошибок:
    function SafeDosDateTimeToVariantTime(...): Boolean;
    begin
    Result := DosDateTimeToVariantTime(...) <> 0;
    if not Result then
    RaiseLastOSError;
    end;

  4. Следите за обновлениями в Pascal-библиотеках:
    В FPC/Lazarus проблема исправлена в версии 3.2.2+
    В Delphi используйте официальные заголовки из Winapi.Windows

Пример полного преобразования

function FileTimeToVariantTime(const FileTime: TFileTime; out VTime: Double): Boolean;
var
  DosDate, DosTime: Word;
  LocalFileTime: TFileTime;
begin
  Result := False;
  if FileTimeToLocalFileTime(FileTime, LocalFileTime) then
    if FileTimeToDosDateTime(LocalFileTime, DosDate, DosTime) then
      Result := DosDateTimeToVariantTime(DosDate, DosTime, @VTime) <> 0;
end;

// Использование:
var
  Ft: TFileTime;
  Vt: Double;
begin
  GetSystemTimeAsFileTime(Ft);
  if FileTimeToVariantTime(Ft, Vt) then
    ShowMessage('Variant time: ' + FloatToStr(Vt))
  else
    ShowMessage('Ошибка преобразования');
end;

Заключение

Проблема с определением DosDateTimeToVariantTime в Pascal-библиотеках демонстрирует важность понимания низкоуровневых особенностей Windows API. Хотя официальные заголовки указывают тип INT, фактическое поведение функции соответствует булевому типу.

Для надежной работы:
1. Используйте сравнение результата с нулем
2. Рассмотрите создание типобезопасных оберток
3. Регулярно обновляйте библиотеки компонентов
4. Проверяйте документацию и фактические реализации

Эти принципы помогут избежать ошибок при работе не только с DosDateTimeToVariantTime, но и с другими API-функциями, где встречаются подобные несоответствия типов.

Создано по материалам из источника по ссылке.

Особенности преобразования форматов даты и времени в Windows API при работе с Pascal и Delphi, включая решение проблем несоответствия типов данных.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Дата и Время ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 17:14:06
2025-12-22 15:21:29/0.009829044342041/0