如何向包含UTC时间的struct tm添加分钟数?

如何向包含UTC时间的struct tm添加分钟数?,c,windows,visual-studio,time,dst,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,

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;
}
如果由于添加而导致
t->tm_min
超过59,则调用
mktime()
来调整结构的所有其他成员变量。但是
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)中不添加任何内容,那么结果就会变得一团糟。现在,它将尝试关闭
*t
中的DST,从而将
t->tm_isdst
设置为0,并将日期重新调整为2011年1月1日09:00:00

因此,当我不想添加任何内容时,这会产生一个不希望的效果,即在指定的时间中添加一个额外的小时或从中减去一个额外的小时。这是因为当
mktime()
发现
t->tm_isdst
中的DST设置与系统本地时区不符时,它会尝试通过重新调整
*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;
}

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

struct tm上的文档说

夏令时标志(tm_isdst)是。。。如果 目前没有这方面的资料


我建议您将其设置为-1,看看是否可以解决问题。

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

密切相关,可以说是重复:.ruakh,您提到的帖子密切相关,但不相似。这里的问题有一个巧妙的解决方法,它涉及从
mktime()
返回的时间戳中减去时区偏移量。但是,我的问题是在
struct tm
对象中向时间添加一定的分钟数,并确保
mktime()
不会因为DST设置而在日期中添加或减去任何额外的内容。这可能在DST转换方面仍然存在问题,例如
设置时间(&t,2011年3月13日,01日,59日,00日,1日)将返回03:00:00。@Borodin是的,但我的评论不完整。原始代码将返回
03:00:00
。更新后的代码(使用
tm_isdst=-1
)返回
01:00:00
。DRH,您是对的。这是一个很好的机会。我试过设置时间(&t,2011年,3月,13,02,30,00,0)用于EST,输出为:
太阳2011年3月13日01:30:00
,因为2011年3月13日凌晨2:30不是有效时间,因为时钟在该日期直接从凌晨2:00跳到凌晨3:00。你所举的例子也是如此。感谢您注意到这一点并让我们了解它。DRH中的文档提到:“在指定tm结构时间时,将tm_isdst字段设置为:零(0)表示标准时间有效,大于0的值表示夏令时有效,小于0的值表示C运行时库代码计算标准时间或夏令时是否有效。“-无论我如何初始化
t->tm_isdst
都会得到相同的答案。因此,我无法理解这个函数是如何利用
tm_isdst
@Susam Pal的。我不是100%,但我相信文档是从他们的
mktime
文档中提取出来的,实际上并不适用于
\u mkgmtime
。这是基于将
tmèisdst
设置为各种值以及将我的本地时间设置为输入和输出DST的各种实验,在所有情况下,
tmèisdst
的结果都设置为
0
(这是我对UTC的期望值),对于使用Unix的用户,有
timegm
,它是
gmtime
的反义词(和
timelocal
,它是
localtime
的反义词,相当于
mktime
)。