在C中检测未来日期的DST标志

时间:2011-03-13 08:20:41

标签: c timezone dst

我有一个系统,我以字符串的形式提供日期和时间,例如“2011-03-13 03:05:00”。我可能会在“2011-03-13 01:59:00”收到此字符串,我需要知道从现在到字符串中的时间之间的时间长度(由于DST更改,时间为6分钟)。

我有解析字符串并创建tm结构的代码,然后使用time_t将其转换为mktime。问题是我必须在解析时间时手动设置tm_isdst标志,因此我正在寻找一种方法来检测是否应该设置tm_isdst。有什么想法吗?

我对如何处理有2个2AM特定于我的应用程序的情况有一些想法,但我仍然需要一种方式来说“如果这个时间是当前的系统时间,那么DST会在影响?“

编辑:基于Pete建议的想法。如果我:

怎么办?
  1. 检查收到的时间和当前系统时间是否有不同的小时:
  2. 如果同一小时但是过去,请在当前时间添加一小时,看看DST标志是否已更改。 (如果同一小时和将来,假设与当前时间相同的DST标志(这是一年中的大部分时间))
  3. 如果不同的小时,我们将1小时添加到当前系统时间并查看DST标志是否已更改
  4. 思想?

3 个答案:

答案 0 :(得分:5)

根据man mktime(在Linux上,强调我的):

  

tm_isdst中指定的值   字段通知mktime()是否   夏令时(DST)在   对tm中提供的时间的影响   结构:正值表示DST   有效;零意味着DST是   没有效果; 和负值   意味着mktime()应该(使用   时区信息和系统   数据库)试图确定   DST是否有效   指定时间

你试过吗?

(这是“试图确定”,因为有些时候基本上是模棱两可的。)

你可以尝试真正模糊的时间是看mktime是否“纠正”你的dst旗帜。我敢打赌这不是便携式的。示例代码,转换设置于2010年10月31日,凌晨3点在我的时区(欧洲/巴黎)回滚至凌晨2点:

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

void printit(int hour, int isdst)
{
    struct tm when;
    memset(&when, 0, sizeof(when));
    when.tm_sec = 0;
    when.tm_min = 30;
    when.tm_hour = hour;
    when.tm_mday = 31;
    when.tm_mon = 9;
    when.tm_year = 110;
    when.tm_isdst = isdst;
    time_t secs = mktime(&when);
    fprintf(stdout, "%2d %ld %d %s", isdst, secs, when.tm_isdst, asctime(&when));
}

int main(int argc, char **argv)
{
    for (int i=1; i<4; i++) {
        fprintf(stdout, "At %dam\n", i);
        printit(i, 1);
            printit(i, 0);
        printit(i, -1);
    }
}

输出是:

At 1am
 1 1288481400 1 Sun Oct 31 01:30:00 2010
 0 1288485000 1 Sun Oct 31 02:30:00 2010
-1 1288481400 1 Sun Oct 31 01:30:00 2010
At 2am
 1 1288485000 1 Sun Oct 31 02:30:00 2010
 0 1288488600 0 Sun Oct 31 02:30:00 2010
-1 1288488600 0 Sun Oct 31 02:30:00 2010
At 3am
 1 1288488600 0 Sun Oct 31 02:30:00 2010
 0 1288492200 0 Sun Oct 31 03:30:00 2010
-1 1288492200 0 Sun Oct 31 03:30:00 2010

如您所见,当时间不明确时,mktime会通过设置右tm_isdst并抵消时间来纠正它。 当 不明确时,tm_isdst不会更改。

答案 1 :(得分:1)

依靠我的蛮力方式。这可能有效:

  1. 完全解析时间字符串并将其放入tm结构
  2. 调用mktime()在该tm struct
  3. 上获取time_t val
  4. 为新的time_t val添加6分钟(使用6分钟的值)?
  5. 调用asctime()或类似命令从该time_t val获取tm结构(即“故障时间”)
  6. 在这个tm结构中你刚刚从asctime()返回,tm_isdst会告诉你什么?
  7. - 皮特

    是的,你是对的:整个时间的混乱是非常糟糕的(甚至是恶意的,有时候认为)旨在让程序员绊倒并为你的懒惰/迂腐/愚蠢的CS教练提供完美的闭卷测验问题

答案 2 :(得分:0)

我和你有同样的问题,我不知道这个解决方案能解决它吗?

struct tm *local_tm;
time_t t;
t = time(NULL);
local_tm = localtime(&t);
local_tm->tm_year = 2012-1900;
local_tm->tm_mon = 9 - 1;
local_tm->tm_mday = 13;
time_t utc_time = mktime(local_tm);

我认为如果你从系统得到tm,那么tm_isdst字段已经设置好了,所以剩下的就是更改除tm_isdst之外的其他字段,我不确定它是否正确,但我会尝试一下,如果它有效对我来说,我会给予进一步的反馈。