我正在尝试将文件的创建日期修改为发布日期。我首先将诸如“ 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_INFORMATION
和GetTimeZoneInformation
,但我只得到了TIME_ZONE_ID_STANDARD
。
几件事:
SYSTEMTIME
只是一个简单的结构。它具有年,月,星期几,日(月),小时,分钟,秒和毫秒的单独字段。它既不是UTC时间也不是当地时间,也不是其他时间。除非将其传递给函数,否则不会考虑这一点。
FILETIME
是另一个普通结构。它表示自1601-01-01午夜以来的100纳秒间隔数。许多文档会让您以为它始终使用UTC,但是有些函数FileTimeToLocalFileTime
却证明了这一点。因此,像SYSTEMTIME
一样,由每个函数决定如何解释它。
SystemTimeToFileTime
函数接受指向被解释为UTC的SYSTEMTIME
的指针,并返回也代表UTC的FILETIME
的指针。不涉及本地时区。
请勿尝试自己调整本地时间(代码中的st.wHour = 6
)。小时将根据时区和夏令时而有所不同。
除了GetTimeZoneInformation
,您没有看到来自TIME_ZONE_STANDARD
的任何响应,因为它告诉您当前正在执行的操作-与您可能正在使用的日期断开了连接。
您不应该试图自己弄清楚如何调整DST。 DST并非普遍适用,并且并非总是偏移一小时。相反,请使用将您关心的时区转换为UTC的函数。
最终,听起来您正在询问如何将文件时间设置为特定日期的本地时区的午夜。因此,我建议您执行以下步骤:
用您关心的日期构造一个SYSTEMTIME
,并将时间分量设置为零(默认值)。
使用GetDynamicTimeZoneInformation
功能获取当地时区。您希望使用“动态”版本,以便考虑Windows知道的标准时间和DST规则中的任何历史差异,而不仅仅是当前的规则集。
将这两个值传递给GetDynamicTimeZoneInformation
函数。它将输入时间解释为处于输入时区(这是系统的本地时区)中。结果是以UTC表示的TzSpecificLocalTimeToSystemTimeEx
。
将该值传递给TzSpecificLocalTimeToSystemTimeEx
,后者期望输入的单位是UTC。
此外,请记住FILETIME
:
NTFS存储实际的UTC时间,因此即使计算机具有不同的时区设置,您也可以在计算机之间移动文件,并且时间戳记表示通用时间中的同一点。
FAT及其变体存储本地时间。因此,当您调用SetFileTime
时,Windows会将UTC转换为本地时区并写入结果。如果随后在具有不同时区的系统上打开文件,则日期将在that时区中解释,从而导致不同的UTC时间。 (将文件从相机移动到计算机时,通常在USB记忆棒,存储卡等上看到这种情况。)
最后,您说:
...最好在日期可以追溯到60年代的日期,也可以在现在使用。
[遗憾的是,Windows时区无法跟踪到目前为止的历史日期。 not all file systems track file times in the same way将跟踪2010年的时区和DST规则,并转发地球上所有人口稠密的地方。虽然,一些时区跟踪2010年以前的历史变化,因为该政策正式制定之前的工件。 (它们在给定区域内是准确的,只是开始年份在所有区域内均不一致)。如果历史日期对您的应用程序很重要,则您将需要一种非常不同的方法-一种不使用Windows时区数据,而是使用SetFileTime
的方法。 (有关这些内容的更多信息,请参见Microsoft's time zone policy。)以下是您可以探索的一些想法:
请记住,IANA数据库仅保证从1970年开始。您说过您需要从1960年开始,尽管有一些区域提供了该数据(并且还有一些更旧的数据),但不能保证该时期的正确性。