给定日期/时间作为字符串,知道当时是不是是 DST 的最佳方法是啥?

Posted

技术标签:

【中文标题】给定日期/时间作为字符串,知道当时是不是是 DST 的最佳方法是啥?【英文标题】:Given a Date/Time as a string, what is the best way to know if it was DST at that time?给定日期/时间作为字符串,知道当时是否是 DST 的最佳方法是什么? 【发布时间】:2012-03-13 06:23:04 【问题描述】:

假设给了我这样一个字符串:"2009-4-9",表示 2009 年 4 月 9 日。假设首先,我只关心本地时间(我也关心其他时区,但我'将首先解决简单的事情)。了解夏令时是否在当时有效的最佳方式是什么?

您可以假设系统具有正确更新的时区文件,例如/etc/localtime,并且我对便携式解决方案感兴趣。 c 或 c++ 都可以接受。

你也可以假设我只关心过去或现在的日期,而不关心未来。

目前我有一个看起来像这样的“hack”(我知道 localtime_r 是一个库扩展,但它与我可以使其便携的相同功能足够接近)

struct tm tm;
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) 
    // convert the broken down structure into seconds since epoch
    const time_t t = mktime(&tm);

    // convert it back to a broken down structure, this seems pointless at first...
    // but libc will fill out fields such as tm_isdst
    localtime_r(&t, &tm);

    printf("DST : %d\n", tm.tm_isdst);

虽然这行得通(而且似乎是一种非常有效的方法),但我觉得来回转换很愚蠢。有没有更好的办法?

【问题讨论】:

您关心一天中的什么时间?它可能是一天开始时的一个偏移量和一天结束时的另一个偏移量...... @JonSkeet:好问题,您可以假设一天中的任何时间。我敢肯定这会使问题进一步复杂化......实际上,标准工作时间左右的时间是常见的用例。 【参考方案1】:

您根本不需要致电localtime_r()mktime() 规范化您传递的 struct tm,包括将 tm_isdst 设置为非负值,如果它被传递到 -1。所以你只需要:

struct tm tm =  0 ;
// convert the time string to a broken down structure in localtime
if(strptime("2009-4-9", "%Y-%m-%d", &tm)) 
    tm.tm_isdst = -1;
    // normalise the broken down structure - this calculates tm_isdst
    mktime(&tm);

    printf("DST : %d\n", tm.tm_isdst);

mktime() 的这种行为是 C 标准所要求的;例如,C99 说:

mktime函数转换故障时间,表示为 当地时间,在timeptr 指向的结构中放入日历 与返回的值具有相同编码的时间值 time 函数。 tm_wday 的原始值和 tm_yday结构的组件被忽略了,原来的 其他组件的值不限于范围 如上所述。276 成功完成后, 设置了结构的tm_wdaytm_yday 组件 适当地,并且其他组件被设置为代表 指定的日历时间,但其值强制为范围 如上所示; tm_mday 的最终值直到 tm_montm_year 已确定。

脚注 276 明确指出 tm_isdst 成员:

276) 因此,tm_isdst 的正值或零值会导致 mktime 函数分别假设夏令时, 在指定时间内是否有效。负值导致 它试图确定夏令时是否有效 指定时间。

【讨论】:

这是记录和/或标准行为吗?还是只是副作用?如果这是标准行为,请分享您的来源。 @EvanTeran:C标准要求;我已更新答案以包含相关部分。【参考方案2】:

从 UTC 到本地时间的转换不是可逆函数。例如,在秋季,当时钟跳回一小时时,当地时间 02:00 和 03:00 之间会出现两次。给定此时间间隔内的时间,无法确定本地时间是在本地 daylight 时间的特定 UTC 时间,还是在本地 的一小时后发生标准时间

【讨论】:

这个问题似乎只涉及日期,我认为这将是该日期的午夜。我认为 DST 过渡特别避开了午夜。 这是一个我没有想到的好点。出于我的需要,这可能被认为是可接受的情况,因为所讨论的时间通常在工作时间左右。 @MarkRansom:再想一想。例如,巴西的过渡时间是在午夜。你不应该假设午夜总是存在 - 或者它只发生一次。 @MarkRansom:不幸的是,我也担心时间问题。 :-/ @MarkRansom:我刚刚通过 Noda Time 运行了那个“查询”,有一些例子,是的。朱巴和喀土穆都在 2000 年 1 月 15 日下午 1 点进行了过渡。那是最接近中午的时间,但还有很多其他的例子,人们会醒着。例如,复活节岛的过渡时间看起来像是当地时间晚上 10 点->11 点和晚上 10 点->9 点。【参考方案3】:

我之前在 C 语言中进行过多次转换,我认为您几乎可以按照我的方式进行转换。据我所知,localtime_r 及其亲属可能是您唯一的选择(除非有一些第三方日期库。)当然,Greg Hewgill 对于时间切换之间的“灰色时间”是正确的。

【讨论】:

以上是关于给定日期/时间作为字符串,知道当时是不是是 DST 的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在python中获取下一次DST更改的时间

如何确定给定时区中的给定时间是不是在postgresql中是DST?

Java 8 的新 Java 日期时间 API 是不是负责 DST?

给定区域的 pytz 中的 DST 偏移量错误

在 DST 更改发生时将字符串解析为日期

如何确定 DST 何时在 Python 中的特定位置开始或结束? [复制]