保存自 Unix 纪元以来的tv_sec
完整秒数 - 1970-01-01 00:00:00 +00:00 - 并且tv_usec
(或tv_nsec
使用更现代的struct timespec
)保存小数部分 - 值 [0..999,999]微秒struct timeval
和 [0..999,999,999] 纳秒struct timespec
.
在 64 位整数普及之前的日子里,time_t
它是 32 位有符号类型,并且在 2038 年 1 月“用完”——自纪元以来将有超过 20 亿秒。没有空间将亚秒单位存储在一个整数中。
-2147483647 = 1901-12-13 20:45:53 +00:00
+2147483647 = 2038-01-19 03:14:07 +00:00
即使是现在,如果处理纳秒,您需要 30 位来表示最多 999,999,999 纳秒(以及 20 位来表示最多 999,999 微秒)。纳秒的要求意味着尝试缩放 64 位数字来表示秒和纳秒是不明智的——Y2K38 问题将推迟大约 280 年,而两部分解决方案将其推迟到宇宙结束后,对于每个人来说应该足够长。(如果我还在的话,我计划在 5000-01-02 开始研究 Y10K 问题。)
因此,虽然不理想,但两部分结构使得使用接受time_t
值的常规格式化函数变得很容易——它们有很多,还有那些struct tm
从值派生的time_t
。他们的算术并不难。
我注意到,在某些方面,POSIX 未对两者struct timeval
进行struct timespec
指定。tv_usec
a 的或tv_nsec
部分的符号是什么,struct timeval
或者组件struct timespec
是否tv_sec
为负(请参阅自纪元以来的秒数-如果年份 <1970 或值为负,则关系未定义)。POSIX 保留了未定义的负值的行为tv_sec
,这可能是明智的,但确实让生活有点困难。当然,还有“儒略历和公历是哪个国家的哪个部分什么时候切换的”的问题。和“有零年吗?” 这也必须处理。什么时候time_t
是一个 32 位的数字,它可以追溯到 1901 年 12 月,这在很大程度上避免了这些问题(但俄罗斯直到十月革命之后才从儒略转换为公历,这发生在公历 11 月)。现在这time_t
通常是一个 64 位数字,公元前(或 BCE)年也变得可表示。
tv_usec
打印或tv_nsec
部分时要小心。%.6d
请记住通过使用微秒、纳秒来添加足够的前导零%.9ld
,其中必要的转换说明符(d
vs ld
vs ...)tv_usec
在 POSIX 中没有明确定义——但d
通常是正确的。(tv_nsec
成员是long
; 这很容易和可靠。)