暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基姆拉尔森 (Kim larsen) 星期计算公式​

工程师站台 2020-03-26
1941

<前提>

公元0年的1月1日是星期日(另一种佐证一周的第一天是礼拜天的说法:)日、月、火、水、木、金、土


<1>

先不考虑闰年的情况下,每年365天,365%7=1,也就是说第二年的某一天(月日)是第一年的那一天(月日)的下一天,这样可以得出公式1(不考虑闰年,只考虑一月的情况)

DayOfWeek = (d-1 + y) % 7    公式(1)

<2>

再考虑闰年的情况,我们知道闰年的计算公式:1. 普通闰年:每4年一次;2.世纪闰年:每400年一次。 因此当年的之前的闰年数目:

NumOfLeapYear = (y-1)/4 - (y-1)/100 + (y-1)/400

这样我们可以推导出公式2(考虑了闰年的一月的情况)

DayOfWeek = (d-1 + y + (y-1)/4 - (y-1)/100 + (y-1)/400) % 7 公式(2)

再来考虑非一月份的情况,如果每个月恰巧是28天的话,所有的月份都可以按照一月的day进行计算,也就是说后面的月份还得考虑一个偏移量。如下表所示(暂不考虑闰年的情况)

月份
天数
偏差(相对于28天)
当月累计偏差(相对于28天)
当月偏移量(累计偏差模7)
131
3
0
0
228
0
33
331
3
33
430
2
6
6
5
31
3
8
1
630
2
11
4
7
31
3
13
6
8
313
16
2
9
30219
5
10
31
3
21
0
1130
2
24
3
12313
26
5
根据表格,我们得到这样这个查找表
// golang
// Offset of the month
OM = [...]int{033614625035
于是,在不考虑闰年的的情况,我们可以得到公式3
DayOfWeek = (d-1 + y + (y-1)/4 - (y-1)/100 + (y-1)/400 + OM[m-1]) % 7  公式(3)
<3>
但是如果要考虑闰年的话,对于3月以及之后的月份又需要多加一个偏差。因此,有人机智的把当年的1、2月份看作上一年的13、14月份,这样也就相当于把元年的起始点放在了0年3月1日(这样对于闰年2月的累计偏移量就不会被计算进去了)。重新推得公式1,2,3
// 0年3月1日是星期三


DayOfWeek = (d + 2 + y) % 7    公式(1)'
// 因为3月开始作为元月,之前有多少闰年的计算也就和当年有关
DayOfWeek = (d + 2 + y + y/4 - y/100 + y/400) % 7 公式(2)'
// 偏移查找表
DayOfWeek = (d + 2 + y + y/4 - y/100 + y/400 + NewOM[m-3]) % 7  公式(3)'

重新计算查找表

月份
天数
偏差
当月累计偏差
当月偏移量
331
3
00
430
2
3
3
5
31
3
5
5
630
2
8
1
7
31
3
10
3
8
313
13
6
9
30216
2
10
31
3
18
4
1130
2
21
0
12313
23

2

13(1)31
3
26
5
14(2)28/29
0
291
NewOM = [...]int{035136240251}

神(无)奇(聊)的数学家推导出

令m-3=x,NewOM[x]满足表达式 [2 * (x + 3) + 3 * (x + 4) / 5 - 1] % 7
m取值范围是[3, 14]
因此NewOM[m-3] = [2*m + 3*(m+1)/5 -1] % 7

这样可以得到最后的一个唯一公式

DayOfWeek = (d + 1 + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7  公式(3)''

当然这个公式中的m取址范围是[3, 14],当计算1、2月时,就把它看成前一年的13、14月份。

严谨的同学肯定会说,对于0年的1、2月份上面的公式是否通用?代个值进去看看就知道啦!例如:0年1月1日

d = 1, m = 13, y = -1
=> DayOfWeek = (1 + 1 + 2*13 + 3*(13+1)/5 -1) % 7 = 0

<后续>

还有一个魔数公式叫做Zeller公式,也是可以用来计算DayOfWeek
/*
* 蔡勒公式
* 1582.10.4之后 w = (y + y/4 + c/4 - 2*c + (26*(m+1))/10 + d - 1) % 7
* 1582.10.4及之前 w = (y + y/4 + c/4 -2*c + (13*(m+1))/5 + d + 2) % 7;
*/

文章转载自工程师站台,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论