转换不存在的 struct tm 时的 mktime 问题(因为日光变化时间)
Posted
技术标签:
【中文标题】转换不存在的 struct tm 时的 mktime 问题(因为日光变化时间)【英文标题】:mktime issue when converting a struct tm that doesn't exist (because of the daylight changing time) 【发布时间】:2012-08-28 09:12:15 【问题描述】:我有一个 mktime 问题,如果由于 DST 更改而导致小时不存在,那么使用 MSVS 2010 的 windows 上的 mktime 将返回过去的 time_t,在我的情况下为 23:00,它应该返回 1:00AM第二天(在 Linux 上它应该返回凌晨 1:00)。我的问题发生在巴西时区(格林威治标准时间 -3)上,恰好是自动调整夏令时发生的时间。在他们的情况下,这发生在 2012 年 10 月 21 日凌晨 0:00(这将变为凌晨 1:00)。
这是部分代码:
/* test_date1.cpp : Defines the entry point for the console application.
*
*/
#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int _tmain(int argc, _TCHAR* argv[])
time_t mytime=1350784881;
struct tm *timeinfo;
char *tz;
/*time ( &mytime ); */
timeinfo = localtime ( &mytime );
printf("%.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n",
timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year, timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);
timeinfo->tm_mday=21;
timeinfo->tm_mon=9;
timeinfo->tm_year=112;
timeinfo->tm_hour=0;
timeinfo->tm_min=0;
timeinfo->tm_isdst=-1;
printf("The shit: %.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n",
timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year, timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);
mytime= mktime(timeinfo);
printf("mytime is=%d\n", mytime);
timeinfo = localtime ( &mytime );
printf("%.2d/%.2d/%.4d, %.2d:%.2d isdst?=%d\n",
timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year, timeinfo->tm_hour, timeinfo-> tm_min, timeinfo -> tm_isdst);
return 0;
Windows 上的结果是:
20/09/0112, 23:01 isdst?=0
21/09/0112, 00:00 isdst?=-1
mytime is=1350784800
20/09/0112, 23:00 isdst?=0
在 Linux 上是:
20/09/0112, 23:01 isdst?=0
21/09/0112, 00:00 isdst?=-1
mytime is=1350788400
21/09/0112, 01:00 isdst?=1
如您所见,在 time_t 从 Unix 返回 C 和从 Microsoft Visual Studio 2010 返回 C 之间,mytime 的差异是 3600 秒。
这个程序应该在不同的平台(UNIX/WINDOWS/etc)和任何时区上运行,所以我不应该对时区进行硬编码。
正如您所见,问题出在 Windows 上,错误地返回了时间。在这一刻,我不知道如何解决这个问题。有人遇到过这个特殊问题吗?你是怎么解决的?我特别需要当地日的开始。
非常感谢,
玩笑
【问题讨论】:
当您提出此类问题时,请务必记录操作系统版本。看看 TZ 环境变量给你带来了什么。 【参考方案1】:我不知道 mktime 的行为是否在您传递无效时间时被定义,所以这实际上可能不是错误。
无论如何,除了自己重新实现 mktime 之外,您还需要解决这个问题。我提出以下算法:
为当天上午 9 点构建一个 struct tm。 转换为 time_t。 从 time_t 中减去 24 小时。如果没有夏令时变化,那么此时您将看到前一天上午 9 点。如果夏令时开始了,你会看到早上 8 点;如果它完成了,你正在看上午 10 点。
转换回 struct tm。 将 struct tm 中的日期与原始日期进行比较。 如果还不是正确的日期,请将 time_t 增加一个小时,然后重试。由于您一次只添加一个小时,一旦您获得所需的日期,您就可以确定您获得了该日期的最早时间。
我做了一些我认为目前安全的假设:夏令时永远不会在一个小时内开始或结束,它永远不会在上午 8 点到 10 点之间开始或结束,并且它的变化永远不会超过一个小时。
我故意不假设夏令时永远不会在晚上开始或结束(例如,晚上 11 点变成午夜,反之亦然)或清晨(例如,凌晨 2 点变成凌晨 3 点,反之亦然) - 反之亦然,这正是这里发生的事情)。
【讨论】:
以上是关于转换不存在的 struct tm 时的 mktime 问题(因为日光变化时间)的主要内容,如果未能解决你的问题,请参考以下文章