在Delphi中实现跨平台时间(毫秒)



我在Delphi(在Windows中(中有一段代码,我使用RAD Studio为跨平台实现了这段代码。这是代码:

uses SysUtils, Windows, DateUtils;
type
TSystem_Time = record
wYear: word;
wMonth: word;
wDayOfWeek: word;
wDay: word;
wHour: word;
wMinute: word;
wSecond: word;
wMilliseconds: word;
end;
function DatumInSeconds2(y, m, d, h, mi, s: word): longword;
var
RelDay: longword;
begin
if y >= 1970 then
dec(y, 1900)
else if y < 70 then
inc(y, 100); // 00..69 -> 100..169
if (y < 70) or (y > 169) or (m < 1) or (m > 12) or (d < 1) or (d > 31) then
begin
DatumInSeconds2 := 0;
exit;
end;
while m > 1 do
begin
dec(m);
d := d + DaysInMonth[m];
if (m = 2) and ((y mod 4) = 0) then
inc(d); { gilt auch fuer Jahr 2000 }
end;
RelDay := longword(365) * longword(y - 70) + // Tage in den Vorjahren
longword((y - 69) div 4) + // Schalttage in den Vorjahren
d - 1;
DatumInSeconds2 := ((RelDay * longword(24) + h) * longword(60) + mi) *
longword(60) + s
end;
function GetTimeInMilliSeconds_Windows: Int64; // For windows
var
stt: TSystemTime;
secFrom1900: Int64;
UtcSystemTime: TSystemTime;
LocalFileTime: TFileTime;
UTCFileTime: TFileTime;
begin
Writeln('Enter GetTimeInMilliSeconds_Windows');
GetTimeInMilliSeconds_Windows := 0;
{ W1035 Return value of function 'GetTimeInMilliSeconds' might be undefined }
GetSystemTime(stt);
SystemTimeToFileTime(stt, LocalFileTime);
// Local System Time -> Local File Time
if LocalFileTimeToFileTime(LocalFileTime, UTCFileTime) then
// Local File Time -> UTC File Time
if FileTimeToSystemTime(UTCFileTime, UtcSystemTime) then
begin // Local File Time -> UTC System Time
with UtcSystemTime do
begin
secFrom1900 := DatumInSeconds2(wYear, wMonth, wDay, wHour, wMinute,
wSecond) + 2208988800;
Writeln('secFrom1900', secFrom1900);
Writeln('wYear', wYear);
Writeln('wMonth', wMonth);
Writeln('wDay', wDay);
Writeln('wHour', wHour);
Writeln('wMinute', wMinute);
Writeln('wSecond', wSecond);
Writeln('wMilliseconds', wMilliseconds);
GetTimeInMilliSeconds_Windows := (secFrom1900 * 1000) + wMilliseconds;
end;
end
else
begin
// In case the conversion to UTC fails, return the timestamp in local time.
with stt do
begin
secFrom1900 := DatumInSeconds2(wYear, wMonth, wDay, wHour, wMinute,
wSecond) + 2208988800;
GetTimeInMilliSeconds_Windows := (secFrom1900 * 1000) + wMilliseconds;
end;
end;
end;
function GetTimeInMilliSeconds_Crossplatform: Int64; // crossplatform code
var
dtNow, newdt: TDateTime;
st: TSystem_Time;
secFrom1900: Int64;
begin
Writeln('Enter GetTimeInMilliSeconds_Crossplatform');
GetTimeInMilliSeconds_Crossplatform := 0;
dtNow := Now;
newdt := TTimeZone.Local.ToUniversalTime(dtNow);
DecodeDateTime(newdt, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,
st.wSecond, st.wMilliseconds);
with st do
begin
secFrom1900 := DatumInSeconds2(wYear, wMonth, wDay, wHour, wMinute, wSecond)
+ 2208988800;
// secFrom1900:= DateTimeToUnix(newdt) + 2208988800;
Writeln('secFrom1900', secFrom1900);
Writeln('wYear', wYear);
Writeln('wMonth', wMonth);
Writeln('wDay', wDay);
Writeln('wHour', wHour);
Writeln('wMinute', wMinute);
Writeln('wSecond', wSecond);
Writeln('wMilliseconds', wMilliseconds);
GetTimeInMilliSeconds_Crossplatform := (secFrom1900 * 1000) +
st.wMilliseconds;
end;
end;

这是输出:

Enter GetTimeInMilliSeconds_Windows
secFrom19003830898396
wYear2021
wMonth5
wDay25
wHour2
wMinute26
wSecond36
wMilliseconds551
Original_GetTimeInMilliSeconds>>3830898396551
sec3830898396
Enter GetTimeInMilliSeconds_Crossplatform
secFrom19003830918196
wYear2021
wMonth5
wDay25
wHour7
wMinute56
wSecond36
wMilliseconds560
Test_GetTimeInMilliSeconds>>3830918196560

所以这里的问题是,当我尝试执行它们时,它们在小时和分钟上都有所不同。有人能提出一些解决这个问题的想法吗?或者可能需要其他方法来实现它?提前谢谢。

首先介绍当前function GetTimeInMilliSeconds_Windows: Int64;中的错误。这个错误并不像我说的那样是固定的3个小时。我住在芬兰,现在是3小时,我们的时区是UTC+2小时+1小时夏令时。该错误与UTC时间和当地时间之间的差异相同。

发生此错误的原因是您调用了两个不同的函数,它们将本地时间转换/返回到UTC。下面是MSDN的函数调用和简短描述。

GetSystemTime(stt);-以协调世界时(UTC(格式检索当前系统日期和时间

结果:2021,5,2,25,15,23,39219,时间:15.23.39。我的实际当地时间是18.23.39

SystemTimeToFileTime(stt, LocalFileTime);-将系统时间转换为文件时间格式。系统时间以协调世界时(UTC(为基础。

LocalFileTimeToFileTime(LocalFileTime, UTCFileTime)-将本地文件时间转换为基于协调世界时(UTC(的文件时间。

FileTimeToSystemTime(UTCFileTime, UtcSystemTime)-将文件时间转换为系统时间格式。系统时间以协调世界时(UTC(为基础。

结果:2021,5,2,25,12,23,39,219,时间:12.23.39

这是我对更好(在我看来(解决方案的建议。由于你没有说明你有什么样的用例,你可能需要根据需要应用它。无论如何,结果是自1900年初以来的nr(毫秒(。

function GetTimeInMilliSeconds_Crossplatform: Int64;
var
dtNow: TDateTime;
epoch: TDatetime;
st: TSystemTime;
secsbetween, msecsBetween: int64;
begin
// define
epoch := EncodeDateTime(1900, 1, 1, 0, 0, 0, 0);
// get current local date time
dtNow := Now;
// Memo1.Lines.Add('DtToS, loc: '+DateTimeToStr(dtNow));
// or get current date time as UTC
dtNow := TTimeZone.Local.ToUniversalTime(Now);
// Memo1.Lines.Add('DtToS, utc: '+DateTimeToStr(dtNow));
// Convert to date and time record if required
DecodeDateTime(dtNow, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
// convert to milliseconds from 1900.01.01 00.00.00
msecsBetween := MilliSecondsBetween(dtNow, epoch);
// Memo1.Lines.Add(Format('Milliseconds since epoch = %d',[msecsBetween]));

result := msecsBetween;
end;

最新更新