Delphi 跨平台的实施时间(以毫秒为单位)
Implement Time in Milliseconds for Cross platform in 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 小时 DST。错误与 UTC 时间和本地时间之间的差异相同。
错误发生是因为您调用了两个不同的函数,convert/return 从本地时间到 UTC。下面是函数调用和来自 MSDN 的简要说明。
GetSystemTime(stt);
- Retrieves the current system date and time in Coordinated Universal Time (UTC) format
result: 2021, 5, 2, 25, 15, 23, 39, 219, Time: 15.23.39. My actual local time is 18.23.39
SystemTimeToFileTime(stt, LocalFileTime);
- Converts a system time to file time format. System time is based on Coordinated Universal Time (UTC).
LocalFileTimeToFileTime(LocalFileTime, UTCFileTime)
- Converts a local file time to a file time based on the Coordinated Universal Time (UTC).
FileTimeToSystemTime(UTCFileTime, UtcSystemTime)
- Converts a file time to system time format. System time is based on Coordinated Universal Time (UTC).
result: 2021, 5, 2, 25, 12, 23, 39, 219, Time: 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;
我在 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 小时 DST。错误与 UTC 时间和本地时间之间的差异相同。
错误发生是因为您调用了两个不同的函数,convert/return 从本地时间到 UTC。下面是函数调用和来自 MSDN 的简要说明。
GetSystemTime(stt);
- Retrieves the current system date and time in Coordinated Universal Time (UTC) format
result: 2021, 5, 2, 25, 15, 23, 39, 219, Time: 15.23.39. My actual local time is 18.23.39
SystemTimeToFileTime(stt, LocalFileTime);
- Converts a system time to file time format. System time is based on Coordinated Universal Time (UTC).
LocalFileTimeToFileTime(LocalFileTime, UTCFileTime)
- Converts a local file time to a file time based on the Coordinated Universal Time (UTC).
FileTimeToSystemTime(UTCFileTime, UtcSystemTime)
- Converts a file time to system time format. System time is based on Coordinated Universal Time (UTC).
result: 2021, 5, 2, 25, 12, 23, 39, 219, Time: 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;