当前位置: 首页 > 知识库问答 >
问题:

奇怪的mktime逻辑,秒数为负

谢哲瀚
2023-03-14

我在时间管理上使用过很多次。

当向mktime提供一个包含负值的结构tm时,我注意到一些非常奇怪的事情。

以下面的代码为例。2013年11月3日,洛杉矶的DST发生了变化。如果我在tm中指定时间为2013-11-04午夜,并减去24小时,则得到的值与2013-11-03午夜相同。它与UTC的时差为25小时,这很好,就像isdst=-1一样,我们可以说是在看“Wallcock time”。减去1440分钟(24*60)也是一样。但是,如果我减去86400(24*60*60)秒,我得到2013-11-03凌晨1点。就UTC而言,这是24小时的差异。下面是代码的输出:

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

对我来说,这毫无意义——为什么秒与分钟、小时和天的待遇不同?除了C,我什么都找不到。

这种行为打破了我的一些假设,使事情变得复杂。有人知道mktime/localtime的好替代方案吗(我测试了boost、ICU和tzcode,速度太慢了,无法满足我的需要)。

提前感谢任何想法:)

#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;
}

共有1个答案

仲学真
2023-03-14

struct tmtm_isdst==-1中使用mktime时,值超出范围是有问题的,并且未指定。就我个人而言,我认为您的系统在这里的行为方式是错误的,但标准并不清楚它应该如何行为,因此任何此类使用最多都是不可移植的。要在struct tm上进行算术运算,您应该确保tm_isdst事先设置为0或1,以便计算结果明确无误。

请注意,一种简单的方法是,在应用算术来确定日光时间是否有效(即为tm_isdst填写一个确定值)之前,只需在原始struct tm(使用tm_isdst==-1)上调用mktime),然后在进行算术调整后再次调用它。

 类似资料:
  • 使用 uni-app 的 renderjs,监听逻辑层的数据: 更新任何一个逻辑层的变量,updateXXX 都会被调用。请教这是什么原因?

  • 我正在处理一个多模块的Maven项目,其中每个模块都是一个Spring Boot应用程序(即打包为一个可执行的jar)。有些模块依赖于其他模块。该项目使用platform-bom版本1.1.4版本。 我发现了一个我认为奇怪的逻辑来决定使用哪些应用程序属性文件--尽管没有明确地与https://docs.spring.io/spring-boot/docs/current/reference/htm

  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方

  • 问题内容: 我在GregorianCalendar类中遇到一个奇怪的行为,我想知道我是否真的做得不好。 仅当初始化日期的月份的实际Maximum大于我将日历设置为的月份时,才追加此值。 这是示例代码: 我知道问题是由于日历初始化日期是31天(可能是5月),与设置为2月(28天)的月份混淆了。修复很容易(只需在设置年和月之前将day_of_month设置为1),但是我想知道这确实是想要的行为。有什么

  • 问题内容: 我正在为一个问题而苦苦挣扎,我不明白为什么它不起作用。如何通过将变量传递并转换为? 为什么在顶部代码段中不起作用,但在行下方的底部代码段中起作用? 唯一的区别似乎是添加了一个额外的变量,该变量也被键入为? 问题答案: 该是一种原始类型,同时是一个普通的Java类。您不能在原始类型上调用方法。但是该方法在上可用,如javadoc中所示 有关这些原始类型的更多信息,请参见此处

  • 问题内容: 为什么的到哪里去了? 问题答案: 删除任何字符,并从字符串的开头和结尾。