如何向包含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日)本地时区为PST的代码>将返回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
)。