2012-09-03 23 views
1

我有一个mktime问题,如果小时因为DST更改而不存在,那么使用MSVS 2010的窗口上的mktime将返回一个time_t在我的情况下为23:00,当它应该在第二天上午1:00返回时(在Linux上它将返回上午1:00,因为它应该)。我的问题正好发生在巴西时区(格林威治标准时间-3),恰好在自动调整夏令时的时候。在他们的情况下,这发生在2012年12月21日凌晨0点(这将变成凌晨1点)。转换不存在的struct tm时mktime问题(由于日光转换时间)

这是代码的一部分:

/* 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 

正如你所看到的数值指明MyTime差异在time_t从Unix返回C和从Microsoft Visual Studio 2010返回C之间是3600秒。

这个程序应该运行在不同的平台上(UNIX/WINDOWS/etc)和任何时区,所以我不应该对时区进行硬编码。

正如你看到的问题是在Windows上错误地返回时间。在这一刻,我不知道如何解决这个问题。有人有这个特殊问题吗?你是如何解决它的?我特别需要当地的日子。

非常感谢,

Jokerush

+0

当你问这样的问题时,总是记录操作系统版本。看看TZ环境变量带给你什么。 –

回答

0

我不知道,当你传递一个无效的时间mktime的行为定义,所以这可能不是实际上是一个错误。

无论如何,您自己不需要重新实施mktime,您需要解决该问题。我提出以下算法:

  • 在当天的上午9点建立一个struct tm。
  • 转换为time_t。
  • 从time_t减去24小时。

如果夏令时没有变化,那么此时您正在查看前一天的上午9点。如果夏令时开始,你正在看早上8点;如果它完成了,你在上午10点看。

  • 转换回结构tm。
  • 将struct tm中的日期与原始日期进行比较。
  • 如果还不是正确的一天,请在time_t上添加一小时并重试。

由于您一次只能添加一小时,所以一旦您获得了想要的日期,就可以确定您已经获得了该日期的最早时间。

我正在做一些我认为目前安全的假设:夏令时从未开始或完成半小时,从未在早上8点到上午10点之间开始或结束,而且从未更改过比一个小时。

我故意不假设夏令从来没有开始或结束在晚上(例如,晚上11点午夜变成或反之亦然),或在清晨(例如,凌晨2点变为凌晨3点,反之亦然,这正如它发生的恰恰是这里发生的事情)。