mktime和tm_isdst

问题描述 投票:14回答:3

我在这里想到了很多不同的看法。

我读了man mktime

 (A positive or zero value for tm_isdst causes mktime() to presume initially
 that summer time (for example, Daylight Saving Time) is or is not in
 effect for the specified time, respectively.  A negative value for
 tm_isdst causes the mktime() function to attempt to divine whether summer
 time is in effect for the specified time. 

我的问题是,不应该将tm_isdst保留为-1,让系统决定它是否为dst,以及代码是否与dst无关?

我错过了什么吗?

c unix time freebsd mktime
3个回答
4
投票

我认为最初的原因是某些时区没有夏令时。由于mktime不是异步安全的,也不是可重入的,因此允许实现将夏令时的当前值存储在POSIX extern char tzname [2]中,由daylight [0或1]索引。这意味着tzname [0] =“[std TZ name]”和tzname =“[daylight TZ name,例如EDT]”

有关此内容的更多信息,请参见tzset()手册页。符合mktime()的标准要求表现得好像无论如何都要调用tzset()。这种情况避免了使用tm_isdst,IMO。

底线:您的特定实现和时区将决定是否对tm_isdst使用-1,0或1。所有实现都没有一种默认的正确方法。


10
投票

如果可能,您应该避免将tm_isdst设置为-1。系统无法始终仅从日期和时间确定DST状态。在夏令时结束之前和之后的一小时,这是模棱两可的。例如,如果您在2012年11月4日凌晨1:30通过mktime(),那么从time_t获取正确的mktime()值的信息不足。通常我看到mktime()假设它是模糊的标准时间,但我没有看到任何文档保证所有平台上的行为。 2012年11月4日凌晨1:30,tm_isdst == 1将在1小时前,因为小时1:00:00至1:59:59重复。

#include <stdio.h>
#include <time.h>

int main()
{
    time_t daylight, standard;
    struct tm timestr;
    double diff;

    timestr.tm_year = 2012 - 1900;
    timestr.tm_mon = 11 - 1;
    timestr.tm_mday = 4;
    timestr.tm_hour = 1;
    timestr.tm_min = 30;
    timestr.tm_sec = 0;

    /* first with standard time */
    timestr.tm_isdst = 0;
    standard = mktime(&timestr);

    /* now with daylight time */
    timestr.tm_isdst = 1;
    daylight = mktime(&timestr);

    diff = difftime(standard, daylight);

    printf("Difference is %f hour(s)", diff/60.0/60.0);

    return 0;
}

这会产生:

Difference is 1.000000 hour(s)

两者都是2012年11月4日凌晨1:30,但两者都是两个不同的time_t值,相隔1小时。

mktime()基本上有2个输出:

  • time_t的
  • 修复时间结构

时间结构既是输入又是输出。它由mktime()修改,以将所有结构成员返回到标称范围。例如,如果增加tm_hour成员+= 500,则意味着将时间增加500小时。 tm_hour成员将被更改为值00到23,并且tm_daytm_mday等将相应地进行调整。 tm_isdst也是输入和输出。其价值如下:

  • 1(DST生效,即白天时间)
  • 0(DST无效,即标准时间)
  • -1(未知的DST状态)

所以mktime()将为tm_isdst输出1或0,从不输出-1。

-1是一个可能的输入,但我认为它意味着“未知”。不要认为它意味着“自动确定”,因为一般来说,mktime()不能总是自动确定它。

显式DST状态(0或1)应来自软件外部的某些内容,例如将其存储在文件或数据库中,或提示用户。


0
投票

我认为你确实应该使用-1作为tm_isdst字段,除非你有关于你正在处理的时间类型的信息。

例如,在加利福尼亚州,我们仍然有PST和PDT。如果要解析日期并且存在时区信息,则应相应地设置tm_isdst。正如Jim McNamara所提到的那样,在调用tzname[]之后,这些名字可以在tzset()数组中找到。

例如,以下C ++代码编写PST/PDT

int main(int argc, char * argv [])
{
    tzset();
    std::cerr << tzname[0] << "/" << tzname[1] << "\n";

    return 0;
}

tzname[]数组中的偏移量对应于tm_isdst的值。 (PST - 太平洋标准时间,tm_isdst = 0和PDT,太平洋夏令时,tm_isdst = 1。)

如果您的输入中没有时区信息,那么使用-1是最佳选择。只有当日期对应于更改发生的日期和时间时,才会遇到问题。正如Rich Jahn解释的那样,在2012年11月4日,他在标准时间和日光时间之间进行了时间变换,大约在那个时候,gmtime()必须做出选择,这与你期望的相反。话虽这么说,它只发生在一年中和半夜共2小时。因此,除非您正在处理日期非常重要的关键类型的软件,否则它可能无关紧要。

所以,作为回顾:

  • 如果您有时区附加到您想要转换的日期,请使用该信息来确定tm_isdst的值(就是说,我不太确定您如何处理,以防您必须支持所有时区... tzname[]数组只为您提供用户当前的时区。)
  • 在所有其他情况下,使用-1
© www.soinside.com 2019 - 2024. All rights reserved.