【问题标题】:Odd behavior of mktime()mktime() 的奇怪行为
【发布时间】:2010-12-14 07:14:52
【问题描述】:

继续my attempt to create a DateTime class,我正在尝试将“纪元”时间存储在我的函数中:

void DateTime::processComponents(int month, int day, int year, 
                                 int hour, int minute, int second) {
    struct tm time;
    time.tm_hour = hour;
    time.tm_min = minute;
    time.tm_sec = second;
    time.tm_mday = day;
    time.tm_mon = month;
    time.tm_year = year - 1900;
    ticks_ = mktime(&time);

    processTm(time);
}

void DateTime::processTm(struct tm time) {
    second_ = time.tm_sec;
    minute_ = time.tm_min;
    hour_ = time.tm_hour;
    weekday_ = time.tm_wday;
    monthday_ = time.tm_mday;
    yearday_ = time.tm_yday;
    month_ = time.tm_mon;
    year_ = time.tm_year + 1900;
}

对于任意日期processComponents(5,5,1990,1,23,45)(1990 年 6 月 6 日凌晨 1:23:45),它会按预期正确设置所有值。

但是,经过进一步测试,我发现对于 processComponents(0,0,1970,0,0,0)(1970 年 1 月 1 日凌晨 12:00:00),mktime(&time) 导致 time 搞砸了:

time.tm_mon  = 11;
time.tm_mday = 30;
time.tm_year = 69;
time.tm_hour = 23;
time.tm_min  = 0;
time.tm_sec  = 0;

time.tm_isdst  = 0;
time.tm_gmtoff = -18000;
time.tm_zone   = "EST";
time.tm_wday   = 2;
time.tm_yday   = 363;

转换为 1969 年 12 月 31 日晚上 11:00:00 的日期。

我可以验证 mktime() 负责,因为通过注释掉该行,它会正确报告日期和时间为 1970 年 1 月 1 日上午 12:00:00。

为什么mktime() 只会搞乱时代?我应该如何解决/解决这个问题?

谢谢!

【问题讨论】:

    标签: c++ date mktime


    【解决方案1】:

    您将 0 作为 day 参数传递,并将其放入 time.tm_mdaystruct tm 的那个组件(并且只有那个组件)是从 1 开始的,而不是从 0 开始的。

    别问我为什么。

    要指定 1970 年 1 月 1 日凌晨 12:00:00,您可以这样称呼它:

    processComponents(0,1,1970,0,0,0);
    

    作为sdtom mentioned,您需要确保正确设置tm_isdst - 0 表示无效,正数表示有效,负数表示您不知道(在这种情况下mktime()应该尝试猜测)。

    只是让您知道,当我在 MSVC 9 中将您拥有的日期 (0 Jan 1970, 00:00:00) 传递给 mktime() 时,它会返回一个错误(传入的 struct tm 未触及并且返回time_t 值为 -1)。

    【讨论】:

    • 谢谢!当我明确设置 time.tm_isdst = -1 时,一切正常。
    【解决方案2】:

    由于它关闭一小时,我预计夏令时。 time.tm_isdst 的值是否设置在某个地方?如果您没有设置它,它可能会随机设置为 1 或 0,这会影响您的结果。

    【讨论】:

    • +1。我也是这么想的。根据 Python(在 Mac OS X 上),gmtime(0) 返回:time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)。不过,我不确定这证明了什么,因为 Python 在构建 time.struct_time 对象时会对 struct tm 进行一些翻译。
    • tm_isdst 报告为 0。根据我的调试器,我已更新帖子以反映 time 结构的其余部分。
    • 为它指定-1,因为你没有在任何地方设置它并且不知道它:)
    【解决方案3】:

    将所有零传递给mktime() 被解释为“Sun Jan 0 00:00:00 1900”。基于此,需要做一些调整……

    // the input is local time
    // the output is seconds since the epoch
    // The epoch is Jan 1, 1970 @ 0:00 GMT
    time_t mktime_wrapper( int month, int day, int year,
                           int hour=0, int min=0, int sec=0, bool isDST=-1
                         )
       {
       tm t;
       t.tm_sec=sec, t.tm_min=min, t.tm_hour=hour, t.tm_isdst=isDST;
       t.tm_mday=day, t.tm_mon=month-1, t.tm_year=year-1900;
       return mktime( &t );
       }
    

    【讨论】:

      猜你喜欢
      • 2019-09-18
      • 2012-06-06
      • 1970-01-01
      • 2013-12-04
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多