C++计算任意日期是星期几

常用公式

 W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D 

Y是年份数

D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天。

蔡勒(Zeller)公式

W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1

或者是:

w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

公式中的符号含义如下:

w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六

c:世纪(注:一般情况下,在公式中取值为已经过的世纪数,也就是年份除以一百的结果,而非正在进行的世纪,也就是现在常用的年份除以一百加一;不过如果年份是公元前的年份且非整百数的话,c应该等于所在世纪的编号,如公元前253年,是公元前3世纪,c就等于-3)

y:年(一般情况下是后两位数,如果是公元前的年份且非整百数,y应该等于cMOD100+100)

m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)

d:日

[ ]代表取整,即只要整数部分。

下面以中华人民共和国成立100周年纪念日那天(2049年10月1日)来计算是星期几,过程如下:

w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

=49+[49/4]+[20/4]-2×20+[26×(10+1)/10]+1-1

=49+[12.25]+5-40+[28.6]

=49+12+5-40+28

=54 (除以7余5)

即2049年10月1日(100周年国庆)是星期五。

再比如计算2006年4月4日,过程如下:

w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

=6+[6/4]+[20/4]-2*20+[26*(4+1)/10]+4-1

=-12 (除以7余5,注意对负数的取模运算!实际上应该是星期二而不是星期五)

w=(-12%7+7)%7=2;

注意:

蔡勒公式只适合于1582年(中国明朝万历十年)10月15日之后的情形。罗马教皇格里高利十三世在1582年组织了一批天文学家,根据哥白尼日心说计算出来的数据,对儒略历作了修改。将1582年10月5日到14日之间的10天宣布撤销,继10月4日之后为10月15日。

后来人们将这一新的历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历公历.

#include<iostream>

usingnamespacestd;

int main(){

int year,month,day;

while(cin>>year>>month>>day){

if(month<3){

year-=1;

month+=12;

}

charb[7][10]={"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};

int c=int(year/100),y=year-100*c;

int w=int(c/4)-2*c+y+int(y/4)+(26*(month+1)/10)+day-1;

w=(w%7+7)%7;

cout<<b[w]<<endl;}return 0;}。

对蔡勒(Zeller)公式的改进 

相比于另外一个通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。不过,笔者给出的通用计算公式似乎更加简洁(包括运算过程)。

现将公式列于其下: W=[y/4]+r (y/7)-2r(c/4)+m’+d 

公式中的符号含义如下:

r ( )代表取余,即只要余数部分;

m’是m的修正数,现给出1至12月的修正数1’至12’如下:(1’,10’)=6;(2’,3’,11’)=2;(4’,7’)=5;5’=0;6’=3;8’=1;(9’,12’)=4(注意:在笔者给出的公式中,y为润年时1’=5;2’=1)。其他符号与蔡勒(Zeller)公式中的含义相同。 

下面以中华人民共和国成立100周年纪念日那天(2049年10月1日)来计算是星期几:

 w=[y/4]+r (y/7)-2r(c/4)+m’+d

                   = [49/4]+r (49/7)-2r(20/4)+10’+1

                   =12+0-2×0+6+1

 =19    (除以7余5)

基姆拉尔森计算公式

 W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) %7 

该式可能与蔡勒公式的计算都是较为复杂,但有改进的地方:对于世纪这个概念不被引用,直接就是计算年代数(4位数)的!既不用再把 世纪 和 年代数(后两位)分开。

在公式中d表示日期中的日数

m表示月份数

y表示年数

 注意:在公式中有个与其他公式不同的地方: 把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。

#include <iostream>
using namespace std;
int CaculateWeekDay(int y,int m,int d)
{
if(m==1) m=13,y--;
if(m==2) m=14,y--;
int week=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
return week;
 
}
 
