mktime和tm_isdst

har*_*ari 14 c unix time freebsd mktime

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

我看了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. 
Run Code Online (Sandbox Code Playgroud)

我的问题是,不tm_isdst应该-1让系统决定它的dst是否与代码成为dst不可知的那样?

我错过了什么吗?

Ric*_*ahn 10

如果可能,您应该避免将tm_isdst设置为-1.系统无法始终仅从日期和时间确定DST状态.在夏令时结束之前和之后的一小时,这是模棱两可的.例如,如果您在mktime()2012年11月4日凌晨1:30 过去,那么这些信息不足以从中获取正确的time_tmktime().通常我看到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;
}
Run Code Online (Sandbox Code Playgroud)

这会产生:

Difference is 1.000000 hour(s)
Run Code Online (Sandbox Code Playgroud)

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

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

  • time_t的
  • 修复时间结构

时间结构既是输入又是输出.它被修改mktime()为将所有结构成员返回到标称范围.例如,如果增加tm_hour成员+= 500,则意味着将时间增加500小时.的tm_hour构件将被改变为值00〜59,以及tm_day,tm_mday和等等都将被相应地调整.tm_isdst也是输入和输出.其价值如下:

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

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

-1是一个可能的输入,但我认为它意味着"未知".不要将其视为"自动确定"的含义,因为一般情况下,mktime()不能总是自动确定它.

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

  • 好吧,如果你不知道DST,你需要自己确定(祝你好运),或者将它设置为`-1`.没有其他选择.如果你把它设置为0,你就得不到任何保证错误的DST,如果你把它设置为1你强制DST也保证错误. (4认同)
  • @RichJahn:它存储在一个数据库中:大约每个 UNIX/Linux 系统的 TZ 数据库。关于在任何给定时间内从那里检索它的最简单方法是在 tm_isdst 设置为 -1 的情况下执行 mktime ... 你还记得 DST 更改何时发生吗?要求用户提供这些信息是不合理的。“如果可能,您应该避免将 tm_isdst 设置为 -1 *。*” - 在哪些合理、常见的使用场景中是可能的? (2认同)
  • @SF。我的全部观点是“它”没有存储在任何地方。电脑不知道。以此类推,如果我说:绝对值是5,原来的数字是正数还是负数?除非它是一个读心程序,否则你无法编写程序来解决这个问题。答案是:我不知道,你告诉我。我知道 2017 年 11 月 5 日午夜是美国 CDT,凌晨 5:00 是美国 CST。但是凌晨 1 点 30 分?我不知道,你告诉我。如果时间不明确,我编写的应用程序会使其成为致命错误或提示用户。不幸的是,我认为大多数日期选择器 UI 完全忽略了这个问题。 (2认同)

jim*_*ara 5

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

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

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