从 GetSystemTimePreciseAsFileTime() 到本地时间的可靠快速方法

问题描述 投票:0回答:2

WinAPI 函数

GetSystemTimePreciseAsFileTime()
将时间写入
FILETIME
结构,该时间为 UTC。我想获得微秒和百纳秒的本地时间。我希望这个算法首先可靠,然后快速。

问题是到目前为止我考虑过的所有 WinAPI 似乎都不可靠:

  1. FileTimeToLocalFileTime()
    似乎不可靠,因为其文档

在将文件时间转换为时间时考虑夏令时 本地时间,使用以下函数序列代替使用 文件时间到本地文件时间...

  1. 但是,上述序列函数中的建议
    SystemTimeToTzSpecificLocalTime()
    似乎也不可靠,因为其文档说:

SystemTimeToTzSpecificLocalTime 函数可以计算本地时间 在以下情况下时间不正确:

a) 时区使用 新旧年份的 UTC 偏移量不同。

b) UTC 时间为 转换后的时间和计算出的当地时间是不同年份的。

情况 a) 似乎并不重要,但是,我绝对希望算法在新年前后能够正常工作。

最后,我考虑了

SystemTimeToTzSpecificLocalTimeEx()
,但是,我不清楚它与
SystemTimeToTzSpecificLocalTime()
有什么不同,而且它的文档似乎不值得信赖:它说
lpTimeZoneInformation
参数是可选的,但事实并非如此。没有说明如何指定默认值(是
NULL
吗?)以及该函数在默认情况下的行为方式(它会假设当前时区吗?)。

算法的下一部分是提取亚毫秒值,因为它们不是由

SYSTEMTIME
结构提供的。我可以只取
N%10000
其中 N 是存储在
uint64_t
结构中的
FILETIME
值吗?

c++ winapi time timezone localtime
2个回答
2
投票

SystemTimeToTzSpecificLocalTime
SystemTimeToTzSpecificLocalTimeEx
之间的区别在于后者使用
DYNAMIC_TIME_ZONE_INFORMATION
结构,它正确地反映了Windows注册表中的所有逐年信息。

TIME_ZONE_INFORMATION
结构

时区信息没有任何逐年变化。它仅反映当前有效的规则。如果您正在使用任意日期时间值,则应避免使用此结构,因为您无法保证当前规则是您正在使用的日期时间的正确规则。

但是,如果您只关心“当前”时间,那么就没有必要关心逐年变化。即使您获取的时间接近年初或年底,Windows 也会在适当的时间更新当前的时区规则。

此外,对于

SystemTimeToTzSpecificLocalTime

SystemTimeToTzSpecificLocalTimeEx
 函数,时区参数是可选的。通过 
NULL
 将使用当前本地时区。这记录在 
SystemTimeToTzSpecificLocalTime
:

如果

lpTimeZone

NULL
,则该函数使用当前活动时区。

SystemTimeToTzSpecificLocalTimeEx

上的文档中缺少它,但具有相同的效果。

因此,要获取操作系统可以提供的所有可用精度的当前本地时间,则:

  1. GetSystemTimePreciseAsFileTime
    
    
  2. FileTimeToSystemTime
    
    
  3. SystemTimeToTzSpecificLocalTime
    (这里不需要
    Ex
    ,并将 tz 留空)
  4. SystemTimeToFileTime
    
    
  5. 将步骤 1 中的亚毫秒复制到步骤 4 的结果。

0
投票
我认为模式可靠的方法是 SystemTimeToTzSpecificLocalTimeEx() ,它保留时区的 DST 更改历史记录,其中 DST 规则可能已经更改或计划在将来更改。

例如如果您有 10 年前的文件日期,并且该时区的 DST 规则发生了更改,SystemTimeToTzSpecificLocalTimeEx() 将为您提供 10 年前的正确本地日期。

我认为一旦欧洲在不久的将来取消夏令时,它将变得非常有用,以便在当地时间上获得正确的历史外观。

例如假设将 JPEG 文件保存到磁盘,并在 EXIF 中将正确的拍摄日期存储为本地日期字符串。操作系统将文件日期写入 UTC。将UTC文件日期转换为本地日期进行显示时,必须与EXIF存储的本地日期字符串完全相同。如果 DST 不匹配,日期将不相同。

SystemTimeToTzSpecificLocalTime() 大部分情况下都可以工作,除非 DST 规则在现在和创建文件的过去之间发生了变化,就像 DST 被删除一样。这就是为什么必须使用 SystemTimeToTzSpecificLocalTimeEx() 从 DST 历史角度获取正确的本地日期。

© www.soinside.com 2019 - 2024. All rights reserved.