Linux-x64 glibc:为什么 2 月 1 日早于 1 月 31 日?
当你调用 mktime() 时,2 月 1 日似乎早于 1 月 31 日。这是为什么?我做错了什么还是这是 glibc 的错误?
这是代码:
struct tm tm;
time_t tt;
memset(&tm, 0, sizeof(tm));
tm.tm_year = 2011;
tm.tm_mon = 1;
tm.tm_mday = 31;
tm.tm_hour = 11;
tm.tm_min = 41;
tm.tm_sec = 28;
tm.tm_isdst = 0;
tt = mktime(&tm);
printf("Time now %d-%d-%d %d:%d:%d (%s) = %lu\n",
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone, tt);
memset(&tm, 0, sizeof(tm));
tm.tm_year = 2011;
tm.tm_mon = 2;
tm.tm_mday = 1;
tm.tm_hour = 1;
tm.tm_min = 1;
tm.tm_sec = 1;
tm.tm_isdst = 0;
tt = mktime(&tm);
printf("Time now %d-%d-%d %d:%d:%d (%s) = %lu\n",
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone, tt);
这是输出:
Time now 2011-2-3 11:41:28 (PST) = 61257325288
Time now 2011-2-1 1:1:1 (PST) = 61257114061
请注意,最初的目的是比较两个 time_t。这个问题导致第一个日期/时间看起来晚于第二个,这显然是一个问题。
这只是用“gcc test.c”编译并在 Ubuntu 9.10、gcc 版本 4.4.1 (Ubuntu 4.4.1-4ubuntu8)、libc-2.10.1-0ubuntu15
上使用“./a.out”运行 32-位系统结果与预期一致 - 即与 64 位结果完全不同!
有人愿意确认/反驳这个结果和/或深入了解我可能做错了什么吗?
When you call mktime(), Feb 1 seems to come before Jan 31. Why is this? Am I doing something wrong or is this a bug in glibc?
Here's the code:
struct tm tm;
time_t tt;
memset(&tm, 0, sizeof(tm));
tm.tm_year = 2011;
tm.tm_mon = 1;
tm.tm_mday = 31;
tm.tm_hour = 11;
tm.tm_min = 41;
tm.tm_sec = 28;
tm.tm_isdst = 0;
tt = mktime(&tm);
printf("Time now %d-%d-%d %d:%d:%d (%s) = %lu\n",
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone, tt);
memset(&tm, 0, sizeof(tm));
tm.tm_year = 2011;
tm.tm_mon = 2;
tm.tm_mday = 1;
tm.tm_hour = 1;
tm.tm_min = 1;
tm.tm_sec = 1;
tm.tm_isdst = 0;
tt = mktime(&tm);
printf("Time now %d-%d-%d %d:%d:%d (%s) = %lu\n",
tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_zone, tt);
And here's the output:
Time now 2011-2-3 11:41:28 (PST) = 61257325288
Time now 2011-2-1 1:1:1 (PST) = 61257114061
Note that the original intention was to compare two time_t's. This issue causes the first date/time to appear to be later than the second, which is obviously a bit of a problem.
This is just compiled with "gcc test.c" and run with "./a.out" on Ubuntu 9.10, gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8), libc-2.10.1-0ubuntu15
On a 32-bit system the results are as expected - i.e. completely different to the 64 bit result!
Would anyone care to confirm/refute this result and/or give some insight into what I may be doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
tm_mon 是从零开始的,因此您尝试设置 2 月 31 日,该日期已标准化。这是 mktime() 定义的链接。
tm_mon is zero-based, so you attempted to set February 31st, which got normalized. Here's a link to the definition of mktime().
对
struct tm
成员的赋值不正确。.tm_mon
是从零开始的.tm_mon
是从零开始@吉姆·加里森。.tm.tm_year
是基于 1900time_t
打印说明符"%ld"
是不一定是time_t
的匹配说明符,因此会导致未定义的行为 (UB)。time_t
甚至可能不是整数类型。建议强制转换为宽签名类型或这个。请注意,tt = mktime(&tm)
在出错时返回 -1 值,因此对于查看 -1 而不是无符号值非常有用。.tm_isdst
mktime()
按当地时间运行。tm.tm_isdst = 0;
断言时间戳是标准时间(对于PST 大约一月)。此代码是否在一月份的日光时区运行(例如惠灵顿),报告的tm.tm_hour
可能与预期不同。通常最好让mktime()
推导.tm_isdst
。否则,在 DST 发生变化时,查找时间戳之间的差异(OP 的更高目标)可能会意外地改变一个小时。Incorrect assignments to
struct tm
members..tm_mon
is zero based.tm_mon
is zero based@Jim Garrison..tm.tm_year
is 1900 basedtime_t
print specifier"%ld"
is not certainly the matching specifier fortime_t
, thus incurring undefined behavior (UB).time_t
might not not even be an integer type. Recommend a cast to a wide signed type or this. Note thattt = mktime(&tm)
returns a -1 value on error, so useful to see -1 and not an unsigned value..tm_isdst
mktime()
operates on local time.tm.tm_isdst = 0;
asserts the time stamp is standard time (reasonable for PST about January). Had this code been run in a timezone with daylight time in January (e.g. Wellington), the reportedtm.tm_hour
may differ from expectations. Usually best to letmktime()
deduce.tm_isdst
. Otherwise finding the difference between timestamps (OP's higher goal) may shift an hour unexpectedly when spanning a DST change.