日历算法
简介
日历系统深刻的影响着人们的生活,人们使用日历来安排生产生活事件。日历是一种将时间划分成各种标准单位(年,月,日,周等)的系统。划分标准通常是按照人类长期观察到的周期性自然现象来确定,如阳历,阴历,阴阳历,也有按照人们生活习惯来划分的,如星期制,儒略日。
术语
回归年(Tropical year)
是由地球上观察,太阳经过四季变化回到相同的点所经历的时间,即地球公转一周(绕黄道运行360°)。经过长期测量有如下数据:
1回归年 = 365.2421990741日 = 365天5小时48分46秒1
阳历(Solar Calendar)
根据地球围绕太阳公转轨道位置,或地球上所呈现出太阳直射点的周期性变化,所制定的历法2。 如:格里历
阴历
按月亮的月相周期3来安排的历法4。月亮绕地球运行一周时间为一个月,称为朔望月,大约29.530588日,分为大月30日、小月29日。一年有12个朔望月,约354或355日[4]。
阴阳历
单纯的“阳历”只保证一年的时间与地球绕日运行周期基本一致,单纯的“阴历”是指历法中只保证一个月的时间与月亮运行周期基本一致。而“阴阳历”同时保证日月周期一致。
农历
中国传统历法, 属于阴阳历的一种。历法规则是上一个公历年的冬至所在的朔望月是上一个农历年的十一月(冬月/子月)。将朔日定为每月的第一天即初一(月球运行到地球和太阳之间,在地球上看不到月亮)。
格里历(Gregorian calendar)
格里历即公历,历年平均长度为365.2425日,接近平均回归年的365.242199074日,约每3300年误差一日。格里历平年365天,闰年366天。闰年2月份为29天,平年2月份为28天。如此设置是为了吻合回归年时长。
- 天数分布
| 月份 | 1月 | 2月 | 3月 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 10月 | 11月 | 12月 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 天数 | 31 | 28/29 | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 |
- 置闰算法,
| 世纪年 | 400的倍数 | 100的倍数 | 4的倍数 |
|---|---|---|---|
| 结果 | 闰 | 不闰 | 闰 |
纪元元年
纪元元年,即公元1年,源自于欧洲等西方基督教信仰为主国家,以当时认定的耶稣出生为纪年的开始。在一般以耶稣诞生在约公元前7年至前4年左右的说法最可靠。格里历使用该体系。
儒略日(Julian day)
一种以连续的日数计算时间的计时方式5。儒略日数记录是从起点的时间(0日)到当前的天数。例如,2000年1月1日的UT12:00是儒略日2,451,545。常用来计算两个日期之间相隔的天数。
星期(Week)
一个时间单位,每星期有7日。计算一个格里历日期是星期几时,会给定一个已知的日期。例如1753年4月1日是星期日,求2019年1月30日是周几。首先计算两个日期的差值。两个日期相隔了266-1=265年,其中64个闰年,201个平年。1753年4月1日还剩下365-31-28-31-1=274天,2019年1月30日已经过了30天。相隔天数275+265*365+64+30=97094天,97094除以7余数为3。因此2019年1月30日是周三。计算两个日期的差值时也可以将格里历日期转换成儒略日,然后计算两个儒略日的差值。为了简化计算人们研究出了很多计算算法,有兴趣的在维基百科6中深入阅读。
算法
- 计算格里历置闰算法
int isleapyear(int y) { return (y%100 != 0 && y%4 == 0 ) || (y%100 == 0 && y%400 == 0); } - 计算星期算法(Sakamoto’s methods)
int dayofweek(int y, int m, int d) /* 1 <= m <= 12, y > 1752 (in the U.K.) */ { static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }
参考资料
linux 下的奇怪日历
#cal 9 1752
September 1752
Su Mo Tu We Th Fr Sa
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30