Перевести TDateTime в SYSTEMTIME

Тема в разделе "WASM.A&O", создана пользователем Dmitry_177, 27 мар 2007.

  1. Dmitry_177

    Dmitry_177 New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2007
    Сообщения:
    75
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    А тебе неременно хочется "ручками", поупражняться в A&0 ?
    Не проще ли через апишные SystemTimeToFileTime и FileTimeToSystemTime ?
    Грузишь DateTime в FPU, умножаешь на 24*60*60*10^7 (число 100 нс интервалов в сутках), округляешь до целого и прибавляешь заранее расчитанную дельту - получаешь FILETIME и из него SYSTEMTIME

    PS: исправил 10000 на 10^7 - опять забыл про микросекунды ;))
     
  3. Dmitry_177

    Dmitry_177 New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2007
    Сообщения:
    75
    а как это сделать?
     
  4. Dmitry_177

    Dmitry_177 New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2007
    Сообщения:
    75
    Добрые люди подсказали вот такую процедуру:

    Код (Text):
    1. procedure _DateTimeToSystemTime(DateTime: TDateTime; var SystemTime: TSystemTime);
    2. var
    3.  FT:TFileTime;
    4. begin
    5.  Int64(FT):=Round((DateTime+109205.0)*864000000000.0);
    6.  FileTimeToSystemTime(FT,SystemTime);
    7. end;
    Правильная ли она?
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Да, правильная
    TDateTime - это вещественное число типа double, представляющее число дней (суток), прошедших с 30.12.1899. Целая часть это число целых суток, а дробная - сотв-но доля суток (т.е. часы, минуты и т.д.). FILETIME это целое число Int64, представляющее собой число 100нс интервалов, прошедших с 1.01.1601. Соответственно для перевода TDateTime в FILETIME нужно
    1) прибавить к DateTime разницу дней между 1.01.1601 и 30.12.1899. Эту разницу можно вычислить заранее, задав SYSTEMTIME st = 1.01.1601 и вычислив DayDelta:=-SystemTimeToDateTime(st) = 109205
    2) перевести DateTime из дней в 100нс интервалы, умножив на константу 24*60*60*100*100*10=864000000000

    PS: Чтобы не связываться с дельфийской SystemTimeToDateTime я предлагал другую последовательность вычислений - сначала умножить, а затем прибавить константу dFT, которая получается просто путем перевода даты 30.12.1899 из st в FT через SystemTimeToFileTime. Этот перевод выглядит более прозрачным (dt=0 соответствует FT=dFT) и не требует SysUtils для вычисления константы. Ну а результат ес-но будет один и тот же
     
  6. random

    random New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2008
    Сообщения:
    38
    Делаю так потипу вот :
    Код (Text):
    1. .const
    2.             ConstSystemTimeAdd     QWORD 109205
    3.             ConstSystemTimeMul      QWORD 864000000000
    4. .date
    5. FileTime            FILETIME       <?>  
    6. SystemTime      SYSTEMTIME <?>  
    7. TDateTime                   QWORD ?
    8. .code
    9. ........
    10.                                   fld QWORD PTR TDateTime  
    11.             fild QWORD PTR ConstSystemTimeAdd
    12.             fadd
    13.             fild ConstSystemTimeMul
    14.             fmul
    15.             fstp FileTime
    16.             invoke FileTimeToSystemTime,ADDR FileTime,ADDR SystemTime
    17. ......
    получается в SystemTime чушь какая-то....Притом что TdateTime корректная - 39600, год в результате -
    дамп SYSTEMTIME
    00403090 72 42 0C 00 04 00 14 00 14 00 14 00 1E 00 rB.......
    004030A0 1B 02 
     
  7. random

    random New Member

    Публикаций:
    0
    Регистрация:
    10 янв 2008
    Сообщения:
    38
    Excuse me, разобрался... надо было вместо fstp юзать fistp