1

我有一个 mktime 问题,如果由于 DST 更改而导致小时不存在,那么使用 MSVS 2010 的 windows 上的 mktime 将在过去返回一个 time_t,在我的情况下为 23:00,它应该在第二天凌晨 1:00 返回(在 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 上,时间返回错误。在这一刻,我不知道如何解决这个问题。有人遇到过这个特殊问题吗?你是怎么解决的?我特别需要地方日的开始。

非常感谢,

笑话

4

1 回答 1

0

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

无论如何,除了自己重新实现 mktime 之外,您还需要解决这个问题。我提出以下算法:

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

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

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

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

我做了一些我认为目前是安全的假设:夏令时永远不会在一个小时内开始或结束,它永远不会在上午 8 点到 10 点之间开始或结束,并且它永远不会改变超过一个小时。

我故意假设夏令时永远不会在晚上开始或结束(例如,晚上 11 点变成午夜,反之亦然)或清晨(例如,凌晨 2 点变成凌晨 3 点,反之亦然,这正是发生在这里)。

于 2012-09-03T21:14:48.267 回答