确定夏令时是否适用于特定日期

我正在尝试将文件的创建日期修改为发布日期。我首先将诸如“ 2005年4月2日”之类的字符串转换为std::tm。然后,我创建一个SYSTEMTIME,如下所示:

std::tm dt = from_string("2 April 2005");
SYSTEMTIME st { 0 };
st.wYear = dt.tm_year + 1900; // dt is years from 1900
st.wMonth = dt.tm_mon + 1; // dt is month index 0
st.wDay = dt.tm_mday;
st.wHour = 6; // FILETIME is based on UTC,which is 6 hours ahead

然后,我将SYSTEMTIME转换为FILETIME,并使用它来应用更改。

这将文件时间设置为2 April 2005 12:00:00 AM,这是正确的。但是,将4月2日之后的视频设置为1:00:00 AM,并且可以肯定的是,夏令时发生在2005年4月3日。

如何确定某个日期是否在夏令时之前或之后,以便可以相应地调整st.wHour?目标是将所有时间都设置为12:00:00 AM。最好在日期可以追溯到60年代的日期以及当前日期使用。

我尝试使用TIME_ZONE_INFORMATIONGetTimeZoneInformation,但我只得到TIME_ZONE_ID_STANDARD

lucifer0777777777777 回答:确定夏令时是否适用于特定日期

几件事:

  • SYSTEMTIME只是一个简单的结构。它具有年,月,星期几,日(月),小时,分钟,秒和毫秒的单独字段。它既不是UTC时间也不是当地时间,也不是其他时间。在将其传递给函数之前,不会考虑这一点。

  • FILETIME是另一个简单的结构。它表示自1601-01-01午夜以来的100纳秒间隔数。许多文档会让您以为它始终使用UTC,但是有FileTimeToLocalFileTime之类的函数对此进行了证明。因此,就像SYSTEMTIME一样,由每个函数决定如何解释它。

  • SystemTimeToFileTime函数接受指向被解释为UTC的SYSTEMTIME的指针,并返回也代表UTC的FILETIME的指针。没有涉及本地时区。

  • 请勿自行调整本地时间(代码中的st.wHour = 6)。小时将需要根据时区和夏令时进行更改。

  • 除了GetTimeZoneInformation之外,您没有看到TIME_ZONE_STANDARD的任何响应,因为它告诉您当前有效的内容-与您可能正在使用的日期断开了连接。 / p>

  • 您不应该试图自己弄清楚如何调整DST。 DST并非普遍适用,并且并非总是偏移一小时。而是使用一个功能,将您关心的时区转换为UTC。

最终,这听起来像是您在询问如何将文件时间设置为特定日期的本地时区的午夜。因此,我建议您执行以下步骤:

  • 用您关心的日期和时间分量设置为零(默认值)构造一个SYSTEMTIME

  • 使用GetDynamicTimeZoneInformation函数获取本地时区。您希望使用“动态”版本,以便考虑Windows知道的标准时间和DST规则的历史差异,而不仅仅是当前的规则集。

  • 将这两个值传递给TzSpecificLocalTimeToSystemTimeEx函数。它将输入时间解释为处于输入时区(这是系统的本地时区)中。结果是一个FILETIME(以UTC表示)。

  • 将该值传递给SetFileTime,后者期望输入的单位是UTC。

此外,请记住not all file systems track file times in the same way

  • NTFS存储实际的UTC时间,因此即使计算机具有不同的时区设置,您也可以在计算机之间移动文件,并且时间戳表示“通用时间”中的同一点。

  • FAT及其变体存储本地时间。因此,当您调用SetFileTime时,Windows会将UTC转换为本地时区并写入结果。如果随后在具有不同时区的系统上打开文件,则日期将在那个时区中解释,从而导致不同的UTC时间。 (将文件从相机移动到计算机时,通常在USB记忆棒,存储卡等上看到这种情况。)

最后,你说:

...最好在日期可以追溯到60年代的日期都适用。

不幸的是,Windows时区无法跟踪到目前为止的历史日期。 Microsoft's time zone policy将跟踪2010年的时区和DST规则,并转发到地球上所有人口稠密的地方。虽然,一些时区跟踪2010年以前的一些历史变化,因为该政策正式制定之前的工件。 (它们在给定区域内是准确的,只是开始年份在所有区域内都不一致)。

如果历史日期对您的应用程序很重要,则需要一种非常不同的方法-一种不使用Windows时区数据,而使用IANA time zone database的方法。 (有关the timezone tag wiki的更多信息。)以下是您可以探索的一些想法:

  • ICU project具有时区支持和C implementation。为此目的,它有点繁重,但是如果您将其用于应用程序的其他本地化方面,则很好。

  • Howard Hinnant(对上述问题发表了评论)在支持IANA时区方面表现出色Date library

  • 可以从Windows.Globalization.Calendar UWP类获得所需的内容。我尚未测试过是否会使用IANA数据中的历史规则,或者是否会使用Windows数据。 (如果有机会检查,我会回来并更新此答案。)

请记住,IANA数据库仅保证从1970年开始。您说过您需要从1960年开始,尽管有些地区提供了该地区的数据(有些地区更早),但并不能保证这段时期的正确性。

本文链接:https://www.f2er.com/2784454.html

大家都在问