int main()
{
    int y,m,d;
    for(;;){
    cin>>y>>m>>d;
    int week=CaculateWeekDay(y,m,d);
     
    switch(week)
    {
    case 0: cout<<"Monday星期一"<<endl; break;
    case 1: cout<<"Tuesday星期二"<<endl; break;
    case 2: cout<<"Wednesday星期三"<<endl; break;
    case 3: cout<<"Thursday星期四"<<endl; break;
    case 4: cout<<"Friday星期五"<<endl; break;
    case 5: cout<<"Saturday星期六"<<endl; break;
    case 6: cout<<"Sunday星期日"<<endl; break;
    }
    }
    return 0;
}
string CaculateWeekDay(int y,int m, int d)
{
int week = 0;
if(m==1){m=13;y--;}
if(m==2) {m=14;y--;}
if((y<1752)||((y==1752)&&(m<9))||((y==1752)&&(m==9)&&(d<3))) //判断是否在1752年9月3日之前
week =(d+2*m+3*(m+1)/5+y+y/4+5)%7; //1752年9月3日之前的公式
else
week =(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7; //1752年9月3日之后的公式
string weekstr="";
switch(week)
{
case 0: {weekstr="Monday"; break;}
case 1: {weekstr="Tuesday"; break;}
case 2: {weekstr="Wednesday"; break;}
case 3: {weekstr="Thursday"; break;}
case 4: {weekstr="Friday"; break;}
case 5: {weekstr="Saturday"; break;}
case 6: {weekstr="Sunday"; break;}
}
return weekstr;
}

 

其他计算公式

(年+年/4+年/400-年/100-年基数+月基数+日)/7=……余星期几注:式中分数均取整年基数,平年1,闰年2。

月基数:1、平年:一月0,二月3,三月3,四月6,五月1,六月4, 七月6,八月2,九月5,十月0,十一月3,十二月5。

2、闰年:一月0,二月3,三月4,四月0,五月2,六月5, 七月0,八月3,九月6,十月1,十一月4,十二月6.如:1949年10月1日是星期几? (1949+1949/4+1949/400-1949/100-1+0+1)/7=(1949+487+4-19-1+0+1)/7=345……6即该日为星期六。

所谓月基数,就是前面月的日数和除7余数,如2月基数,前面月数的日数总和的7余数为3,则该月的基数就是3,如4月(闰年)基数,前面三个月的日数总和为:(31+29+31)/7=91/7……0 为了简化运算,先取各月 余数,再相加,再取7余数:(3+1+3)/7……0,即4月基数为0,为了加快计算速度,通常是将平年和闰年的月基数编成基数表,直接查算。月基数见上。

#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,c,d,e,f;
double x,y;
printf("请输入年份:\n");
scanf("%d", &a);
printf("请输入月份:\n");
scanf("%d", &b);
printf("请输入日子:\n");
scanf("%d", &c);
x = a;
y = x / 4;
e = (int)y;
if(y == e)
{
e = 2;//e是年基数
}
else
{
e = 1;
}
if(e = 1)
{
switch(b)
{
case 1:
b = 0;
break;
case 2:
b = 3;
break;
case 3:
b = 3;
break;
case 4:
b = 6;
break;
case 5:
b = 1;
break;
case 6:
b = 4;
break;
case 7:
b = 0;
break;
case 8:
b = 3;
break;
case 9:
b = 5;
break;
case 10:
b = 0;
break;
case 11:
b = 3;
break;
case 12:
b = 5;
break;
}
}
else
{
switch(b)
{
case 1:
b = 0;
break;
case 2:
b = 3;
break;
case 3:
b = 4;
break;
case 4:
b = 0;
break;
case 5:
b = 2;
break;
case 6:
b = 5;
break;
case 7:
b = 0;
break;
case 8:
b = 3;
break;
case 9:
b = 6;
break;
case 10:
b = 1;
break;
case 11:
b = 4;
break;
case 12:
b = 6;
break;
}//b是月基数
}
f = (a + a / 4 + a / 400 - a / 100 - e + b + c) % 7;
switch(f)
{
case 1:
printf("那一天是星期一");
break;
case 2:
printf("那一天是星期二");
break;
case 3:
printf("那一天是星期三");
break;
case 4:
printf("那一天是星期四");
break;
case 5:
printf("那一天是星期五");
break;
case 6:
printf("那一天是星期六");
break;
case 0:
printf("那一天是星期日");
break;
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值