Linux-x64 glibc:为什么 2 月 1 日早于 1 月 31 日?

发布于 2024-10-16 03:24:43 字数 1146 浏览 7 评论 0原文

当你调用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风吹过旳痕迹 2024-10-23 03:24:43

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().

甜扑 2024-10-23 03:24:43

为什么 2 月 1 日早于 1 月 31 日?

struct tm 成员的赋值不正确。


.tm_mon 是从零开始的

.tm_mon 是从零开始@吉姆·加里森

// tm.tm_mon = 1;
tm.tm_mon = 1 - 1; // For January

.tm.tm_year 是基于 1900

// tm.tm_year = 2011;
tm.tm_year = 2011 - 1900;

time_t 打印说明符

"%ld" 是不一定是 time_t 的匹配说明符,因此会导致未定义的行为 (UB)。 time_t 甚至可能不是整数类型。建议强制转换为宽签名类型或这个。请注意,tt = mktime(&tm) 在出错时返回 -1 值,因此对于查看 -1 而不是无符号值非常有用。

// printf("%lu\n", tt);
printf("%lld\n", (long long) tt);

.tm_isdst

mktime()当地时间运行。 tm.tm_isdst = 0; 断言时间戳是标准时间(对于PST 大约一月)。此代码是否在一月份的日光时区运行(例如惠灵顿),报告的 tm.tm_hour 可能与预期不同。通常最好让 mktime() 推导 .tm_isdst。否则,在 DST 发生变化时,查找时间戳之间的差异(OP 的更高目标)可能会意外地改变一个小时。

// tm.tm_isdst = 0;
tm.tm_isdst = -1;  // DST information is not available, mktime will adjust.
tt = mktime(&tm)

Why does Feb 1 come before Jan 31?

Incorrect assignments to struct tm members.


.tm_mon is zero based

.tm_mon is zero based@Jim Garrison.

// tm.tm_mon = 1;
tm.tm_mon = 1 - 1; // For January

.tm.tm_year is 1900 based

// tm.tm_year = 2011;
tm.tm_year = 2011 - 1900;

time_t print specifier

"%ld" is not certainly the matching specifier for time_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 that tt = mktime(&tm) returns a -1 value on error, so useful to see -1 and not an unsigned value.

// printf("%lu\n", tt);
printf("%lld\n", (long long) tt);

.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 reported tm.tm_hour may differ from expectations. Usually best to let mktime() deduce .tm_isdst. Otherwise finding the difference between timestamps (OP's higher goal) may shift an hour unexpectedly when spanning a DST change.

// tm.tm_isdst = 0;
tm.tm_isdst = -1;  // DST information is not available, mktime will adjust.
tt = mktime(&tm)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文