Помогите с формулой.
Формулу я не знаю. По поводу самого преобразования FileTime в SystemTime.
При всей многобитности
FileTime не учитывает добавленные (корректирующие или високосные) секунды. Следовательно, для получения в «удобном для человека» виде значения даты и времени можно просто учесть длительность лет, месяцев, дней,…
Если не стремиться к эффективности алгоритма, то можно поступить так.
1. Перебирая по очереди годы, начиная с 1601, найти полное число прошедших лет. (Вычитая по ходу из FileTime кол-во, приходящееся на очередной прошедший год.)
2. Найти количество прошедших месяцев в последнем (не завершенном) годе. (Попутно вычитая из FileTime кол-во, приходящееся на соответствующий месяц).
3. Найти день в текущем месяце (и вычесть из FileTime кол-во, приходящееся на прошедшие дни в текущем месяце).
4. Найти час, затем минуту, секунды и миллисекунды, попутно вычитая соответствующие кол-ва.
В результате FileTime будет содержать остаток.
Пример такой функции на Maple.
[Для лучшей читаемости часть исходного текста оформлено в виде двух вложенных функций:
DaysInMonth — возвращает по номеру месяца число дней в этом месяце;
IsLeap — проверка високосный ли год.
Передаваемое в качестве первого параметра значение FileTime присваивается локальной переменной
FT_с.]
Код:
> # Описание констант
# CBinMilliS = 10000, CBinS = 1000*CBinMilliS, CBinM = 60*CBinS, CBinH = 60*CBinM
# CBinD = 24*CBinH, # CnMinY = 365*CBinD, ClBinY = 366*CBinD;
> SystemTime := table(): # Определяем переменную, в которую будет возвращён результат
> macro(CnBinY = 315360000000000, ClBinY = 316224000000000, CBinD=864000000000, CBinH = 36000000000, CBinM = 600000000, CBinS = 10000000, CBinMilliS = 10000):
> FileTime2SystemTime := proc(FT, ST)::integer;
# InPut - FileTimeT
# OutPut – SystemTime
local Leap, FT_n, FT_c, IsLeap, i, DaysInMonth;
DaysInMonth:= proc(M::integer)::integer;
# InPut: M - Month
# Res: Days in Month
if (M < 1) or M > 12 then error "M < 1 or M > 12"; end if;
if member(M, {4, 6, 9, 11})
then 30
elif member(M, {1, 3, 5, 7, 8, 10, 12})
then 31
else `if`(Leap, 29, 28);
end if;
end proc;
IsLeap:= yy -> (irem(yy, 4) = 0 and irem(yy, 100)<>0) or irem(yy, 400) = 0;
ST[Year]:= 1601; ST[Month]:=1; ST[Day]:=1;
ST[Hour]:=0; ST[Minute]:=0; ST[Milliseconds]:=0;
FT_c:= FT;
# Get Year
do
if IsLeap(ST[Year]+1)
then
Leap:= true;
FT_n:= FT_c - ClBinY;
else
Leap:= false;
FT_n:= FT_c - CnBinY;
end if;
if FT_n >= 0
then
FT_c:= FT_n;
ST[Year]:= ST[Year]+1;
else
break;
end if;
end do:
# Get Month
if FT_c = 0 then return 0; end if;
FT_n:= FT_c;
for i from 1 to 12
do
FT_n:= FT_n - DaysInMonth(i)*CBinD;
if FT_n < 0
then
ST[Month]:= i;
break;
else
FT_c:= FT_n;
end if;
end do;
# Get Day
i:= iquo(FT_c, CBinD);
FT_c:= FT_c - i*CBinD;
ST[Day]:= i+1;
if FT_c = 0 then return 0; end if;
# Get Hour
ST[Day]:= iquo(FT_c, CBinH);
FT_c := FT_c - ST[Day]*CBinH;
if FT_c = 0 then return 0; end if;
# Get Minute
ST[Minute]:= iquo(FT_c, CBinM);
FT_c := FT_c - ST[Minute]*CBinM;
if FT_c = 0 then return 0; end if;
# Get Second
ST[Second]:= iquo(FT_c, CBinS);
FT_c:= FT_c - ST[Second]*CBinS;
if FT_c = 0 then return 0; end if;
# Get MilliSeconds
ST[Milliseconds]:= iquo(FT_c, CBinMilliS);
FT_c:= FT_c - ST[Milliseconds]*CBinMilliS;
return FT_c;
end proc:
Ес-но, вместо написания функции можно воспользоваться сервисом ОС: функцией
FileTimeToSystemTimeКод:
# Создание the FileTimeToSystemTime Specification из kernel32.dll.
# Поскольку (по крайней мере, в старых версиях Maple) при непосредственном обращении к функции из внешней dll
# автоматически преобразуются только структурированные типы ARRAY, string[n], complex[4], complex[8], REF(type)
# FileTime определяется как int64 [8-байтное целое со знаком]
# SystemTime - как ARRAY(1..8, integer[2]) [8 целых со знаком]
> FileTimeToSystemTime := define_external('FileTimeToSystemTime', 'FileTime'::REF(integer[8]), 'SystemTime'::REF(ARRAY(1..8, integer[2])), LIB="kernel32.dll"):
Теперь задаём переменную со значением FileTim
Код:
# Задаём значение FileTime
> FileTimeL := 1629075564: FileTimeH:=30680738:
FileTime:= FileTimeL + FileTimeH*65536*65536:
Пример вызова самодельной функции
Код:
#SystemTime была определена выше, см. фрагмент с определением FileTime2SystemTime
# Вызов самодельной функции
> FileTime2SystemTime(FileTime, SystemTime):
# Вывод результата преобразования на экран
> SystemTime[Year], SystemTime[Month], SystemTime[Day], SystemTime[Minute], SystemTime[Second], SystemTime[Milliseconds];
2018, 7, 28, 18, 39, 55, 622
Пример вызова функции kernel32.dll
Код:
# Определяем переменную ST, в которую будет возвращён результат
> ST:= Array(1..8, datatype=integer[2]):
# Вызываем функцию kernel32.dll
> FileTimeToSystemTime(FileTime, ST);
# Выводим на экран результат преобразования
> ST[1], ST[2], ST[4], ST[5], ST[6], ST[7], ST[8];
2018, 7, 28, 18, 39, 55, 622
UPD. В момент корректирующей секунды возможно расхождение результата возвращаемого самодельной функцией и
FileTimeToSystemTime. Я не знаю деталей работы
FileTimeToSystemTime. Самодельная функция не учитывает, что в минуте может быть 61 секунда. Но моменты эти достаточно редки: не чаще раза в году.