UPD: DCDateTimeUtils - better time zone support (Unix)

This commit is contained in:
Alexander Koblov 2025-10-25 14:19:46 +03:00
commit 4ff6ff14dd
2 changed files with 43 additions and 51 deletions

View file

@ -62,10 +62,17 @@ const
implementation
{$IF not DEFINED(MSWINDOWS)}
constructor TFileTimeEx.create( aSec:int64; aNanosec:int64 );
constructor TFileTimeEx.Create(aSec: Int64; aNanosec: Int64);
begin
self.sec:= aSec;
self.nanosec:= aNanosec;
Self.sec:= aSec;
Self.nanosec:= aNanosec;
if Self.nanosec < 0 then
Self.nanosec := 0
else if Self.nanosec > 999999999 then
begin
Self.nanosec := 999999999;
end;
end;
class operator TFileTimeEx.=(l,r : TFileTimeEx): Boolean;

View file

@ -4,7 +4,7 @@
Date and time functions.
Copyright (C) 2009-2012 Przemysław Nagay (cobines@gmail.com)
Copyright (C) 2017-2024 Alexander Koblov (alexx2000@mail.ru)
Copyright (C) 2017-2025 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -44,6 +44,7 @@ function DateTimeToFileTime(DateTime : TDateTime) : DCBasicTypes.TFileTime;
function DateTimeToFileTimeEx(DateTime : TDateTime) : DCBasicTypes.TFileTimeEx;
function FileTimeToWinFileTime(FileTime : DCBasicTypes.TFileTime) : TWinFileTime;
function FileTimeExToWinFileTime(FileTime : DCBasicTypes.TFileTimeEx) : TWinFileTime;
function WinFileTimeToFileTimeEx(FileTime: TWinFileTime) : DCBasicTypes.TFileTimeEx;
{en
@ -147,6 +148,8 @@ uses
const
UnixWinEpoch = TWinFileTime($019DB1DED53E8000); // Unix epoch start
MinWinUnixSec = (0 - TUnixFileTime(UnixWinEpoch div 10000000 - 1));
MaxWinUnixSec = TUnixFileTime(High(TWinFileTime) div 10000000 - 1);
const { Short names of months. }
ShortMonthNames: TMonthNameArray = ('Jan','Feb','Mar','Apr','May','Jun',
@ -283,7 +286,7 @@ begin
end;
{$ENDIF}
function FileTimeToWinFileTime(FileTime: DCBasicTypes.TFileTime): TWinFileTime;
function FileTimeToWinFileTime(FileTime: DCBasicTypes.TFileTime): TWinFileTime; inline;
{$IF DEFINED(MSWINDOWS)}
begin
Result:= TWinFileTime(FileTime)
@ -294,6 +297,23 @@ begin
end;
{$ENDIF}
function FileTimeExToWinFileTime(FileTime: DCBasicTypes.TFileTimeEx): TWinFileTime;
{$IF DEFINED(MSWINDOWS)}
begin
Result:= TWinFileTime(FileTime)
end;
{$ELSEIF DEFINED(UNIX)}
begin
if (FileTime.Sec > MaxWinUnixSec) then
Result:= High(TWinFileTime)
else if (FileTime.Sec < MinWinUnixSec) then
Result:= Low(TWinFileTime)
else begin
Result:= UnixWinEpoch + FileTime.sec * 10000000 + FileTime.nanosec div 100;
end;
end;
{$ENDIF}
function WinFileTimeToFileTimeEx(FileTime: TWinFileTime): DCBasicTypes.TFileTimeEx;
{$IF DEFINED(MSWINDOWS)}
begin
@ -358,9 +378,7 @@ function WinFileTimeToDateTime(ft : TWinFileTime) : TDateTime;
{$IF DEFINED(MSWINDOWS)}
var
lpUniversalTime, lpLocalTime: TSystemTime;
{$ENDIF}
begin
{$IF DEFINED(MSWINDOWS)}
if (Win32MajorVersion > 5) then
begin
FileTimeToSystemTime(@ft, @lpUniversalTime);
@ -368,20 +386,22 @@ begin
Result := SystemTimeToDateTime(lpLocalTime);
end
else
{$ENDIF}
begin
WinFileTimeToLocalFileTime(ft,ft);
Result := (ft / 864000000000.0) - 109205.0;
end;
end;
{$ELSE}
begin
Result := FileTimeToDateTimeEx(WinFileTimeToFileTimeEx(ft));
end;
{$ENDIF}
function DateTimeToWinFileTime(dt : TDateTime) : TWinFileTime;
{$IF DEFINED(MSWINDOWS)}
var
lpUniversalTime, lpLocalTime: TSystemTime;
{$ENDIF}
begin
{$IF DEFINED(MSWINDOWS)}
if (Win32MajorVersion > 5) then
begin
DateTimeToSystemTime(dt, lpLocalTime);
@ -389,12 +409,16 @@ begin
SystemTimeToFileTime(@lpUniversalTime, @Result);
end
else
{$ENDIF}
begin
Result := Round((Extended(dt) + 109205.0) * 864000000000.0);
WinLocalFileTimeToFileTime(Result, Result);
end;
end;
{$ELSE}
begin
Result := FileTimeExToWinFileTime(DateTimeToFileTimeEx(dt));
end;
{$ENDIF}
function DosFileTimeToDateTime(const DosTime: TDosFileTime): TDateTime;
var
@ -499,43 +523,6 @@ end;
{$IF DEFINED(UNIX)}
procedure NormalizeFileTime(var UnixTime: DCBasicTypes.TFileTimeEx);
const
NSecsPerSec = 1000000000;
begin
while UnixTime.nanosec <= -NSecsPerSec do
begin
if (UnixTime.sec = Low(Int64)) then
begin
UnixTime.nanosec:= 0;
Exit;
end;
Dec(UnixTime.sec);
Inc(UnixTime.nanosec, NSecsPerSec);
end;
while UnixTime.nanosec >= NSecsPerSec do
begin
if (UnixTime.sec = High(Int64)) then
begin
UnixTime.nanosec:= NSecsPerSec - 1;
Exit;
end;
Inc(UnixTime.sec);
Dec(UnixTime.nanosec, NSecsPerSec);
end;
if (UnixTime.nanosec < 0) then
begin
if (UnixTime.sec = Low(Int64)) then
begin
UnixTime.nanosec:= 0;
end
else begin
Dec(UnixTime.sec);
Inc(UnixTime.nanosec, NSecsPerSec);
end;
end;
end;
function UnixFileTimeToDateTime(UnixTime: TUnixFileTime) : TDateTime;
var
filetime: DCBasicTypes.TFileTimeEx;
@ -549,8 +536,6 @@ var
ATime: TTimeStruct;
Milliseconds: Word;
begin
NormalizeFileTime(UnixTime);
if (fpLocalTime(@UnixTime.sec, @ATime) = nil) then
Exit(UnixEpoch);
@ -650,7 +635,7 @@ begin
if (AUnixTime = -1) then
Result:= TFileTimeExNull
else begin
Result:= TFileTimeEx.create(AUnixTime, MilliSecond*1000*1000);
Result:= TFileTimeEx.Create(AUnixTime, MilliSecond * 1000 * 1000);
end;
end;
{$ELSE}