如何将分钟添加到包含UTC时间的struct tm?

时间:2012-01-27 23:37:19

标签: c windows visual-studio time dst

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}}。

解决这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

struct tm上的文档说

  

夏令时标志(tm_isdst)如果是,则小于零   信息不可用。

我建议你将它设置为-1,看看是否能解决问题。

答案 1 :(得分:1)

可以使用Windows函数_mkgmtime代替mktime命令安全地执行此转换(无论本地时区设置如何)。