为什么struct tm中的tm_year成员相对于1900而不是1970年的C on macosx?

时间:2017-07-27 15:46:51

标签: c macos time.h

当我遇到这个问题时,我正在尝试专家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)

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

tm_year的{​​{1}}成员相对于C库规范的1900。所有兼容的标准库都使用它。

  

struct tm结构应至少包含以下成员,任何顺序。成员的语义及其正常范围在注释§7.27.2.14

中表示
tm

... int tm_year; // years since 1900 返回time()值“,可能代表a 基于特定时期的日历时间“。这通常是1970年1月1日0:00:00世界时。* nix系统坚持这一点。这个1月的时代不是C要求的,并且没有直接连接到time_t tm_year struct tm成员的纪元。