蔡勒(Zeller)公式:根据任意日期,计算当天星期几

首先,注明参考地址:https://zhuanlan.zhihu.com/p/79290515

蔡勒公式用于根据日期计算那一天是星期几。

回想,如果我们已知一个日期,和那个日期是星期几,根据要求日期和已知日期的差值 mod 7就可以得到要求日期星期几了。当然,蔡勒公式也是基于这个想法实现的,只是加入了一些计算方面的化简转换等操作。

蔡勒公式的形式:

解释:W是星期数;c是4位年份的前两位;y是4位年份的后两位;m是月份,m的取值范围是[3,14],某年的1、2月看做上一年的13、14月,比如2020年的1月1日看做2019年的13月1日来计算;d是日数;[]是取整运算;mod是求余运算。

拿我写这篇博文的日期做例子试一下吧,2020年02月27日,需要将这个日期看做2019年14月27日。于是,c=20,y=19,m=14,d=27,于是D=5-40+19+4+39+27-1=53,53 mod 7=4,所以2020年02月27日是星期四,查看日历,确实如此。

最后关于蔡勒公式,还需要做两点补充说明:

  1. 在计算机编程中,W 的计算结果有可能是负数。如果W是负数,就让W+7,得到的就是一个正数了。
  2. 此公式只适用于格里高利历(也就是现在的公历)。

计算目标日期的星期数是基于基准点日期和目标日期天数差、基准点日期、基准点星期数来计算的,于是我们将天数差记作D。假设基准点日期是yyyy-MM-dd这一天,基准点星期数是星期日。将D划分为3个部分。举例说明一下:基准日期是2010-10-01,目标日期是2020-02-27。

第一部分:2010-10-01到2010-12-31的天数。

第二部分:2011-01-01到2019-12-31的天数。

第三部分:2020-01-01到2020-02-27的天数。

如果将基准日期选择为某一年的12月31日,那么第一部分就可以忽略掉了,再结合这一天是星期日的规则,我们得出一个日期:0000年12月31日,这一天是星期日,此时,就选定了一个基准日期。下面计算D2和D3。

一年最少有365天,考虑到闰年的情况,四年一闰,百年不闰,四百又闰,后面三个取整运算是用来处理闰年的。

下面计算D3,我们将每个月看做28+Excess天,当年的m月之前所有月份Excess的和是Accum(m),于是可以得到D3的表达式和一个表格:

月份 1 2 3 4 5 6 7 8 9 10 11 12
天数 31 28 31 30 31 30 31 31 30 31 30 31
Excess 3 0 3 2 3 2 3 3 2 3 2 3
Accum 0 3 3 6 8 11 13 16 19 21 24 26

从3月份开始,Excess呈现3、2、3、2、3的循环,当m≥3时,Accum(m)的增量也是3、2、3、2、3的循环。也就是每5个月增加13,那么将13÷5作为系数,又因为Accum(m)是离散的整数,那么,我们取x=1,2,3……得到一个表格,观察表格中的数据。

x 4 5 6 7 8 9 10 11 12 13 14
f(x) 10 13 15 18 20 23 26 28 31 33 36

当x≥4时,f(x)的增量也是3、2、3、2、3的循环,也就是f(x)的增幅(x≥4)和Accum(m)的增幅(x≥3)相同,它们相差一个常数7。当m≥3时,Accum(m)值的序列,相当于x≥4时,f(x)-7值的序列,于是,m≥3时,

考虑m=1和m=2的情况,则有

这里的i表示是否是闰年,如果是闰年,i=1,如果是平年,i=0。

假设有13月,按照3、2、3、2、3增量的顾虑,第13个月天数为31,正好和1月份的天数是一样的,于是将每年的1月和2月当做上一年的13月和14月,因为14月作为最后一个月了,平年闰年的影响只有只有在14月才会出现,但是第14月计算的时候,直接使用d来表示日了,于是i就不需要了,于是D3的公式就变成了这样,此时m取值范围是[3,14]。

因为每年的1月和2月被当做了上一年的13月和14月,在D2的计算中,计算闰日的时候,公式需要做修改,假设要算0004年03月01日对应的D2时,将每一年都看作03月到14月,那么,需要计算3个365天+0003年14月多出的一天(0003年的14月实际是0004年的02月),相当于把0004年的闰日那一天挪到了0003年里,相当于0003年是闰年,于是D2的公式需要调整为:

这里的(y-1)×365是不变的,因为年份差还是y-1,变化的是闰年“提前了一年”。

至此,根据D=D2+D3得到的公式是:

D=(y-1)\times365+\begin{bmatrix} \frac{y}{4} \end{bmatrix}-\begin{bmatrix} \frac{y}{100} \end{bmatrix}+\begin{bmatrix} \frac{y}{400} \end{bmatrix}+(m-1)\times28+\begin{bmatrix} \frac{13(m+1)}{5} \end{bmatrix}-7+d

后面的操作是用D mod 7,不如现在将D mod 7化简一下,化简结果为:

用上式计算每世纪第一年的03月01日的星期数,得到下表:

年份 1,401,801,……,2001 101,501,901,……,2101 201,601,1001,……,2201 301,701,1101,……,2301
星期数 4 2 0 5

可以发现,每隔4个世纪,星期数就重复一次。又因为5 mod 7 = 5,-2 mod 7 = 5,所以将上面表格中的5看做-2,再看4、2、0、-2,这是一个等差数列。所以每个世纪第一年的03月01日的星期数是

,其中c是世纪数-1。带入某个世纪第一年的03月01日,可以得到:

利用同余定理变换得:

于是,在每世纪的第一年,计算D的公式可以更新为

这个公式只适用于每世纪的第一年,需要再加上计算闰日的部分,就可以计算这个世纪其他年份日期的星期数了。

因为365 mod 7 = 1,所以化简为

假设,那么,于是,,带入上式可得:

这便是蔡勒公式的最终形式。

你可能感兴趣的:(随手记录)