2

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

我有代码可以解析字符串并创建一个tm结构,然后将其转换为time_twith mktime。问题是我tm_isdst在解析时间时必须手动设置标志,所以我正在寻找一种方法来检测是否tm_isdst应该设置。有任何想法吗?

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

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

  1. 检查收到的时间和当前系统时间是否有不同的小时:
  2. 如果同一小时但在过去,则在当前时间添加一个小时,然后查看 DST 标志是否更改。(如果同一小时和将来,假设与当前时间相同的 DST 标志(这是一年中的大部分时间))
  3. 如果不同的时间,我们在当前系统时间上增加 1 小时,看看 DST 标志是否改变

想法?

4

3 回答 3

5

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

tm_isdst 字段中指定的值通知 mktime() 对于 tm 结构中提供的时间,夏令时 (DST) 是否有效:正值表示 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是不改变的。

于 2011-03-13T08:41:24.127 回答
1

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

  1. 完全解析时间字符串,放入tm结构中
  2. 调用 mktime() 以获取该 tm 结构的 time_t val
  3. 将 6 分钟添加到新的 time_t val (使用 6 分钟的什么值?)
  4. 调用 asctime( ) 或类似方法从 time_t val 中获取 tm 结构(即“分解时间”)
  5. 在这个 tm 结构中,你刚从 asctime() 回来,tm_isdst 告诉你什么?

——皮特

是的,你是对的:整个时间混乱是非常糟糕的(甚至是恶意的,有时有人认为)旨在绊倒程序员,并为你的妓女提供完美的闭卷测验问题懒惰/迂腐/白痴的 CS 讲师。

于 2011-03-13T08:31:55.827 回答
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 之外的其他字段,我不确定它是否正确,但我会尝试一下,如果它适用于我,我会给出进一步的反馈。

于 2012-09-13T06:19:25.410 回答