1019 lines
33 KiB
ObjectPascal
1019 lines
33 KiB
ObjectPascal
|
{*******************************************************}
|
|||
|
{ MiTeC Common Routines }
|
|||
|
{ Datetime routines }
|
|||
|
{ }
|
|||
|
{ }
|
|||
|
{ Copyright (c) 1997-2021 Michal Mutl }
|
|||
|
{ }
|
|||
|
{*******************************************************}
|
|||
|
|
|||
|
{$INCLUDE Compilers.inc}
|
|||
|
|
|||
|
unit MiTeC_Datetime;
|
|||
|
|
|||
|
interface
|
|||
|
|
|||
|
uses {$IFDEF RAD9PLUS}
|
|||
|
WinAPI.Windows, System.SysUtils, System.Classes;
|
|||
|
{$ELSE}
|
|||
|
Windows, SysUtils, Classes;
|
|||
|
{$ENDIF}
|
|||
|
|
|||
|
|
|||
|
{$IFDEF FPC}
|
|||
|
type
|
|||
|
TValueRelationship = -1..1;
|
|||
|
|
|||
|
const
|
|||
|
LessThanValue = Low(TValueRelationship);
|
|||
|
EqualsValue = 0;
|
|||
|
GreaterThanValue = High(TValueRelationship);
|
|||
|
{$ENDIF}
|
|||
|
|
|||
|
type
|
|||
|
TLanguage = (lngEn, lngCz);
|
|||
|
|
|||
|
TRegistryTimeZoneInfo = record
|
|||
|
Bias: Longint;
|
|||
|
StandardBias: Longint;
|
|||
|
DaylightBias: Longint;
|
|||
|
StandardDate: TSystemTime;
|
|||
|
DaylightDate: TSystemTime;
|
|||
|
end;
|
|||
|
|
|||
|
const
|
|||
|
DaysInMonths: array [1..12] of Integer =
|
|||
|
(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
|||
|
|
|||
|
MinutesPerDay = 60 * 24;
|
|||
|
SecondsPerMinute = 60;
|
|||
|
SecondsPerHour = 3600;
|
|||
|
SecondsPerDay = MinutesPerDay * 60;
|
|||
|
MsecsPerMinute = 60 * 1000;
|
|||
|
MsecsPerHour = 60 * MsecsPerMinute;
|
|||
|
DaysPerYear = 365.2422454; // Solar Year
|
|||
|
DaysPerMonth = DaysPerYear / 12;
|
|||
|
DateTimeBaseDay = -693593; // 1/1/0001
|
|||
|
EncodeDateMaxYear = 9999;
|
|||
|
SolarDifference = 1.7882454; // Difference of Julian Calendar to Solar Calendar at 1/1/10000
|
|||
|
DateTimeMaxDay = 2958466; // 12/31/EncodeDateMaxYear + 1;
|
|||
|
FileTimeBase = -109205.0;
|
|||
|
FileTimeStep: Extended = 24.0 * 60.0 * 60.0 * 1000.0 * 1000.0 * 10.0; // 100 nSek per Day
|
|||
|
|
|||
|
tzAEST = 'AUS Eastern Standard Time';
|
|||
|
tzJST = 'Tokyo Standard Time';
|
|||
|
tzCET = 'Central Europe Standard Time';
|
|||
|
tzGMT = 'GMT Standard Time';
|
|||
|
tzEST = 'Eastern Standard Time';
|
|||
|
tzPST = 'Pacific Standard Time';
|
|||
|
|
|||
|
procedure ResetMemory(out P; Size: Longint);
|
|||
|
|
|||
|
function SecondsToTime(const ASeconds: Int64): TDateTime;
|
|||
|
function UTCToDateTime(UTC: Cardinal; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
function UTCToDateTimeEx(UTC: int64; CorrectToLocal: Boolean = True): TDateTime;
|
|||
|
function Int64ToDateTime(UTC: Int64; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
function DSTDate2Date(dstDate: TSystemTime; year: word): TDateTime;
|
|||
|
function FileTimeToDateTimeStr(FileTime: TFileTime): string;
|
|||
|
function FileTimeToDateTime(FT: FILETIME; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
function ParseDate(YYYYMMDD: string): TDatetime;
|
|||
|
function EasterSunday(const Year: Word): TDateTime;
|
|||
|
function GetWorkDays(ADT: TDatetime; ACount: Integer): Integer;
|
|||
|
function DateToStrDef(ADT: TDateTime; ADef: string = ''): string;
|
|||
|
function DateTimeToStrDef(ADT: TDateTime; ADef: string = ''; AValidDateLimit: TDatetime = 0): string;
|
|||
|
function DateTimeToFileTime(dt: TDateTime): FILETIME;
|
|||
|
function IncWorkDays(ADT: TDateTime; ADays: Cardinal): TDateTime;
|
|||
|
function DecWorkDays(ADT: TDateTime; ADays: Cardinal): TDateTime;
|
|||
|
function UTCToSystemTime(UTC : TDateTime) : TDateTime;
|
|||
|
function GetDaylightBias: Integer;
|
|||
|
function GetDaylightName: string;
|
|||
|
function GetCurrentTimezoneKeyName: string;
|
|||
|
procedure GetTimeZoneList(AList: TStringList);
|
|||
|
function GetTimeZone(AKeyName: string; out AData: TTimeZoneInformation; AYear: Word = 0): string;
|
|||
|
function LocalDateTimeToTZ(AValue: TDateTime; ATZ: TTimeZoneInformation): TDateTime;
|
|||
|
|
|||
|
function GetDateTimeForBiasSystemTime(ADateTime: TSystemTime; AGivenYear: Integer): TDateTime;
|
|||
|
function GetBiasForDate(ADateTime: TDateTime): Integer;
|
|||
|
function LocalDateTimeToUTC(Local: TDateTime): TDateTime;
|
|||
|
function UTCToLocalDateTime(UTC: TDateTime): TDateTime;
|
|||
|
function RFC822DateToDateTime(RFC822DateTime: string; ADefault: TDatetime = 0): TDateTime;
|
|||
|
|
|||
|
function CompareSysTime(st1, st2: TSystemTime): integer;
|
|||
|
|
|||
|
function GreaterOrEquals(ANow,AThen: TDateTime): Boolean;
|
|||
|
function LessOrEquals(ANow,AThen: TDateTime): Boolean;
|
|||
|
function Less(ANow,AThen: TDateTime): Boolean;
|
|||
|
function Greater(ANow,AThen: TDateTime): Boolean;
|
|||
|
|
|||
|
function IsTimeInRange(ATime: TDateTime; AStartTime, AEndTime: TDateTime; AInclusive: Boolean = True): Boolean;
|
|||
|
function IsDateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
|
|||
|
function IsDateInRange(ADate: TDateTime; AStartDate, AEndDate: TDateTime; AInclusive: Boolean = True): Boolean;
|
|||
|
|
|||
|
function SecondsBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
function MinutesBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
function HoursBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
function DaysBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
function WeeksBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
|
|||
|
function FormatTicks(AValue :Int64; AWholeSecondsOnly: Boolean = True) :string;
|
|||
|
function FormatSeconds(AValue :Int64; AShort: Boolean = True) :string;
|
|||
|
function FormatMilliseconds(AValue :Int64; AWholeSecondsOnly: Boolean = True; AShort: Boolean = True) :string;
|
|||
|
|
|||
|
function XMLStrToDateTime(const AString: string): TDateTime;
|
|||
|
function XMLStrToDateTimeDef(const AString: string; const ADefDateTime: TDateTime = 0): TDateTime;
|
|||
|
function XMLTryStrToDateTime(const AString: string; var ADatetime: TDateTime): Boolean;
|
|||
|
|
|||
|
const
|
|||
|
{$IFDEF CZLNG}
|
|||
|
Zodiac :array[0..12] of record
|
|||
|
Sign :string;
|
|||
|
FromDOY, ToDOY :integer;
|
|||
|
Ruler,Traits :string;
|
|||
|
end = (
|
|||
|
(Sign:'Aries - Beran';FromDOY:81;ToDOY:111;Ruler:'Mars';Traits:'State<74>nost, r<>znost a netrp<72>livost'),
|
|||
|
(Sign:'Taurus - B<>k';FromDOY:112;ToDOY:142;Ruler:'Venu<6E>e';Traits:'Odhodlanost, v<>elost a tvrdohlavost'),
|
|||
|
(Sign:'Gemini - Bl<42><6C>enci';FromDOY:143;ToDOY:173;Ruler:'Merkur';Traits:'<27>ilost, v<>estrannost a nest<73>lost'),
|
|||
|
(Sign:'Cancer - Rak';FromDOY:174;ToDOY:204;Ruler:'Mes<65>c';Traits:'Vynal<61>zavost, citlivost a sebeovl<76>d<EFBFBD>n<EFBFBD>'),
|
|||
|
(Sign:'Leo - Lev';FromDOY:205;ToDOY:235;Ruler:'Slunce';Traits:'S<>la, tv<74>r<EFBFBD><72> talent a sebev<65>dom<6F>'),
|
|||
|
(Sign:'Virgo - Panna';FromDOY:236;ToDOY:266;Ruler:'Merkur';Traits:'Skromnost, prakti<74>nost a povznesenost'),
|
|||
|
(Sign:'Libra - V<>hy';FromDOY:267;ToDOY:296;Ruler:'Venu<6E>e';Traits:'Idealismus, romantika a lehkomyslnost'),
|
|||
|
(Sign:'Scorpio - <20>t<EFBFBD>r';FromDOY:297;ToDOY:326;Ruler:'Pluto a Mars';Traits:'V<><56>nivost, c<>lev<65>domost a <20><>rlivost'),
|
|||
|
(Sign:'Sagittarius - St<53>elec';FromDOY:327;ToDOY:356;Ruler:'Jupiter';Traits:'Optimismus, aktivita a neklid'),
|
|||
|
(Sign:'Capricorn - Kozoroh';FromDOY:357;ToDOY:366;Ruler:'Saturn';Traits:'Opatrnost, cti<74><69>dost a pesimismus'),
|
|||
|
(Sign:'Capricorn - Kozoroh';FromDOY:1;ToDOY:20;Ruler:'Saturn';Traits:'Opatrnost, cti<74><69>dost a pesimismus'),
|
|||
|
(Sign:'Aquarius - Vodn<64><6E>';FromDOY:21;ToDOY:50;Ruler:'Uran a Saturn';Traits:'Nez<65>vislost, sv<73>r<EFBFBD>znost a tvrdohlavost'),
|
|||
|
(Sign:'Pisces - Ryby';FromDOY:51;ToDOY:80;Ruler:'Neptun a Jupiter';Traits:'Starostlivost, intuitivnost a neur<75>itost')
|
|||
|
);
|
|||
|
{$ENDIF}
|
|||
|
|
|||
|
ZodiacEn :array[0..12] of record
|
|||
|
Sign :string;
|
|||
|
FromDOY, ToDOY :integer;
|
|||
|
Ruler,Traits :string;
|
|||
|
end = (
|
|||
|
(Sign:'Aries';FromDOY:81;ToDOY:111;Ruler:'Mars';Traits:'Bravery, energy and impatience '),
|
|||
|
(Sign:'Taurus';FromDOY:112;ToDOY:142;Ruler:'Venus';Traits:'Resoluteness, warmth of feeling and stubborness'),
|
|||
|
(Sign:'Gemini';FromDOY:143;ToDOY:173;Ruler:'Mercury';Traits:'Agility, versatility and inconstancy'),
|
|||
|
(Sign:'Cancer';FromDOY:174;ToDOY:204;Ruler:'Moon';Traits:'Inventibility, sensitivity and self-possession'),
|
|||
|
(Sign:'Leo';FromDOY:205;ToDOY:235;Ruler:'Sun';Traits:'Strength, creativity and self-confidence'),
|
|||
|
(Sign:'Virgo';FromDOY:236;ToDOY:266;Ruler:'Mercury';Traits:'Modesty, practicality and loftiness'),
|
|||
|
(Sign:'Libra';FromDOY:267;ToDOY:296;Ruler:'Venus';Traits:'Idealist, romantic and improvidence'),
|
|||
|
(Sign:'Scorpio';FromDOY:297;ToDOY:326;Ruler:'Pluto and Mars';Traits:'Passion, resolution and jealousy'),
|
|||
|
(Sign:'Sagittarius';FromDOY:327;ToDOY:356;Ruler:'Jupiter';Traits:'Optimistic, active and unquiet'),
|
|||
|
(Sign:'Capricorn';FromDOY:357;ToDOY:366;Ruler:'Saturn';Traits:'Prudent, ambitiousness and pesimistic'),
|
|||
|
(Sign:'Capricorn';FromDOY:1;ToDOY:20;Ruler:'Saturn';Traits:'Prudent, ambitiousness and pesimistic'),
|
|||
|
(Sign:'Aquarius';FromDOY:21;ToDOY:50;Ruler:'Uran and Saturn';Traits:'Independent, individual and stubborn'),
|
|||
|
(Sign:'Pisces';FromDOY:51;ToDOY:80;Ruler:'Neptun and Jupiter';Traits:'Careful, intuitive and casual')
|
|||
|
);
|
|||
|
|
|||
|
type
|
|||
|
TTzSpecificLocalTimeToSystemTime = function (lpTimeZoneInformation: PTimeZoneInformation; var pLocalTime, pUniversalTime: TSystemTime): BOOL; stdcall;
|
|||
|
TSystemTimeToTzSpecificLocalTime = function (lpTimeZoneInformation: PTimeZoneInformation; var pUniversalTime, pLocalTime: TSystemTime): BOOL; stdcall;
|
|||
|
var
|
|||
|
TzSpecificLocalTimeToSystemTime: TTzSpecificLocalTimeToSystemTime = nil;
|
|||
|
SystemTimeToTzSpecificLocalTime: TSystemTimeToTzSpecificLocalTime = nil;
|
|||
|
|
|||
|
|
|||
|
implementation
|
|||
|
|
|||
|
uses {$IFDEF RAD9PLUS}
|
|||
|
System.Types, System.DateUtils, System.Timespan, System.Win.Registry
|
|||
|
{$ELSE}
|
|||
|
Types, DateUtils, Registry
|
|||
|
{$ENDIF}
|
|||
|
;
|
|||
|
|
|||
|
procedure ResetMemory(out P; Size: Longint);
|
|||
|
begin
|
|||
|
if Size>0 then begin
|
|||
|
Byte(P):=0;
|
|||
|
FillChar(P,Size,0);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function UTCToSystemTime(UTC : TDateTime) : TDateTime;
|
|||
|
var
|
|||
|
TimeZoneInf: _TIME_ZONE_INFORMATION;
|
|||
|
UTCTime,LocalTime: TSystemTime;
|
|||
|
begin
|
|||
|
if GetTimeZoneInformation(TimeZoneInf)<$FFFFFFFF then begin
|
|||
|
DatetimetoSystemTime(UTC,UTCTime);
|
|||
|
if SystemTimeToTzSpecificLocalTime(@TimeZoneInf,UTCTime,LocalTime) then begin
|
|||
|
result:=SystemTimeToDateTime(LocalTime);
|
|||
|
end else
|
|||
|
result:=UTC;
|
|||
|
end else
|
|||
|
result:=UTC;
|
|||
|
end;
|
|||
|
|
|||
|
function GetDateTimeForBiasSystemTime(ADateTime: TSystemTime; AGivenYear: Integer): TDateTime;
|
|||
|
var
|
|||
|
Year, Month, Day: Word;
|
|||
|
Hour, Minute, Second, MilliSecond: Word;
|
|||
|
begin
|
|||
|
with ADateTime do begin
|
|||
|
wYear:=AGivenYear;
|
|||
|
while not TryEncodeDayOfWeekInMonth(wYear,wMonth,wDay,wDayOfWeek,Result) do
|
|||
|
Dec(wDay);
|
|||
|
DecodeDateTime(Result,Year,Month,Day,Hour,Minute,Second,MilliSecond);
|
|||
|
Result:=EncodeDateTime(Year,Month,Day,wHour,wMinute,wSecond,wMilliseconds);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function GetBiasForDate(ADateTime: TDateTime): Integer;
|
|||
|
var
|
|||
|
tzi: TIME_ZONE_INFORMATION;
|
|||
|
st,dt: TDateTime;
|
|||
|
s: string;
|
|||
|
begin
|
|||
|
s:=GetCurrentTimezoneKeyName;
|
|||
|
GetTimeZone(s,tzi,YearOf(ADatetime));
|
|||
|
st:=GetDateTimeForBiasSystemTime(tzi.StandardDate,YearOf(ADateTime));
|
|||
|
dt:=GetDateTimeForBiasSystemTime(tzi.DaylightDate,YearOf(ADateTime));
|
|||
|
if tzi.StandardDate.wMonth=0 then
|
|||
|
Result:=tzi.Bias
|
|||
|
else if tzi.StandardDate.wMonth>tzi.DaylightDate.wMonth then
|
|||
|
if (ADateTime<st) and (ADateTime >= dt) then
|
|||
|
Result:=tzi.Bias+tzi.DaylightBias
|
|||
|
else
|
|||
|
Result:=tzi.Bias+tzi.StandardBias
|
|||
|
else if (ADateTime >= st) and (ADateTime<dt) then
|
|||
|
Result:=tzi.Bias+tzi.StandardBias
|
|||
|
else
|
|||
|
Result:=tzi.Bias+tzi.DaylightBias;
|
|||
|
end;
|
|||
|
|
|||
|
function UTCToLocalDateTime(UTC: TDateTime): TDateTime;
|
|||
|
var
|
|||
|
sUTC,sLocal: TSystemTime;
|
|||
|
begin
|
|||
|
DateTimeToSystemTime(UTC,sUTC);
|
|||
|
if SystemTimeToTzSpecificLocalTime(nil,sUTC,sLocal) then
|
|||
|
Result:=SystemTimeToDateTime(sLocal)
|
|||
|
else
|
|||
|
Result:=IncMinute(UTC,-GetBiasForDate(UTC));
|
|||
|
end;
|
|||
|
|
|||
|
function LocalDateTimeToUTC(Local: TDateTime): TDateTime;
|
|||
|
var
|
|||
|
sUTC,sLocal: TSystemTime;
|
|||
|
begin
|
|||
|
Result:=0;
|
|||
|
if Assigned(TzSpecificLocalTimeToSystemTime) then begin
|
|||
|
DateTimeToSystemTime(Local,sLocal);
|
|||
|
if TzSpecificLocalTimeToSystemTime(nil,sLocal,sUTC) then
|
|||
|
Result:=SystemTimeToDateTime(sUTC);
|
|||
|
end;
|
|||
|
if Result=0 then
|
|||
|
Result:=IncMinute(Local,GetBiasForDate(Local));
|
|||
|
end;
|
|||
|
|
|||
|
function CompareSysTime(st1, st2: TSystemTime): integer;
|
|||
|
begin
|
|||
|
if st1.wYear<st2.wYear then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wYear>st2.wYear then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wMonth<st2.wMonth then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wMonth>st2.wMonth then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wDayOfWeek<st2.wDayOfWeek then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wDayOfWeek>st2.wDayOfWeek then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wDay<st2.wDay then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wDay>st2.wDay then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wHour<st2.wHour then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wHour>st2.wHour then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wMinute<st2.wMinute then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wMinute>st2.wMinute then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wSecond<st2.wSecond then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wSecond>st2.wSecond then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
if st1.wMilliseconds<st2.wMilliseconds then
|
|||
|
Result:=-1
|
|||
|
else
|
|||
|
if st1.wMilliseconds>st2.wMilliseconds then
|
|||
|
Result:=1
|
|||
|
else
|
|||
|
Result:=0;
|
|||
|
end;
|
|||
|
|
|||
|
function GetDaylightBias: Integer;
|
|||
|
var
|
|||
|
TimeZoneInfo: TTimeZoneInformation;
|
|||
|
begin
|
|||
|
FillChar(TimeZoneInfo, SizeOf(TimeZoneInfo), #0);
|
|||
|
GetTimeZoneInformation(TimeZoneInfo);
|
|||
|
Result:=TimeZoneInfo.DaylightBias;
|
|||
|
end;
|
|||
|
|
|||
|
function GetDaylightName: string;
|
|||
|
var
|
|||
|
TimeZoneInfo: TTimeZoneInformation;
|
|||
|
begin
|
|||
|
FillChar(TimeZoneInfo, SizeOf(TimeZoneInfo), #0);
|
|||
|
GetTimeZoneInformation(TimeZoneInfo);
|
|||
|
Result:=TimeZoneInfo.DaylightName;
|
|||
|
end;
|
|||
|
|
|||
|
function GetCurrentTimezoneKeyName: string;
|
|||
|
const
|
|||
|
rkTZKN = {HKEY_LOCAL_MACHINE\}'SYSTEM\CurrentControlSet\Control\TimeZoneInformation';
|
|||
|
rvTZKN = 'TimeZoneKeyName';
|
|||
|
begin
|
|||
|
Result:='';
|
|||
|
with TRegistry.Create do begin
|
|||
|
Rootkey:=HKEY_LOCAL_MACHINE;
|
|||
|
if OpenKeyReadOnly(rkTZKN) then begin
|
|||
|
if ValueExists(rvTZKN) then
|
|||
|
Result:=ReadString(rvTZKN);
|
|||
|
CloseKey;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
procedure GetTimeZoneList(AList: TStringList);
|
|||
|
var
|
|||
|
i: Integer;
|
|||
|
begin
|
|||
|
AList.Clear;
|
|||
|
with TRegistry.Create do
|
|||
|
try
|
|||
|
Rootkey:=HKEY_LOCAL_MACHINE;
|
|||
|
if not OpenKeyReadOnly('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\') then
|
|||
|
Exit;
|
|||
|
GetKeyNames(AList);
|
|||
|
CloseKey;
|
|||
|
for i:=0 to AList.Count-1 do
|
|||
|
if OpenKeyReadOnly(Format('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\%s',[AList[i]])) then begin
|
|||
|
AList[i]:=AList[i]+'='+ReadString('Display');
|
|||
|
CloseKey;
|
|||
|
end;
|
|||
|
finally
|
|||
|
Free;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function GetTimeZone(AKeyName: string; out AData: TTimeZoneInformation; AYear: Word = 0): string;
|
|||
|
var
|
|||
|
s: string;
|
|||
|
rtz: TRegistryTimeZoneInfo;
|
|||
|
begin
|
|||
|
Result:='';
|
|||
|
ResetMemory(AData,SizeOf(AData));
|
|||
|
if AYear=0 then
|
|||
|
AYear:=YearOf(Date);
|
|||
|
with TRegistry.Create do
|
|||
|
try
|
|||
|
Rootkey:=HKEY_LOCAL_MACHINE;
|
|||
|
if not OpenKeyReadOnly(Format('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\%s',[AKeyName])) then
|
|||
|
Exit;
|
|||
|
Result:=ReadString('Display');
|
|||
|
s:=ReadString('Std');
|
|||
|
StringToWideChar(s,@(AData.StandardName),Length(s)+1);
|
|||
|
s:=ReadString('Dlt');
|
|||
|
StringToWideChar(s,@(AData.DaylightName),Length(s)+1);
|
|||
|
ReadBinaryData('TZI',rtz,SizeOf(rtz));
|
|||
|
AData.Bias:=rtz.Bias;
|
|||
|
AData.StandardDate:=rtz.StandardDate;
|
|||
|
AData.StandardBias:=rtz.StandardBias;
|
|||
|
AData.DaylightDate:=rtz.DaylightDate;
|
|||
|
AData.DaylightBias:=rtz.DaylightBias;
|
|||
|
CloseKey;
|
|||
|
if not OpenKeyReadOnly(Format('SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\%s\Dynamic DST',[AKeyName])) then
|
|||
|
Exit;
|
|||
|
if not ValueExists(IntToStr(AYear)) then
|
|||
|
Exit;
|
|||
|
ReadBinaryData(IntToStr(AYear),rtz,SizeOf(rtz));
|
|||
|
AData.Bias:=rtz.Bias;
|
|||
|
AData.StandardDate:=rtz.StandardDate;
|
|||
|
AData.StandardBias:=rtz.StandardBias;
|
|||
|
AData.DaylightDate:=rtz.DaylightDate;
|
|||
|
AData.DaylightBias:=rtz.DaylightBias;
|
|||
|
CloseKey;
|
|||
|
finally
|
|||
|
Free;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function LocalDateTimeToTZ(AValue: TDateTime; ATZ: TTimeZoneInformation): TDateTime;
|
|||
|
var
|
|||
|
sLocal,sUTC: TSystemTime;
|
|||
|
begin
|
|||
|
Result:=0;
|
|||
|
AValue:=LocalDatetimeToUTC(AValue);
|
|||
|
if Assigned(SystemTimeToTzSpecificLocalTime) then begin
|
|||
|
DateTimeToSystemTime(AValue,sUTC);
|
|||
|
if SystemTimeToTzSpecificLocalTime(@ATZ,sUTC,sLocal) then
|
|||
|
Result:=SystemTimeToDateTime(sLocal);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function IncWorkDays(ADT: TDateTime; ADays: Cardinal): TDateTime;
|
|||
|
var
|
|||
|
i: Cardinal;
|
|||
|
begin
|
|||
|
Result:=ADT;
|
|||
|
i:=0;
|
|||
|
while i<ADays do begin
|
|||
|
Result:=Result+1;
|
|||
|
if DayOfWeek(Result) in [2..6] then
|
|||
|
Inc(i);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function DecWorkDays(ADT: TDateTime; ADays: Cardinal): TDateTime;
|
|||
|
var
|
|||
|
i: Cardinal;
|
|||
|
begin
|
|||
|
Result:=ADT;
|
|||
|
i:=0;
|
|||
|
while i<ADays do begin
|
|||
|
Result:=Result-1;
|
|||
|
if DayOfWeek(Result) in [2..6] then
|
|||
|
Inc(i);
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function FileTimeToDateTimeStr(FileTime: TFileTime): string;
|
|||
|
begin
|
|||
|
Result:=DateTimeToStr(FileTimeToDateTime(FileTime));
|
|||
|
end;
|
|||
|
|
|||
|
function FileTimeToDateTime(FT: FILETIME; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
var
|
|||
|
SysFTime: TSystemTime;
|
|||
|
begin
|
|||
|
try
|
|||
|
FileTimeToSystemTime(FT,SysFTime);
|
|||
|
Result:=SystemTimeTodateTime(SysFTime);
|
|||
|
if ConvertTimeToLocal then
|
|||
|
Result:=UTCToSystemTime(Result);
|
|||
|
except
|
|||
|
Result:=0;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function ParseDate(YYYYMMDD: string): TDatetime;
|
|||
|
var
|
|||
|
y,m,d: Word;
|
|||
|
begin
|
|||
|
y:=StrToInt(Copy(YYYYMMDD,1,4));
|
|||
|
m:=StrToInt(Copy(YYYYMMDD,5,2));
|
|||
|
d:=StrToInt(Copy(YYYYMMDD,7,2));
|
|||
|
Result:=EncodeDate(y,m,d);
|
|||
|
end;
|
|||
|
|
|||
|
function UTCToDateTime(UTC: Cardinal; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
var
|
|||
|
d: LARGE_INTEGER;
|
|||
|
ft: FILETIME;
|
|||
|
begin
|
|||
|
d.QuadPart:=365*24*60*60;
|
|||
|
d.QuadPart:=((1970-1601)*d.QuadPart+UTC+89*24*60*60+3600)*10000000;
|
|||
|
ft.dwLowDateTime:=d.LowPart;
|
|||
|
ft.dwHighDateTime:=d.HighPart;
|
|||
|
Result:=FiletimeToDateTime(ft,ConvertTimeToLocal);
|
|||
|
end;
|
|||
|
|
|||
|
function UTCToDateTimeEx(UTC: int64; CorrectToLocal: Boolean = True): TDateTime;
|
|||
|
var
|
|||
|
d: LARGE_INTEGER;
|
|||
|
ft: FILETIME;
|
|||
|
begin
|
|||
|
d.QuadPart:=365*24*60*60;
|
|||
|
d.QuadPart:=((1970-1601)*d.QuadPart+89*24*60*60)*10000000+UTC*10;
|
|||
|
ft.dwLowDateTime:=d.LowPart;
|
|||
|
ft.dwHighDateTime:=d.HighPart;
|
|||
|
try
|
|||
|
Result:=FiletimeToDateTime(ft,CorrectToLocal);
|
|||
|
if YearOf(Result)>YearOf(Now) then
|
|||
|
Result:=IncYear(Result,-1970+1601);
|
|||
|
except
|
|||
|
Result:=0;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
|
|||
|
function Int64ToDateTime(UTC: Int64; ConvertTimeToLocal: Boolean = False): TDateTime;
|
|||
|
var
|
|||
|
d: LARGE_INTEGER;
|
|||
|
ft: FILETIME;
|
|||
|
begin
|
|||
|
d.QuadPart:=UTC;
|
|||
|
ft.dwLowDateTime:=d.LowPart;
|
|||
|
ft.dwHighDateTime:=d.HighPart;
|
|||
|
Result:=FiletimeToDateTime(ft);
|
|||
|
if ConvertTimeToLocal then
|
|||
|
Result:=UTCToLocalDateTime(Result);
|
|||
|
end;
|
|||
|
|
|||
|
function DSTDate2Date(dstDate: TSystemTime; year: word): TDateTime;
|
|||
|
begin
|
|||
|
Result:=0;
|
|||
|
if dstDate.wMonth=0 then
|
|||
|
Exit;
|
|||
|
repeat
|
|||
|
if dstDate.wYear=0 then
|
|||
|
try
|
|||
|
Result:=EncodeDayOfWeekInMonth(year,dstDate.wMonth,dstDate.wDay,dstDate.wDayOfWeek)+
|
|||
|
EncodeTime(dstDate.wHour,dstDate.wMinute,dstDate.wSecond,dstDate.wMilliseconds);
|
|||
|
except
|
|||
|
Dec(dstDate.wDay);
|
|||
|
end
|
|||
|
else
|
|||
|
Result:=SystemTimeToDateTime(dstDate);
|
|||
|
until Result>0;
|
|||
|
end;
|
|||
|
|
|||
|
function EasterSunday(const Year: Word): TDateTime;
|
|||
|
var
|
|||
|
C, I, J, H, G, L: Integer;
|
|||
|
D, M: Word;
|
|||
|
begin
|
|||
|
G:=Year mod 19;
|
|||
|
C:=Year div 100;
|
|||
|
H:=(C-C div 4-(8*C+13) div 25+19*G+15) mod 30;
|
|||
|
I:=H-(H div 28)*(1-(H div 28)*(29 div (H+1))*((21-G) div 11));
|
|||
|
J:=(Year+Year div 4+I+2-C+C div 4) mod 7;
|
|||
|
L:=I-J;
|
|||
|
M:=3+(L+40) div 44;
|
|||
|
D:=L+28-31*(M div 4);
|
|||
|
Result:=EncodeDate(Year,M,D);
|
|||
|
end;
|
|||
|
|
|||
|
function GetWorkDays(ADT: TDatetime; ACount: Integer): Integer;
|
|||
|
var
|
|||
|
sd: TDateTime;
|
|||
|
begin
|
|||
|
Result:=0;
|
|||
|
sd:=ADT;
|
|||
|
repeat
|
|||
|
if DayOfWeek(ADT) in [2..6] then
|
|||
|
Inc(Result);
|
|||
|
if ACount<0 then
|
|||
|
ADT:=ADT-1
|
|||
|
else
|
|||
|
ADT:=ADT+1;
|
|||
|
until Result=abs(ACount);
|
|||
|
Result:=Round(abs(int(ADT)-int(sd)));
|
|||
|
end;
|
|||
|
|
|||
|
function DateToStrDef(ADT: TDateTime; ADef: string = ''): string;
|
|||
|
begin
|
|||
|
if ADT<=0 then
|
|||
|
Result:=ADef
|
|||
|
else
|
|||
|
Result:=DateToStr(ADT);
|
|||
|
end;
|
|||
|
|
|||
|
function DateTimeToStrDef(ADT: TDateTime; ADef: string = ''; AValidDateLimit: TDatetime = 0): string;
|
|||
|
begin
|
|||
|
if ADT<=AValidDateLimit then
|
|||
|
Result:=ADef
|
|||
|
else
|
|||
|
Result:=DateTimeToStr(ADT);
|
|||
|
end;
|
|||
|
|
|||
|
function DateTimeToFileTime(dt: TDateTime): FILETIME;
|
|||
|
var
|
|||
|
st: SYSTEMTIME;
|
|||
|
begin
|
|||
|
DateTimeToSystemTime(dt,st);
|
|||
|
SystemTimeToFileTime(st,Result);
|
|||
|
end;
|
|||
|
|
|||
|
function RFC822DateToDateTime(RFC822DateTime: string; ADefault: TDatetime = 0): TDateTime;
|
|||
|
const
|
|||
|
RFC822ConvertDateTimeConvertError = '"%s" is not valid RFC822 datetime';
|
|||
|
|
|||
|
DayArray: array[0..6] of string = ('Mon','Tue','Wed','Thu','Fri','Sat','Sun');
|
|||
|
MonthArray: array[0..11] of string = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
|
|||
|
ZoneArray: array[0..14] of string = ('UT','GMT','EST','EDT','CST','CDT','MST','MDT','PST','PDT','Z','A','M','N','Y');
|
|||
|
var
|
|||
|
lString: string;
|
|||
|
lDayName: string;
|
|||
|
lMonthName: string;
|
|||
|
I: Integer;
|
|||
|
lProceed: Boolean;
|
|||
|
lDay: Integer;
|
|||
|
lMonth: Integer;
|
|||
|
lYear: Integer;
|
|||
|
lTmp: Integer;
|
|||
|
lHours: Integer;
|
|||
|
lMinutes: Integer;
|
|||
|
lSeconds: Integer;
|
|||
|
lTimeZone: TTimeZoneInformation;
|
|||
|
lLocalStringTime: TDateTime;
|
|||
|
lTimeZoneName: string;
|
|||
|
lTimeZoneIndex: Integer;
|
|||
|
lLocalDiffHours: Integer;
|
|||
|
lLocalDiffMinutes: Integer;
|
|||
|
lAddLocalDiff: Boolean;
|
|||
|
begin
|
|||
|
RFC822DateTime:=StringReplace(RFC822DateTime,'GTM','GMT',[rfIgnorecase]);
|
|||
|
lTimeZoneIndex:=-1;
|
|||
|
lAddLocalDiff:=False;
|
|||
|
lMonth:=-1;
|
|||
|
lTmp:=0;
|
|||
|
lString:=RFC822DateTime;
|
|||
|
lProceed:=False;
|
|||
|
if Pos(',',lString)>0 then
|
|||
|
begin
|
|||
|
lDayName:=Copy(lString,1,3);
|
|||
|
for i:=0 to Length(DayArray)-1 do begin
|
|||
|
if lDayName=DayArray[i] then begin
|
|||
|
lProceed:=True;
|
|||
|
Break;
|
|||
|
end;
|
|||
|
end;
|
|||
|
Delete(lString,1,5);
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
if not TryStrToInt(Copy(lString,1,2), lDay) then
|
|||
|
lProceed:=False;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
lMonthName:=Copy(lString,4,3);
|
|||
|
lProceed:=False;
|
|||
|
for i:=0 to Length(MonthArray)-1 do begin
|
|||
|
if lMonthName=MonthArray[I] then begin
|
|||
|
lProceed:=True;
|
|||
|
lMonth:=Succ(I);
|
|||
|
Break;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
if not TryStrToInt(Copy(lString,8,4), lYear) then begin
|
|||
|
// might be only 2 characters long
|
|||
|
if not TryStrToInt(Copy(lString,8,2), lYear) then
|
|||
|
lProceed:=False
|
|||
|
else
|
|||
|
lTmp:=2;
|
|||
|
end else
|
|||
|
lTmp:=4;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
lTmp:=8+Succ(lTmp);
|
|||
|
if not TryStrToInt(Copy(lString,lTmp,2),lHours) then
|
|||
|
lProceed:=False;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
Inc(lTmp,3);
|
|||
|
if not TryStrToInt(Copy(lString, lTmp, 2), lMinutes) then
|
|||
|
lProceed:=False;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
Inc(lTmp,3);
|
|||
|
if not TryStrToInt(Copy(lString,lTmp,2),lSeconds) then
|
|||
|
// Just proceed, seconds are optional.
|
|||
|
lSeconds:=0;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
Inc(lTmp,3); // Start of TimeZone
|
|||
|
lTimeZoneName:=Copy(lString,lTmp,3); // e.g. "GMT"
|
|||
|
if (Copy(lTimeZoneName,1,1)='-') or
|
|||
|
(Copy(lTimeZoneName,1,1)='+') or
|
|||
|
(Length(lTimeZoneName) = 0) then
|
|||
|
// Assume UTC
|
|||
|
lTimeZoneIndex:=0
|
|||
|
else begin
|
|||
|
lProceed:=False;
|
|||
|
if Length(lTimeZoneName)=3 then begin
|
|||
|
for i:=0 to Length(ZoneArray)-1 do begin
|
|||
|
if ZoneArray[i]=lTimeZoneName then begin
|
|||
|
lTimeZoneIndex:=i;
|
|||
|
lProceed:=True;
|
|||
|
Break;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if not lProceed then begin
|
|||
|
// Try the ones with only 2 letters
|
|||
|
for i:=0 to Length(ZoneArray)-1 do begin
|
|||
|
if ZoneArray[i]=Copy(lTimeZoneName,1,2) then begin
|
|||
|
lTimeZoneIndex:=i;
|
|||
|
lProceed:=True;
|
|||
|
Break;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if not lProceed then begin
|
|||
|
// Try the ones with only 1 letter
|
|||
|
for i:=0 to Length(ZoneArray)-1 do begin
|
|||
|
if ZoneArray[i]=lTimeZoneName[1] then begin
|
|||
|
lTimeZoneIndex:=i;
|
|||
|
lProceed:=True;
|
|||
|
Break;
|
|||
|
end;
|
|||
|
end;
|
|||
|
end;
|
|||
|
Inc(lTmp,Length(ZoneArray[lTimeZoneIndex])); // Begin of+/ -
|
|||
|
end;
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
// Get local differential hours
|
|||
|
lAddLocalDiff:=Copy(lString,lTmp,1)='+';
|
|||
|
Inc(lTmp,1); // Begin of local diff hours
|
|||
|
if lTmp<Length(lString) then begin
|
|||
|
// Has local differential hours
|
|||
|
if not TryStrToInt(Copy(lString,lTmp,2),lLocalDiffHours) then
|
|||
|
lProceed:=False
|
|||
|
end else begin
|
|||
|
// No local diff time
|
|||
|
lLocalDiffHours:=-1;
|
|||
|
lLocalDiffMinutes:=-1;
|
|||
|
end;
|
|||
|
end;
|
|||
|
if (lProceed) and (lLocalDiffHours<>-1) then begin
|
|||
|
// Get local differential minutes
|
|||
|
Inc(lTmp,2); // Begin of local diff minutes
|
|||
|
if not TryStrToInt(Copy(lString,lTmp,2),lLocalDiffMinutes) then
|
|||
|
lProceed:=False
|
|||
|
end;
|
|||
|
if lProceed then begin
|
|||
|
// Create current local time of string as TDateTime
|
|||
|
lLocalStringTime:=EncodeDate(lYear,lMonth,lDay)+EncodeTime(lHours,lMinutes,lSeconds,0);
|
|||
|
case lTimeZoneIndex of
|
|||
|
0,1,10: lTmp:=0; // UT, GMT, Z
|
|||
|
2: lTmp:=5; // EST,-5
|
|||
|
3: lTmp:=4; // EDT,-4
|
|||
|
4: lTmp:=6; // CST,-6
|
|||
|
5: lTmp:=5; // CDT,-5
|
|||
|
6: lTmp:=7; // MST,-7
|
|||
|
7: lTmp:=6; // MDT,-6
|
|||
|
8: lTmp:=8; // PST,-8
|
|||
|
9: lTmp:=7; // PDT,-7
|
|||
|
11: lTmp:=1; // A,-1
|
|||
|
12: lTmp:=12; // M,-12
|
|||
|
13: lTmp:=-1; // N,+1
|
|||
|
14: lTmp:=-12; // Y,+12
|
|||
|
end;
|
|||
|
// Calculate the UTC-Time of the given string
|
|||
|
lLocalStringTime:=lLocalStringTime+(lTmp*OneHour);
|
|||
|
if lLocalDiffHours<>-1 then begin
|
|||
|
if lAddLocalDiff then
|
|||
|
lLocalStringTime:=lLocalStringTime-(lLocalDiffHours*OneHour)-(lLocalDiffMinutes*OneMinute)
|
|||
|
else
|
|||
|
lLocalStringTime:=lLocalStringTime+(lLocalDiffHours*OneHour)+(lLocalDiffMinutes*OneMinute);
|
|||
|
end;
|
|||
|
// Now calculate the time in local format
|
|||
|
if GetTimeZoneInformation(lTimeZone)=TIME_ZONE_ID_DAYLIGHT then begin
|
|||
|
Result:=lLocalStringTime-((lTimeZone.Bias+lTimeZone.DaylightBias)*OneMinute);
|
|||
|
end else begin
|
|||
|
Result:=lLocalStringTime-((lTimeZone.Bias+lTimeZone.StandardBias)*OneMinute);
|
|||
|
end;
|
|||
|
end else begin
|
|||
|
//raise EConvertError.Create(Format(RFC822ConvertDateTimeConvertError,[RFC822DateTime]));
|
|||
|
Result:=ADefault;
|
|||
|
end;
|
|||
|
end;
|
|||
|
|
|||
|
function GreaterOrEquals(ANow,AThen: TDateTime): Boolean;
|
|||
|
begin
|
|||
|
Result:=(CompareDateTime(ANow,AThen)<>LessThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function LessOrEquals(ANow,AThen: TDateTime): Boolean;
|
|||
|
begin
|
|||
|
Result:=(CompareDateTime(ANow,AThen)<>GreaterThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function Less(ANow,AThen: TDateTime): Boolean;
|
|||
|
begin
|
|||
|
Result:=(CompareDateTime(ANow,AThen)=LessThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function Greater(ANow,AThen: TDateTime): Boolean;
|
|||
|
begin
|
|||
|
Result:=(CompareDateTime(ANow,AThen)=GreaterThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function IsTimeInRange(ATime: TDateTime; AStartTime, AEndTime: TDateTime; AInclusive: Boolean = True): Boolean;
|
|||
|
var
|
|||
|
LTime, LStartTime, LEndTime: TDateTime;
|
|||
|
begin
|
|||
|
LTime:=TimeOf(ATime);
|
|||
|
LStartTime:=TimeOf(AStartTime);
|
|||
|
LEndTime:=TimeOF(AEndTime);
|
|||
|
|
|||
|
if CompareTime(LEndTime,LStartTime)=LessThanValue then
|
|||
|
if AInclusive then
|
|||
|
Result:=(CompareTime(LStartTime,LTime)<>GreaterThanValue) or (CompareTime(LTime,LEndTime)<>GreaterThanValue)
|
|||
|
else
|
|||
|
Result:=(CompareTime(LStartTime,LTime)=LessThanValue) or (CompareTime(LTime,LEndTime)=LessThanValue)
|
|||
|
else
|
|||
|
if AInclusive then
|
|||
|
Result:=(CompareTime(LStartTime,LTime)<>GreaterThanValue) and (CompareTime(LTime,LEndTime)<>GreaterThanValue)
|
|||
|
else
|
|||
|
Result:=(CompareTime(LStartTime,LTime)=LessThanValue) and (CompareTime(LTime,LEndTime)=LessThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function IsDateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
|
|||
|
begin
|
|||
|
if aInclusive then
|
|||
|
Result:=(CompareDateTime(AStartDateTime,ADateTime)<>GreaterThanValue) and (CompareDateTime(ADateTime,AEndDateTime)<>GreaterThanValue)
|
|||
|
else
|
|||
|
Result:=(CompareDateTime(AStartDateTime,ADateTime)=LessThanValue) and (CompareDateTime(ADateTime,AEndDateTime)=LessThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function IsDateInRange(ADate: TDateTime; AStartDate, AEndDate: TDateTime; AInclusive: Boolean = True): Boolean;
|
|||
|
begin
|
|||
|
if AInclusive then
|
|||
|
Result:=(CompareDate(DateOf(AStartDate),DateOf(ADate))<>GreaterThanValue) and (CompareDate(DateOf(ADate),DateOf(AEndDate))<>GreaterThanValue)
|
|||
|
else
|
|||
|
Result:=(CompareDate(DateOf(AStartDate),DateOf(ADate))=LessThanValue) and (CompareDate(DateOf(ADate),DateOf(AEndDate))=LessThanValue);
|
|||
|
end;
|
|||
|
|
|||
|
function SecondsBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
begin
|
|||
|
Result:=CompareDatetime(AThen,ANow)*SecondsBetween(ANow,AThen);
|
|||
|
end;
|
|||
|
|
|||
|
function MinutesBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
begin
|
|||
|
Result:=CompareDatetime(AThen,ANow)*MinutesBetween(ANow,AThen);
|
|||
|
end;
|
|||
|
|
|||
|
function HoursBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
begin
|
|||
|
Result:=CompareDatetime(AThen,ANow)*HoursBetween(ANow,AThen);
|
|||
|
end;
|
|||
|
|
|||
|
function DaysBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
begin
|
|||
|
Result:=CompareDatetime(AThen,ANow)*DaysBetween(ANow,AThen);
|
|||
|
end;
|
|||
|
|
|||
|
function WeeksBetweenSgn(ANow,AThen: TDateTime): Integer;
|
|||
|
begin
|
|||
|
Result:=CompareDatetime(AThen,ANow)*WeeksBetween(ANow,AThen);
|
|||
|
end;
|
|||
|
|
|||
|
function SecondsToTime(const ASeconds: Int64): TDatetime;
|
|||
|
const
|
|||
|
SecPerDay = 86400;
|
|||
|
SecPerHour = 3600;
|
|||
|
SecPerMinute = 60;
|
|||
|
var
|
|||
|
ms, ss, mm, hh, dd: Cardinal;
|
|||
|
begin
|
|||
|
dd:=ASeconds div SecPerDay;
|
|||
|
hh:=(ASeconds mod SecPerDay) div SecPerHour;
|
|||
|
mm:=((ASeconds mod SecPerDay) mod SecPerHour) div SecPerMinute;
|
|||
|
ss:=((ASeconds mod SecPerDay) mod SecPerHour) mod SecPerMinute;
|
|||
|
ms:=0;
|
|||
|
Result:=dd+EncodeTime(hh,mm,ss,ms);
|
|||
|
end;
|
|||
|
|
|||
|
function FormatTicks(AValue :Int64; AWholeSecondsOnly: Boolean = True) :string;
|
|||
|
{$IFDEF RAD9PLUSxxx}
|
|||
|
var
|
|||
|
ts: TTimeSpan;
|
|||
|
begin
|
|||
|
ts:=TTimeSpan.Create(AValue);
|
|||
|
Result:=Format('%2.2d:%2.2d:%2.2d',[ts.Hours,ts.Minutes,ts.Seconds]);
|
|||
|
if not AWholeSecondsOnly then
|
|||
|
Result:=Result+Format('.%3.3d',[ts.Milliseconds]);
|
|||
|
if ts.Days>0 then
|
|||
|
Result:=Format('%3.3d %s',[ts.Days,Result]);
|
|||
|
{$ELSE}
|
|||
|
const
|
|||
|
TicksPerMillisecond = 10000;
|
|||
|
TicksPerSecond = 1000 * Int64(TicksPerMillisecond);
|
|||
|
var
|
|||
|
dt: TDateTime;
|
|||
|
ms,d: Integer;
|
|||
|
begin
|
|||
|
dt:=SecondsToTime(Round(AValue/TicksPerSecond));
|
|||
|
d:=DaysBetween(0,dt);
|
|||
|
ms:=Integer((AValue div TicksPerMillisecond) mod 1000);
|
|||
|
Result:=FormatDateTime('hh:mm:ss',dt);
|
|||
|
if d>0 then
|
|||
|
Result:=Format('%3.3d %s',[d,Result]);
|
|||
|
if not AWholeSecondsOnly then
|
|||
|
Result:=Result+Format('.%3.3d',[ms]);
|
|||
|
{$ENDIF}
|
|||
|
end;
|
|||
|
|
|||
|
function FormatSeconds(AValue :Int64; AShort: Boolean = True) :string;
|
|||
|
{$IFDEF RAD9PLUSxxx}
|
|||
|
var
|
|||
|
ts: TTimeSpan;
|
|||
|
begin
|
|||
|
ts:=TTimeSpan.Create(0,0,0,AValue);
|
|||
|
if AShort and (ts.Days=0) then
|
|||
|
Result:=Format('%2.2d:%2.2d:%2.2d',[ts.Hours,ts.Minutes,ts.Seconds])
|
|||
|
else
|
|||
|
Result:=Format('%3.3d %2.2d:%2.2d:%2.2d',[ts.Days,ts.Hours,ts.Minutes,ts.Seconds]);
|
|||
|
{$ELSE}
|
|||
|
var
|
|||
|
dt: TDateTime;
|
|||
|
d: integer;
|
|||
|
begin
|
|||
|
dt:=SecondsToTime(AValue);
|
|||
|
d:=DaysBetween(0,dt);
|
|||
|
if AShort and (d=0) then
|
|||
|
Result:=FormatDateTime('hh:mm:ss',dt)
|
|||
|
else
|
|||
|
Result:=Format('%3.3d %s',[d,FormatDateTime('hh:mm:ss',dt)]);
|
|||
|
{$ENDIF}
|
|||
|
end;
|
|||
|
|
|||
|
function FormatMilliseconds(AValue :Int64; AWholeSecondsOnly: Boolean = True; AShort: Boolean = True) :string;
|
|||
|
{$IFDEF RAD9PLUSxxx}
|
|||
|
var
|
|||
|
ts: TTimeSpan;
|
|||
|
begin
|
|||
|
ts:=TTimeSpan.Create(0,0,0,0,AValue);
|
|||
|
if AShort and (ts.Days=0) then
|
|||
|
Result:=Format('%2.2d:%2.2d:%2.2d',[ts.Hours,ts.Minutes,ts.Seconds])
|
|||
|
else
|
|||
|
Result:=Format('%3.3d %2.2d:%2.2d:%2.2d',[ts.Days,ts.Hours,ts.Minutes,ts.Seconds]);
|
|||
|
if not AWholeSecondsOnly then
|
|||
|
Result:=Result+Format('.%3.3d',[ts.Milliseconds]);
|
|||
|
{$ELSE}
|
|||
|
var
|
|||
|
dt: TDateTime;
|
|||
|
ms,d: integer;
|
|||
|
begin
|
|||
|
dt:=SecondsToTime(Round(AValue/1000));
|
|||
|
d:=DaysBetween(0,dt);
|
|||
|
ms:=AValue mod 1000;
|
|||
|
if AShort and (d=0) then
|
|||
|
Result:=FormatDateTime('hh:mm:ss',dt)
|
|||
|
else
|
|||
|
Result:=Format('%3.3d %s',[d,FormatDateTime('hh:mm:ss',dt)]);
|
|||
|
if not AWholeSecondsOnly then
|
|||
|
Result:=Result+Format('.%3.3d',[ms]);
|
|||
|
{$ENDIF}
|
|||
|
end;
|
|||
|
|
|||
|
function XMLStrToDateTime(const AString: string): TDateTime;
|
|||
|
begin
|
|||
|
Result:=XMLStrToDateTimeDef(AString, 0);
|
|||
|
end;
|
|||
|
|
|||
|
function XMLStrToDateTimeDef(const AString: string; const ADefDateTime: TDateTime = 0): TDateTime;
|
|||
|
begin
|
|||
|
if not XMLTryStrToDateTime(aString, Result) then
|
|||
|
Result:=aDefDateTime;
|
|||
|
end;
|
|||
|
|
|||
|
function XMLTryStrToDateTime(const AString: string; var ADatetime: TDateTime): Boolean;
|
|||
|
var
|
|||
|
xYear, xMonth, xDay, xHour, xMinute, xSecond, xMS: Integer;
|
|||
|
sYear, sMonth, sDay, sHour, sMinute, sSecond, sMS: string;
|
|||
|
begin
|
|||
|
sYear:=Copy(AString,1,4);
|
|||
|
sMonth:=Copy(AString,6,2);
|
|||
|
sDay:=Copy(AString,9,2);
|
|||
|
sHour:=Copy(AString,12,2);
|
|||
|
sMinute:=Copy(AString,15,2);
|
|||
|
sSecond:=Copy(AString,18,2);
|
|||
|
sMS:=Copy(AString,21,3);
|
|||
|
Result:=TryStrToInt(sYear,xYear) and
|
|||
|
TryStrToInt(sMonth,xMonth) and
|
|||
|
TryStrToInt(sDay,xDay);
|
|||
|
if Result then begin
|
|||
|
xHour:=StrToIntDef(sHour,0);
|
|||
|
xMinute:=StrToIntDef(sMinute,0);
|
|||
|
xSecond:=StrToIntDef(sSecond,0);
|
|||
|
xMS:=StrToIntDef(sMS,0);
|
|||
|
Result:=TryEncodeDateTime(xYear,xMonth,xDay,xHour,xMinute,xSecond,xMS,ADatetime);
|
|||
|
end;
|
|||
|
|
|||
|
if not Result then
|
|||
|
ADatetime:=0;
|
|||
|
end;
|
|||
|
|
|||
|
initialization
|
|||
|
TzSpecificLocalTimeToSystemTime:=TTzSpecificLocalTimeToSystemTime(GetProcAddress(GetModuleHandle('Kernel32.dll'),'TzSpecificLocalTimeToSystemTime'));
|
|||
|
SystemTimeToTzSpecificLocalTime:=TSystemTimeToTzSpecificLocalTime(GetProcAddress(GetModuleHandle('Kernel32.dll'),'SystemTimeToTzSpecificLocalTime'));
|
|||
|
end.
|
|||
|
|