【问题标题】:Why is the tm_year member in struct tm relative to 1900 rather than 1970 in C on macosx?为什么 struct tm 中的 tm_year 成员相对于 1900 而不是 macosx 上的 C 中的 1970?
【发布时间】:2018-01-03 11:02:26
【问题描述】:

当我遇到这个问题时,我正在尝试专家 C 编程中的示例。我的程序基本上只做一件事:使用标准的gmtime 函数,看看自 1970 年以来已经过去了多少年。 这是我的程序:

#include <stdio.h>
#include <time.h>

int main(int argc, char** argv) {
    time_t now = time(0);
    struct tm *t = gmtime(&now);
    printf("%d\n", t->tm_year);
    return 0;
}

输出为 117,即过去 1900 的年数。这是出乎意料的,因为我事先检查了time()man gmtime,他们都说它们是相对于纪元时间(1970-1-1 00:00:00):

time() returns the time as the number of seconds since the Epoch,
1970-01-01 00:00:00 +0000 (UTC).

http://man7.org/linux/man-pages/man2/time.2.html

The ctime(), gmtime() and localtime() functions all take an argument of data type 
time_t, which represents calendar time.  When interpreted as an absolute time 
value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 
00:00:00 +0000 (UTC).

http://man7.org/linux/man-pages/man3/ctime.3.html

根据上面的描述,我的程序应该返回47而不是117。这是怎么回事?

macos sierra 10.12.5
Darwin 16.6.0 Darwin Kernel Version 16.6.0: Fri Apr 14 16:21:16 PDT 2017; root:xnu-3789.60.24~6/RELEASE_X86_64 x86_64
Apple LLVM version 8.1.0 (clang-802.0.42)

【问题讨论】:

  • 因为doc says 也是online manual
  • 还有手册页:tm_year The number of years since 1900.
  • 您引用的 ctime(3) 联机帮助页中没有提及 tm_year。它描述了如何解释time_t 值,这是gmtime(3)参数
  • 我没有看到 C 标准对特定零日期的要求。你能提供一个参考吗?你为什么引用 OSX 的 Linux 手册页?
  • 感谢所有文档和手册页:D

标签: c macos time.h


【解决方案1】:

tm_year 字段与 所有 POSIX 兼容平台上的 1900 相关,而不仅仅是在 macOS 上。

struct tm 设计用于解析、显示和操作人类可读的日期。创建它时,通常会写入日期,甚至在没有年份数字的“19”部分的情况下存储日期,而 Y2K 问题大约在 25 年后才出现。因此,将tm_year 设为相对于 1900 可以直接打印为两位数的便利性在当时显然是合理的。

Unix 时间戳与“Unix 纪元”相关,即 1970-01-01 00:00:00 UTC。至于原因,see this Q&A

【讨论】:

  • 感谢您的回答!我 mac 上的/usr/include/time.h 页面说它确实是相对于 1900 年的。
  • @RainbowFizz 如果这个回答对你有帮助,请采纳。
【解决方案2】:

struct tmtm_year 成员相对于 C 库规范中的 1900。所有兼容的标准库都使用它。

tm 结构应至少包含以下成员,顺序不限。成员的语义及其正常范围在 cmets §7.27.2.1 4

中表示
...
int tm_year; // years since 1900

time() 返回一个 time_t 值“可能代表一个 基于特定纪元的日历时间”。这通常是 1970 年 1 月 1 日 0:00:00 通用时间。*nix 系统坚持这一点。1 月 1 日的这个纪元,C 不需要,也没有直接连接到纪元到struct tmtm_year 成员。

【讨论】:

  • 我明白了。所以struct tm 是由 C 标准定义的,与 *nix 约定无关。
  • @RainbowFizz time_t 也是由 C 标准库定义的。它是 C 标准允许各种实现细节,例如日期/时间是 (time_t)0。许多*nix 编译器以一种常见的方式进一步限制了这些细节,例如将(time_t)0 设置为1970 年1 月1 日。
猜你喜欢
  • 2012-02-14
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 2015-02-15
  • 2020-07-23
  • 1970-01-01
  • 1970-01-01
  • 2011-03-07
相关资源
最近更新 更多