--- title: 日历与约化儒略日 summary: 日编号系统、外推格里高利历,以及转换算法。 --- # 日历与约化儒略日 日编号是自固定原点起算的天数。日历是用年、月、日为一个日子命名的规则。内核用日编号做运算,用日历做输入与显示,本文档给出二者。 ## 定义 - **儒略日(JD)** 自公元前 4713 年 1 月 1 日正午起,按外推儒略历计天。 - **约化儒略日(MJD)** 自 1858-11-17 午夜起算。 - 二者相差一个固定偏移: ```text JD = MJD + 2400000.5 ``` 半天的差异来自儒略日以正午起始而约化儒略日以午夜起始。此处使用约化儒略日,因为它使日编号保持在一个日的小数部分便于处理的范围内。 ## 日历 外推格里高利历是把 1582 年引入的格里高利历向前延伸。内核全程使用它,包括 1582 年之前的日期,以使每个日编号都有唯一的日历表示。 闰年规则为:能被 4 整除的年份是闰年,但能被 100 整除的年份不是,除非它也能被 400 整除: ```text leap(y) = (y mod 4 == 0) and (y mod 100 != 0 or y mod 400 == 0) ``` 因此 2000 年是闰年,1900 年不是。 ## 数学含义 日历日期与日编号之间的双向转换使用整数运算,因此对每个可表示的日期都是精确的。算法把年份起点移到三月,使闰日落在调整后年份的末尾,从而从日计数中去掉特殊情况。 ```text a = floor((14 - month) / 12) y = year + 4800 - a m = month + 12 a - 3 JDN = day + floor((153 m + 2) / 5) + 365 y + floor(y / 4) - floor(y / 100) + floor(y / 400) - 32045 ``` 逆变换采用相同结构,偏移量为 32044。两个方向各实现一次,并在很宽的日期范围内相互校验。 ## 单位约定 - 日编号单位为天,一天的小数部分携带时刻。 - 小数在午夜为零,在正午为 0.5。 - 日历值包含年、月、日、时、分,以及带小数的秒。在包含插入闰秒的分钟中,秒值可达 60.999。 ## 适用边界 格里高利历是民用约定,日编号是计数约定,二者除此外没有物理含义。日编号是进行运算的便捷方式,不是可观测量。 闰年规则对外推格里高利历是精确的,但不描述 1582 年之前实际使用的任何日历。对 1582 年之前的日期,转换采用外推规则,与历史文献对比时可能发现数日差异。 ## 日编号系统对比 | 系统 | 原点 | 单位 | 午夜时的小数 | 此处采用 | |------|------|------|--------------|----------| | 儒略日 | 公元前 4713-01-01 12:00(外推儒略历) | 天 | 0.5 | 仅转换为 MJD | | 约化儒略日 | 1858-11-17 00:00 | 天 | 0.0 | 是 | | 简化儒略日 | 1858-11-16 12:00 | 天 | 0.5 | 否 | | 截断儒略日 | 1968-05-24 00:00 | 天 | 0.0 | 否 | | 距 J2000.0 的天数 | 2000-01-01 12:00 TT | 天 | 0.5 | 用于地球自转角 | | Unix 时间 | 1970-01-01 00:00 UTC | 秒 | 00:00 时为 0 | 否 | ## 来源 - 日编号约定遵循 IAU 用法,见《天文年历解释性补充》。 - 转换算法为 Howard Hinnant 在 *chrono-Compatible Low-Level Date Algorithms*(2015)中所述。 ## 另见 - [[time-scales]]:日编号可能被解释为的各尺度 - [[leap-seconds]]:日历中可能包含的插入秒 - 距 J2000.0 的天数出现在 [[earth-rotation-angle]]