1.我們先談?wù)劦脑鯓铀闶欠袷情c年:
最根本的原因是:地球繞太陽(yáng)運(yùn)行周期為365天5小時(shí)48分46秒(合365.24219天)即一回歸年(tropical year)。公歷的平年只有365日,比回歸年短約0.2422 日,所余下的時(shí)間約為四年累計(jì)一天,故四年于2月加1天,使當(dāng)年的歷年長(zhǎng)度為366日,這一年就為閏年。現(xiàn)行公歷中每400年有97個(gè)閏年。按照每四年一個(gè)閏年計(jì)算,平均每年就要多算出0.0078天,這樣經(jīng)過四百年就會(huì)多算出大約3天來。因此每四百年中要減少三個(gè)閏年。所以公歷規(guī)定:年份是整百數(shù)時(shí),必須是400的倍數(shù)才是閏年;不是400的倍數(shù)的年份,即使是4的倍數(shù)也是平年。
這就是通常所說的:四年一閏,百年不閏,四百年再閏。例如,2000年是閏年,1900年則是平年。
經(jīng)過計(jì)算驗(yàn)證真是這么回事,驗(yàn)證如下:
365.24219*400(年)=146096.876約等于146097(天)
365*303+366*97=146097(天)
真的是 四年一閏,百年不閏,四百年再閏 ,每400年有97個(gè)閏年303個(gè)平年。
以下代碼是c算法:判斷是否為閏年
//year:年份
//返回值:該年份是不是閏年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{
if(((year%4==0)&&(year0!=0))||(year@0==0))
{
return 1;
}else return 0;
}
2.通過年月日計(jì)算星期的方法
方法概述:
只需要知道三個(gè)代碼
日期代碼+月份代碼+年份代碼
就可以秒算任意年份任意日期的星期數(shù)
方法:
日期代碼就是指日期數(shù),例如1月10日的日期代碼就是10,10月1日的日期代碼就是1
月份代碼,table[12]={6,2,2,5,0,3,5,1,4,6,2,4};//非閏年
table[12]={5,1,2,5,0,3,5,1,4,6,2,4};//閏年
年份代碼,只需將其年份的后兩位數(shù)對(duì)4取模,然后與年份的后兩位數(shù)相加,在對(duì)7取余數(shù),
得到的余數(shù)就是年份代碼,例如2010年的年份代碼是 ([10/4]+10)%7=5,2011年的
的年份代碼是([11/4]+11)%7=6
通過以上三個(gè)參數(shù)就可以秒算星期了:
(日期代碼+月份代碼+年份代碼)%7=星期數(shù)
week[7]={0,1,2,3,4,5,6};//星期日-星期六
例如:2014年3月30日 日期代碼30 月份代碼2 年份代碼3 (30+2+3)%7=0 則是星期日
2008年8月 8日 北京奧運(yùn)會(huì)開幕時(shí)間,日期代碼8 月份代碼1 年份代碼3 (8+1+3)%7=5星
期五,ok都是正確的。
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
static u8 no_leap_year[12]={6,2,2,5,0,3,5,1,4,6,2,4};//非閏年
static u8 leap_year[12]={5,1,2,5,0,3,5,1,4,6,2,4};//閏年
u8 temp2;
u8 yearL;
yearL=year0;
yearL=(yearL/4+yearL)%7;
temp2=Is_Leap_Year(year)?leap_year[month-1]:no_leap_year[month-1];
return ((day+temp2+yearL)%7);
}
那么這樣計(jì)算日期的原理是什么呢?接下來我們探索一下吧!
泰勒公式:
W=[C/4]-2C+y+[y/4]+[26(m+1)/10]+d-1 (其中[ ]為取整符號(hào))
W=W%7
其中,W是所求日期的星期數(shù).如果求得的數(shù)大于7,可以減去7的倍數(shù),直到余數(shù)小于7為止.c是公元年份
的前兩位數(shù)字,y是已知公元年份的后兩位數(shù)字;m是月數(shù),d是日數(shù).方括[ ]表示只截取該數(shù)的整數(shù)部
分。
還有一個(gè)特別要注意的地方:所求的月份如果是1月或2月,則應(yīng)視為前一年的13月或14月.所以公式中m
的取值范圍不是1-12,而是3-14.
后還有一點(diǎn),工元1582年羅馬教皇曾經(jīng)下令修改歷法,把這一年的10月4日(星期4)的下一天改為10月15
日.所以在1582年以前的日子,不能加以套用.
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
u16 W;
u8 m;
u8 yearH=year/100,yearL=year0;
if(month<3)m=month+12;
else m=month;
W=((yearH/4)-(2*yearH)+yearL+(yearL/4)+(26*(m+1)/10)+day-1)%7;
return ((u8)W);
}
以上那兩個(gè)程序子函數(shù)都可以計(jì)算出星期