2015年9月4日 星期五

萬年曆公式

google 萬年曆公式,
沒想到第一個的內容就是有問題的,
奇摩知識+的雖然有加上月日天數對照表,
但是在閏年還是有錯誤。
看到頭昏眼花,
最後用程式驗算,
希望是比較正確的公式。

Ctrl+C Ctrl+P太容易了,
好像沒人要驗算。
代入的年份沒有減1的公式,
在2016年1月1日會出錯。

實際上公式應該是:

日月天數對照表:
一至十二月依序是
平年 [0,3,3 ,6,1,4 ,6,2,5 ,0,3,5]
閏年 [0,3,4,0,2,5,0,3,6,1,4,6]
根據說明,
這是各月1日和1月1日的星期數相差的天數。

判斷閏年:
Wikipedia中寫的目前使用的格里曆閏年規則如下:
  1. 西元年份除以400可整除,為閏年。
  2. 西元年份除以4可整除但除以100不可整除,為閏年。
  3. 西元年份除以4不可整除,為平年。
  4. 西元年份除以100可整除但除以400不可整除,為平年。
//判斷閏年部份寫成PHP 程式
if((!($year%4))&&$year%100!=0||(!($year%400)))
{
    $isLeapYear = true;
    echo $nowYear." is leap year.\n";
}


星期計算公式:
首先將代入的年份-1,
因為上方閏年對照表的閏年1月是和上個平年相同,
如果以閏年數字帶入,會至少多加1天
造成錯誤答案。
所以2016年必須代入2015。

2016年1月1日算法:
2016是閏年
(2016-1)÷4=503.75
(2016-1)÷100=20.15
(2016-1)÷400=5.0375
日月天數對照:0(查表)+1日=1
(2015+503-20+5+1)/7=357 餘 5
表示星期五。
算式:
(去年+(去年÷4)-(去年÷100)+(去年÷400)+日月天數對照表對應數字+日數)÷7 後取餘數
用Excel 或 LibreOffice Calc 驗算(實際上有直接顯示星期的公式),
A2輸入年份,
計算當年1月1日星期幾
=MOD((A2-1+ROUNDDOWN((A2-1)/4)+ROUNDDOWN((A2-1)/400)-ROUNDDOWN((A2-1)/100)+(0+1)),7) 

//計算year年month月第1天星期的PHP程式
$daysBias = [0,3,3,6,1,4,6,2,5,0,3,5];
$daysBiasLeap = [0,3,4,0,2,5,0,3,6,1,4,6];

$day = (floor($year-1)+floor(($year-1)/4)+floor(($year-1)/400)-floor(($year-1)/100)
        +($isLeapYear?$daysBiasLeap[$month-1]:$daysBias[$month-1])
+1)%7;

(如果想維持代入當年數字,上方的閏年的日月天數對照表就需要另外修正。)