【问题标题】:Wrong time with localtime()localtime() 时间错误
【发布时间】:2012-11-30 11:17:15
【问题描述】:

在我的服务器上运行date会得到正确的时间。但是在 C(++) 中使用 localtime() 时我走错了时间。

运行date:Fr 30. Nov 12:15:36 CET 2012

使用localtime()Fr 30 Nov 2012 11:15:36 CET

这里有什么问题?

操作系统:Debian 5.0.10

一些代码:

struct tm* today;
today = localtime(...);
strftime(timeBuffer,50,myConnection.getMetaData().getDateFormat().c_str(),today);

【问题讨论】:

  • 不是专家,在我看来,夏季/冬季时间存在问题。日期可能会考虑到这一点,并根据具体情况增加 1 或 2 小时。
  • 您需要告诉我们myConnection.getMetaData().getDateFormat().c_str() 是什么。你是硬编码 CET 还是%z?这里有点不对劲。 (是的,我知道这是一篇旧帖子!)
  • @LightnessRacesinOrbit :这里有一些严重的坟墓挖掘嘿。但这也是一件好事,因为答案确实不合适。参考。我在下面对我的回答发表评论。

标签: c++ c


【解决方案1】:

免责声明:此答案是在添加任何提及 strftime 之前编写的,是对时间戳 1 小时差异的直觉反应。现在回想起来,这 1 小时的差异不可能是由于 DST(因为日期不是夏天),而是可能显示 UTC 时间戳(UTC 和 CET 之间的 1 小时差异)。

很遗憾,答案已被接受,所以我无法删除它。更不幸的是,如果没有其他信息,就无法回答这个问题。

在此处保留原始答案以获得完全透明,但要知道它并没有解决所提出的问题:

localtime 返回的struct tm 有一个tm_isdst 字段,指示夏令时 (DST) 是否有效。格式化时间时需要考虑该字段。

尝试使用asctime 来格式化时间,例如。 :

puts(asctime(today));

【讨论】:

  • 实际上 asctime() 也考虑到了 tm_isdst 所以就 OP 的预期而言,时间仍然是“错误的”。
  • to downvoters :这个答案是在任何提及 strftime 之前写的,是对时间戳 1 小时差异的直觉反应。现在回想起来,这 1 小时的差异不可能是由于 DST(因为日期不是夏天),而是可能显示 UTC 时间戳(UTC 和 CET 之间的 1 小时差异)。我猜要么是操作平台上的时区设置出现了一些诡计,要么是问题不准确。无论如何,我会在短时间内删除这个答案,因为它现在只能使读者感到困惑。
【解决方案2】:

我在编写日期调整例程时遇到了同样的问题。将 86400 秒(= 1 天)添加到任何给定的日期时间值应该会导致日期时间值增加一天。然而在测试中,输出值总是在预期输出上增加一小时。例如,'2019-03-20 00:00:00' 增加 86400 秒导致 '2019-03-21 01:00:00'。反过来也发生了:'2019-03-21 00:00:00' decremented by -86400 导致 '2019-03-20 01:00:00'。

解决方案(莫名其妙地)是从最终间隔中减去 3600 秒(一小时),然后再将其应用于输入日期时间。

解决方案(感谢@Lightness-Races-in-Orbit 提供的帮助)是在调用mktime() 之前将tm_isdst 设置为-1。这告诉mktime() 输入日期时间值的 DST 状态未知,并且mktime() 应该使用系统时区数据库来确定输入日期时间值的正确时区。

该函数(如下更正)允许对天数进行任何整数调整,现在可以产生始终如一的正确结果:

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

/*******************************************************************************
 *  \fn             adjust_date()
 *******************************************************************************/

int adjust_date(
                        char    *original_date,
                        char    *adjusted_date,
                        char    *pattern_in,
                        char    *pattern_out,
                        int      adjustment,
                        size_t   out_size)
{
/*
struct tm {
    int tm_sec;         // seconds          0-59
    int tm_min;         // minutes          0-59
    int tm_hour;        // hours            0-23
    int tm_mday;        // day of the month 1-31
    int tm_mon;         // month            0-11
    int tm_year;        // year       minus 1900
    int tm_wday;        // day of the week  0-6
    int tm_yday;        // day in the year  0-365
    int tm_isdst;       // daylight saving time 
};
*/
    struct tm day;

    time_t one_day = 86400;
//  time_t interval = (one_day * adjustment) - 3600;
    time_t interval = (one_day * adjustment);

    strptime(original_date, pattern_in, &day);

    day.tm_isdst = -1;
    time_t t1 = mktime(&day);

    if (t1 == -1) {
        printf("The mktime() function failed");
        return -1;
    }

    time_t t2 = t1 + interval;

    struct tm *ptm = localtime(&t2);

    if (ptm == NULL) {
        printf("The localtime() function failed");
        return -1;
    }

    strftime(adjusted_date, out_size, pattern_out, ptm);

    return 0;
}

/*******************************************************************************
 *  \fn             main()
 *******************************************************************************/
int main()
{
    char    in_date[64]     = "20190321000000" ,
            out_date[64],
            pattern_in[64]  = "%Y%m%d%H%M%S",
            pattern_out[64] = "%Y-%m-%d %H:%M:%S";

    int     day_diff = -1,
            ret = 0;

    size_t  out_size = 64;

    memset(out_date, 0, sizeof(out_date));

    ret = adjust_date(in_date, out_date, pattern_in, pattern_out, day_diff, out_size); 

    if (ret == 0)
    {
        printf("Adjusted date: '%s'\n", out_date);
    }

    return ret;
}

希望这对某人有所帮助。非常感谢您富有建设性的 cmets。

【讨论】:

  • “将 86400 秒(= 1 天)添加到任何给定的 datetime 值应该会导致 datetime 值增加一天” Nooooooo。不是每天都有 86400 秒。首先,根据时基,有闰秒(尽管如果您使用的是 UNIX 时间戳,那没关系,因为 UNIX 会忽略闰秒,而是将时钟转过它们-.-)。其次,有 DST 更改(如果您正在了解时区)。仅仅删除一个小时是一个黑客,几乎肯定会在某个时候为你打破。相反,不要这样做来增加时间戳!
  • (很可能您的逻辑的一部分考虑 DST 而另一部分不考虑 - 您在 12 月尝试过时间戳吗?)
  • 此外,虽然这本身可能是一个有趣的问题,但这个答案似乎并没有真正解决提出的问题,抱歉
  • 尤里卡,@Lightness-Races-in-Orbit,你是个天才! true 解决方案是在调用mktime() 之前将tm_isdst 设置为-1。这告诉mktime() 输入日期时间值的 DST 状态是未知的,并且mktime() 应该使用系统时区数据库来确定输入日期时间值的正确时区。该函数(如上所述)允许对天数进行任何整数调整,现在可以产生始终正确的结果。希望这可以阐明原始发帖人的问题,因为mktime()localtime() 是相关的。
  • 我有我的时刻:P
【解决方案3】:

处理日期时间很容易出错,并且通常经过严格测试。我总是推荐使用 boost::date_time http://www.boost.org/doc/libs/1_52_0/doc/html/date_time.html

这里有很好的例子http://en.highscore.de/cpp/boost/datetime.html

【讨论】:

    【解决方案4】:

    你试过了吗? :

     time_t rawtime;
     struct tm * today;
    
     time ( &rawtime );
     today= localtime ( &rawtime );
     puts(asctime (today));
    

    【讨论】:

      猜你喜欢
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 2017-08-14
      • 1970-01-01
      • 2023-01-13
      相关资源
      最近更新 更多