在我的应用程序中,我需要使用文件中描述的模式计算轮班。 最近,由于以下原因,我的一位客户申请暂停:
如果您在冬季结束时填写“struct tm”(非DST)_mktime似乎返回了错误的结果。
代码如下所示:
struct tm tm_start;
tm_start.tm_mday = startday;
tm_start.tm_mon = startmonth-1;
tm_start.tm_year = startyear-1900;
tm_start.tm_hour = starthour;
tm_start.tm_min = startmin;
tm_start.tm_sec = startsec;
tm_start.tm_isdst = -1; // Don't know if DST is active at this moment
_int64 contTime = _mktime64(&tm_start);
假设4月5日凌晨2点从冬季到夏季都有转换。 在实践中,这意味着我们有以下时间:
5 April, 1:58
5 April, 1:59
5 April, 3:00
由于我在应用程序中不知道DST何时开始或结束(我真的想知道吗?)我使用上面显示的代码将日期“5月4日,2:00”传递给_mktime64。
我希望_mktime64能给我time_t值,对应4月5日,3:00(与4月5日,2:00完全相同)。
但是,这不是正在发生的事情。 _mktime64将tm_start更改为4月5日,1:00并返回相应的time_t值。这意味着我得到一个完全不同的时刻。 (事实上:2:00到3:00之间的每一刻都会导致_mktime64在1:00到2:00之间返回一个时刻)
我认为这是Visual Studio 2005中的一个错误,但显然Visual Studio 2010(Release Candidate)具有相同的行为。
问题出现在XP和Windows7上(没有检查Vista)。
这是一个已知的错误吗? 或者还有其他提示来解决这个问题吗?
答案 0 :(得分:3)
这是使用本地时间而不是UTC的必然结果。 DST的结束也很麻烦,时间戳在转换期间是矛盾的,因为本地时间匹配两次。
通过使用UTC可以很容易地解决这个问题,这也是操作系统所做的事情。检查您的CRT实现,例如_gmtime64()或本机GetFileTime()。
答案 1 :(得分:2)
我想它根本就不知道如何正确处理你传入的无效时间。而且它对你的时区肯定无效 - 你认为它是'冬天1:59后1分钟'这意味着你希望它在运行DST时返回'3:00',这听起来很合理。然而它同样可以把它当作“夏天3点前一小时”来对待,这意味着它必定是从冬季开始,因此返回'1:00'。因此,我不认为这是一个错误 - 它更可能是关于如何处理不存在的时间的未定义行为。
我希望最安全的方法是使用UTC,因为没有歧义。显然,这可能不会完全映射到您的应用程序域,但这是一个向后和向后推动时间的阴暗世界!
答案 2 :(得分:1)
尝试将4月5日,2:30转换为time_t
类似于尝试将2011年2月29日转换为time_t
。在这两种情况下,您都不期望有效结果,因为输入不是有效日期。 4月5日,即使凌晨2点也不存在。 1:59.59直接跟随3:00:00