Welcome

首页 / 软件开发 / 数据结构与算法 / 算法系列(十七) 日历生成算法-中国公历(格里历)(下)

算法系列(十七) 日历生成算法-中国公历(格里历)(下)2014-05-24 csdn博客 吹泡泡的小猫【接上篇】

上述计算星期的方法虽然步骤简单,但是每次都要计算两个日期的时间差,不是非 常方便。如果能够有一个公式可以直接根据日期计算出对应的星期岂不是更好?幸运的是,这样的公式是 存在的。此类公式的推导原理仍然是通过两个日期的时间差来计算星期,只是通过选择一个特殊的日期来 简化公式的推导。这个所谓的特殊日期指的是某一年的12月31日这天刚好是星期日这种情况。选择这样的 日子有两个好处,一个是计算上可以省去计算标准日期这一年的剩余天数,另一个是计算出来的日期差余 数是几就是星期几,不需要再计算星期的差值。人们知道公元元年的1月1日是星期一,那么公元前1年的 12月31日就是星期日,用这一天作为标准日期,就可以只计算整数年的时间和日期所在的年积累的天数, 这个星期公式就是:

w = (L * 366 + N * 365 + D) % 7                             (公式 2)

公式中的L是从 公元元年到y年m月d日所在的年之间的闰年次数,N是平常年次数,D是y年内的积累天数。将整年数y - 1 = L + N带入上式,可得:

w = ( (y - 1) * 365 + L + D) % 7                              (公式 3)

根据闰年规律,从公元元年到y年之间的闰年次数是可以计算出来的,即:

将L带入公式2,得到星期w的最终计算公式:

还以2005年5月31日为例,利用公式5计算w的值为:

得到2005年5月31日是星期二,和前面的计算方法得到的结果一致。根据上述分析,可得写出使用公式 5计算星期的算法实现:

146 int TotalWeek(int year, int month, int day)147 {148 int d = CalcYearPassedDays(year, month, day);149 int y = year - 1;150 int w = y * DAYS_OF_NORMAL_YEAR + y / 4 - y / 100 + y / 400 + d;151 152 return w % 7;153 }
公式5的问题在于计算量大,不利于口算星期结果。于是人们就在公式5的基础上继续推导 更简单的公式。德国数学家克里斯蒂安·蔡勒(Christian Zeller, 1822- 1899)在1886年推导出了著名 的为蔡勒(Zeller)公式:

对计算出的w值除以7,得到的余数就是星期几,如果余数是0,则为星期日。蔡勒公式中各符号 的含义如下:

w :星期;

c :世纪数 – 1的值,如21世纪,则 = 20;

m :月数 ,的取值是大于等于3,小于等于14。在蔡勒公式中,某年的1月和2月看作上一年的13月和14月,比如 2001年2月1日要当成2000年的14月1日计算;

y :年份,取公元纪念的后两位,如1998年, = 98 ,2001年, = 1;

d :某月内的日数