set_time()
函数应该花费特定时间并将指定的分钟数添加到此时并将其保存在*t
中。
#include <stdio.h>
#include <time.h>
enum {JAN, FEB, MAR, APR, MAY, JUNE, JULY, AUG, SEP, OCT, NOV, DEC};
void set_time(struct tm *t,
int year, int mon, int day,
int hour, int min, int sec,
int mins_to_add)
{
/* Copy all the values. */
t->tm_year = (year - 1900);
t->tm_mon = mon;
t->tm_mday = day;
t->tm_hour = hour;
t->tm_min = min;
t->tm_sec = sec;
// No DST since we are storing UTC time.
t->tm_isdst = 0;
/* Add minutes to time. */
t->tm_min += mins_to_add;
mktime(t);
/* Debug print */
printf("%s\n", asctime(t));
}
int main(int argc, char **argv)
{
struct tm t;
set_time(&t, 2011, AUG, 1, 10, 00, 00, 0);
return 0;
}
所以,我要求set_time()
在2011年8月1日10:00:00没有添加任何内容。但是,如果我的Windows系统设置为EST时区,我得到的输出是:Mon Aug 01 11:00:00 2011
< / p>
发生错误是因为我执行的任务是将指定的分钟数(在上例中为0)添加到指定的时间(上例中的2011年8月1日10:00:00),这部分代码:
/* Add minutes to time. */
t->tm_min += mins_to_add;
mktime(t);
由于添加mktime()
超过59,调用 t->tm_min
来调整结构的所有其他成员变量。但是mktime()
将struct tm
对象中的时间视为当地时间。因此,当它看到日期是2011年8月1日和当地时区为EST时,它假定需要应用DST,但它发现t->tm_isdst
设置为0
(意味着DST不是适用于*t
)的时间。因此,它适用DST,调整日期从2011年8月1日10:00:00到2011年8月1日11:00:00,并将t->tm_isdst
设置为1
。
如果我将t->tm_isdst
初始化为1
,则不会发生此问题,因为mktime()
会发现*t
中的时间已经应用了DST。但是,如果我要求set_time()
在DST不应该应用的日期添加任何内容,例如2011年1月1日10:00:00,它会搞砸结果。现在,它会尝试关闭DST在*t
中,从而将t->tm_isdst
设置为0,并将日期重新调整为2011年1月1日09:00:00。
因此,当我想向其添加任何内容时,这会产生额外一小时或从指定时间减去额外一小时的不良影响。发生这种情况是因为当mktime()
发现t->tm_isdst
中的DST设置不符合系统的本地时区时,它会尝试通过重新调整{{1}中的时间来正确设置它。 1}}。
解决这个问题的正确方法是什么?
答案 0 :(得分:2)
struct tm
上的文档说
夏令时标志(tm_isdst)如果是,则小于零 信息不可用。
我建议你将它设置为-1,看看是否能解决问题。
答案 1 :(得分:1)
可以使用Windows函数_mkgmtime
代替mktime
命令安全地执行此转换(无论本地时区设置如何)。