当您尝试使用 进行日历算术time_t
时,您自然要担心 的类型和表示time_t
,这当然是实现定义的。它几乎总是一个有符号的整数类型。在 Unix 和现代 MacOS 系统上,它是 1970 年以来的几秒钟,为了兼容性,我认为它也可以在 Windows 上以这种方式使用。它往往是 32 位。综上所述,它通常可以表示 1901 年 12 月 13 日到 2038 年 1 月 18 日之间的日期。
实际上,当我将tm_year
代码中的行更改为
referenceDateComponent.tm_year = 60;
该代码工作并打印了 1721200226,大约是 19921 天或 54.5 年,这正是 1960 年 12 月 31 日和今天之间的差异。
但是,如果您设置tm_year
为负数,您将要求 1900 年之前的日期,而使用time_t
我们一直在讨论的典型定义是行不通的。
(确实,还有其他可能性time_t
。它可能是浮点数。它可能是无符号的而不是有符号的。它可能是 64 位类型,这意味着它的范围将近 600,000,000,000 年,顺便说一下,它不止一个32 位tm_year
可以容纳。)
因此,尽管这里有几个反对者告诉你不要这样做,虽然在时区、闰秒和公历以外的日历方面肯定有很多晦涩难懂的问题,但你通常可以time_t
不用为日期做基本的日历数学在 20 世纪和本世纪直到 2038 年,臭名昭著的“ Y2.038K 问题”即将到来。(我担心它会比不那么臭名昭著的千年虫问题更糟,但那是另一回事了。)
正如我所说,您的代码适用于 1970 年之前的日期。这是我建议用于time_t
基于简单的日期计算的代码(以及已经提到的警告):
time_t makedate(int year, int month, int day)
{
struct tm tm = {0};
tm.tm_hour = 12;
tm.tm_min = tm.tm_sec = 0;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_isdst = -1;
return mktime(&tm);
}
int main()
{
long int d = difftime(makedate(2015, 7, 17), makedate(2015, 6, 1));
printf("%ld sec = %ld days = %.2f years\n", d, d/86400, d/86400./365.25);
d = difftime(makedate(2015, 7, 17), makedate(2014, 7, 17));
printf("%ld sec = %ld days = %.2f years\n", d, d/86400, d/86400./365.25);
d = difftime(makedate(1975, 7, 17), makedate(1965, 7, 17));
printf("%ld sec = %ld days = %.2f years\n", d, d/86400, d/86400./365.25);
d = difftime(makedate(1950, 1, 11), makedate(1925, 1, 1));
printf("%ld sec = %ld days = %.2f years\n", d, d/86400, d/86400./365.25);
d = difftime(makedate(2030, 12, 31), makedate(2025, 12, 31));
printf("%ld sec = %ld days = %.2f years\n", d, d/86400, d/86400./365.25);
}
就像您的代码一样,这利用了令人惊讶的强大mktime
功能,并且可以做它可以做的一切。它处理闰年,没问题。它不处理闰秒或日历更改。
如果,如您所说,您对 1900 年之前的日期感兴趣,恐怕您不走运。 time_t
根本无法在大多数系统上表示这些日期,因此您将不得不寻求其他解决方案。