给定UTC日期和时间为
year
,month
,day
,hour
,minute
,second
,我想知道一个伪代码算法来计算相应的Unix纪元时间戳。
一分钟有60秒,一小时有60分钟,一天有24小时。所以我们可以每天使用 60 × 60 × 24 = 86400 秒并向后计算天数,直到 1970-01-01T00:00:00Z,对吗?不过,月份的天数不同。因此,最好跳过这一点并使用每年 365 天。但是,还有闰年……还有闰秒……等等?
这是否突然使算法变得像处理时区一样复杂,还是仍然相当容易描述?
与我的合著者 Lorenz Schneider 教授一起,我们为这种转换(不考虑闰秒)和相反方向的转换导出了非常有效的算法。
对于 Unix 时间戳到公历日期,我自己在 Linux 内核、libstdc++ (GCC) 和 Firefox 中实现了这些算法。其他人在 .NET、Go、Rust 和 Zig 中实现了它们。
数学并不比除法和取模运算复杂多少。它基于这些概念的概括,我们称之为欧几里得仿射函数,并具有
f(n) = (a * n + b) / d
的形式(因此,当 a = 1
和 b = 0
时,它们简化为除法。)有了这个,还有一个技巧,可以将二月移至 20 月底年,可以处理天数可变的月、年和世纪。
请参阅我们的论文并观看我在 C++ Now 2023 或 C++ on Sea 2023 的演讲。
FWIW:演讲还涵盖了其他两个日历函数的非常有效的算法,这两个函数我都为 libstdc++ (GCC) 做出了贡献:
is_leap(year)
last_day_fo_the_month(month, year)