一、引子
最近想到一个问题,有些指针式手表除了指示时分秒的三针之外只有一个小的日历口显示当前日期,而对于上班族来讲星期的概念可能更常用,那如何通过这个日期就推测出当天是星期几呢?
这里其实蕴含着三个值,第一个是当前年份,一般而言年份这种周期比较长的很难弄错,所以也不用特别注意;第二个是月份,相对于日期来讲当前是处于哪个月还是较容易记住的;第三个是日期,这个对于日复一日的打工仔来说相对就不那么重要了,毕竟每周只要记住哪天是周几就能愉快地上下班了,这个日期值是要以外在的形式提醒我们的。
二、计算公式
查了一下相应的算法,以蔡勒公式 (Zeller's Formula) 最为知名,该公式最早是由德国数学家克里斯蒂安·蔡勒 (Christian Zeller, 1822-1899) 在1886年推导出的。
W = (Y+[Y/4]+[C/4]-2*C+[(13*(M+1))/5]+D-1) mod 7
其中
W
是所求当前日期对应的星期数,0表示周日,1-6表示对应的周一到周六。
Y
是当前年份的后两位,Y=year mod 100。
C
是当前年份的前两位,C=year / 100。
M
是当前月份。
D
是当前日期。
mod
是取余操作。
[]
是高斯取整操作。
【注】
- 负数只能按数论中余数的定义求余。为方便计算可以加上一个7的整数倍,使它变为一个正数,然后再对7求余。
- 该公式使用于公历(格里高利历)的置闰规则。对于儒略历则有所不同。
对推导过程及其历史演变感兴趣的可以看一看参考资料中的[4]和[6]。
三、应用举例
简单来讲,就是利用前面提到的三个值进行计算,分别记作Y、M、D。
首先看年份,取当前年份的后两位并记作 Y,Y=year mod 100,比如今年是2021年则Y=21。
然后看月份,这一步相对比较麻烦一些,分为平年和闰年两种情况。
平年时月份-月份数对应关系分别为:1-6,2-2,3-2,4-5,5-0,6-3,7-5,8-1,9-4,10-6,11-2,12-4。
闰年时月份-月份数对应关系分别为:1-5,2-1,3-2,4-5,5-0,6-3,7-5,8-1,9-3,10-6,11-2,12-4。
闰年与平年的区别在于一月份和二月份,闰年时相当于把平年时此两个月的月份数分别减一,其余不变。
可以利用如下的表盘来记忆。
接着看日期,直接就是日期本身,D=date。
现在利用这三个数值计算星期数,以2021-03-16这个日期为例
Y=21,对应数字为(21/4+21) mod 7=26 mod 7 = 5
M=3,对应数字为2
D=16,对应数字为16
然后三个值对应的数字相加再对其取余,(5+2+16) mod 7=2,表示当前日期为周二。
(全文完)
参考资料
[1] 怎样快速根据日期推算星期 https://jingyan.baidu.com/article/ae97a646820186bbfd461d37.html
[2] Zeller's congruence https://en.wikipedia.org/wiki/Zeller's_congruence
[3] 蔡勒公式 https://blog.csdn.net/qq_42804678/article/details/82793438
[4] [转载]1582年10月4日和1752年9月3日怎么了 https://www.cnblogs.com/igaoshang/articles/Date15821004.html
[5] 总天数以及星期几的计算算法 https://www.cnblogs.com/igaoshang/p/DayOfWeek.html
[6] [转载]蔡勒(Zeller)公式——计算任意一天是星期几 https://www.cnblogs.com/igaoshang/articles/Zeller.html
本文作者 :phillee
发表日期 :2021年3月16日
本文链接 :https://www.cnblogs.com/phillee/p/14446046.html
版权声明 :自由转载-非商用-非衍生-保持署名(创意共享3.0许可协议/CC BY-NC-SA 3.0)。转载请注明出处!
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。