负秒怪异mktime逻辑 [英] Weird mktime logic with negative seconds

查看:150
本文介绍了负秒怪异mktime逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用mktime /本地时间进行时间管理,包括对日期/时间有些沉重的算术。

我发现了一些提供给mktime包含负值的结构TM时,很不可思议。

以低于code。有在洛杉矶DST更改11月3日,2013年如果我TM时间指定为2013年11月4日午夜减去24小时,我得到相同的值2013年11月3日午夜。它为25的小时差UTC-明智的,这是很好的,与isdst = -1可以说,我们正在寻找挂钟时间。同样的,如果我减去1440分钟(24 * 60)。但是,如果我减去86400(24 * 60 * 60)秒,我得到2013年11月3日上午01时。这24小时的区别U​​TC明智的。下面是从下面的code的输出:

  2013年11月3日00:00:00(gmtoff = 0,isdst = -1) -  GT; 2013年11月3日00:00:00(gmtoff = -25200,isdst = 1) - > 1383462000
2013-12--27 00:00:00(gmtoff = 0,isdst = -1) - > 2013年11月3日00:00:00(gmtoff = -25200,isdst = 1) - > 1383462000
2013年11月4日-24:00:00(gmtoff = 0,isdst = -1) - > 2013年11月3日00:00:00(gmtoff = -25200,isdst = 1) - > 1383462000
2013年11月4日00:-1440:00(gmtoff = 0,isdst = -1) - > 2013年11月3日〇时00分00秒(gmtoff = -25200,isdst = 1) - > 1383462000
2013年11月4日00:00:-86400(gmtoff = 0,isdst = -1) - > 2013年11月3日1时○○分00秒(gmtoff = -25200,isdst = 1) - > 1383465600

对于我来说没有任何意义 - 为什么秒区别对待不是几分钟,几小时或几天?我看着男人和C标准,但找不到任何东西。

此行​​为打破了我的一些假设和复杂的事情。是否有人知道一个很好的替代mktime /本地时间(我测试提振,​​ICU和TZ code,我需要的东西都太慢了)。

在此先感谢任何想法:)

 的#include<&time.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&stdlib.h中GT;
字符* printtm(结构TM TM)
{
  静态字符BUF [100];
  sprintf的(BUF,%04d-%02d-%02D 02D%:%02D:%02D(gmtoff =%LD,isdst =%d个),
    tm.tm_year + 1900,tm.tm_mon + 1,tm.tm_mday,
    tm.tm_hour,tm.tm_min,tm.tm_sec,
    tm.tm_gmtoff,tm.tm_isdst);
  返回BUF;
}无效测试(INT Y,INT男,INT D,INT 11H,INT毫米,诠释SS,诠释isdst)
{
  结构TM TM;
  memset的(安培;以旧换新,0,sizeof的(TM));
  tm.tm_year = Y - 1900;
  tm.tm_mon = M - 1;
  tm.tm_mday = D;
  tm.tm_hour = HH;
  tm.tm_min =毫米;
  tm.tm_sec = SS;
  tm.tm_isdst = isdst;
  的printf(%S - >中,printtm(TM));
  time_t的T = mktime(安培; TM);
  的printf(%S - >%LD \\ N,printtm(TM),T);
}
诠释的main()
{
  SETENV(TZ,:美国/洛杉矶,1);
  tzset();  试验(2013,11,03,0,0,0,-1);
  测试(2013,12,-27,0,0,0,-1);
  试验(2013,11,04,-24,0,0,-1);
  试验(2013,11,04,0,-1440,0,-1);
  试验(2013,11,04,0,0,-86400,-1);  返回0;
}


解决方案

使用 mktime 与在结构TM <超出范围的值/ code>和 tm_isdst的== - 1 是有问题的,并在指定的。就个人而言,我认为你的系统是在这里表现的方式是的错误的,但是标准不上它应该如何表现,因此任何这样的使用是不可移植的最好清楚。做算术上的结构TM ,你应该确保 tm_isdst的设置为0或1事前,使明确的结果。

请注意,一个简单的方法做,这是简单地调用 mktime 原始结构TM (用 tm_isdst的== - 1 )应用运算以确定夏令时是否生效前(即填写一个明确的价值 tm_isdst的),然后让你的算法调整后,再次调用它。

I've been using mktime/localtime for time management, including some heavy arithmetic on dates/times.

I noticed something very weird when providing to mktime a struct tm that contains negative values.

Take the code below. There was a DST change in LA on Nov 3rd, 2013. If I specify time in tm as 2013-11-04 midnight and subtract 24 hours, I get the same value as 2013-11-03 midnight. It is 25 hours difference UTC-wise, which is fine, as with isdst=-1 one could say we're looking at 'wallclock-time'. Same if I subtract 1440 minutes (24*60). But, if I subtract 86400 (24*60*60) seconds, I get 2013-11-03 1am. That is 24 hours difference UTC-wise. Here's the output from the code below:

2013-11-03 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-12--27 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 -24:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:-1440:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:00:-86400 (gmtoff=0, isdst=-1) -> 2013-11-03 01:00:00 (gmtoff=-25200, isdst=1) -> 1383465600

For me it doesn't make sense - why are seconds treated differently than minutes, hours and days? I looked at man and the C standard but couldn't find anything.

This behavior breaks some of my assumptions and complicates things. Does someone know a good alternative to mktime/localtime (I tested boost, ICU and tzcode, all too slow for what I need).

Thanks in advance for any thoughts :)

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* printtm(struct tm tm)
{
  static char buf[100];
  sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d (gmtoff=%ld, isdst=%d)",
    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    tm.tm_hour, tm.tm_min, tm.tm_sec,
    tm.tm_gmtoff, tm.tm_isdst);
  return buf;
}

void test(int y, int m, int d, int hh, int mm, int ss, int isdst)
{
  struct tm tm;
  memset(&tm, 0, sizeof(tm));
  tm.tm_year = y - 1900;
  tm.tm_mon = m - 1;
  tm.tm_mday = d;
  tm.tm_hour = hh;
  tm.tm_min = mm;
  tm.tm_sec = ss;
  tm.tm_isdst = isdst;
  printf("%s -> ", printtm(tm));
  time_t t = mktime(&tm);
  printf("%s -> %ld\n", printtm(tm), t);
}


int main()
{
  setenv("TZ", ":America/Los_Angeles", 1);
  tzset();

  test(2013,11,03, 0,0,0, -1);
  test(2013,12,-27, 0,0,0, -1);
  test(2013,11,04, -24,0,0, -1);
  test(2013,11,04, 0,-1440,0, -1);
  test(2013,11,04, 0,0,-86400, -1);

  return 0;
}

解决方案

Using mktime with out-of-range values in the struct tm and tm_isdst==-1 is problematic and under-specified. Personally, I think the way your system is behaving here is wrong, but the standard isn't clear on how it's supposed to behave, and thus any such usage is non-portable at best. To do arithmetic on struct tm, you should make sure tm_isdst is set to either 0 or 1 beforehand, so that the result of unambiguous.

Note that one easy way to do this is to simply call mktime on the original struct tm (with tm_isdst==-1) before applying the arithmetic to determine whether daylight time is in effect (i.e. to fill in a definitive value for tm_isdst) then call it again after making your arithmetic adjustments.

这篇关于负秒怪异mktime逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