18

我看到很多不同的观点所以想在这里问。

我读到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 无关?

我错过了什么吗?

4

3 回答 3

15

如果可能,您应该避免将 tm_isdst 设置为 -1。系统无法始终仅从日期和时间确定 DST 状态。DST 结束前后的一小时不明确。例如,如果您在mktime()2012 年 11 月 4 日凌晨 1:30 经过,则该信息不足以time_tmktime(). 通常我已经看到mktime()假设标准时间模棱两可,但我还没有看到任何文档可以保证在所有平台上的行为。2012 年 11 月 4 日凌晨 1:30tm_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个输出:

  • 时间_t
  • 修复时间结构

time 结构既是输入又是输出。它被修改mktime()为将所有结构成员返回到标称范围。例如,如果您增加 tm_hour 成员+= 500,这意味着将时间增加 500 小时。tm_hour成员将更改为 00 到 23 的值,并且,tm_day等都tm_mday将相应调整。tm_isdst既是输入又是输出。其值如下:

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

因此 mktime() 将为 tm_isdst 输出 1 或 0,而不是 -1。

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

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

于 2012-08-24T18:49:44.950 回答
5

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

有关这方面的更多信息,请参见您的 tzset() 手册页。符合标准的 mktime() 必须表现得好像它调用了 tzset() 一样。这种避免使用 tm_isdst,IMO。

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

于 2011-12-19T18:24:36.933 回答
0

我认为你确实应该使用-1tm_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
于 2019-04-08T07:42:08.093 回答