搜索
bottom↓
回复: 26

请教大侠们: 怎么样计算某年某月的某天是星期几啊?

[复制链接]

出0入0汤圆

发表于 2007-3-13 15:10:25 | 显示全部楼层 |阅读模式
如题!

出0入0汤圆

发表于 2007-3-13 15:18:21 | 显示全部楼层
你可以网上找下.有个计算公式的.

也可以等到家了贴上来.

出0入0汤圆

发表于 2007-3-13 15:20:34 | 显示全部楼层
基姆拉尔森计算公式

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

在公式中d表示日期中的日数,m表示月份数,y表示年数。

出0入0汤圆

发表于 2007-3-13 15:48:11 | 显示全部楼层
这个公式很新颖,计算时用整型还是浮点?

出0入0汤圆

 楼主| 发表于 2007-3-13 16:00:58 | 显示全部楼层
这个公式计算下来,0是星期天吧

出0入0汤圆

 楼主| 发表于 2007-3-13 16:21:08 | 显示全部楼层
刚才利用全整型计算了一下,发现 0 代表的是星期一,1 代表星期二.......

出0入0汤圆

发表于 2007-3-13 16:44:44 | 显示全部楼层
假如这个公式好用,0代表星期几问题不大,可以在括号里加个数调整一下。

出0入0汤圆

发表于 2007-3-13 16:52:11 | 显示全部楼层
假设用0代表星期天,1代表星期一,以此类推



1.

以某天(a)为基准,计算n天(b)之后是星期几:

   假设该天为星期m,则n天之后是星期q:

   q = m + (n % 7)



2.

一年有365天,2001年的今天是星期2, 2002年的今天是:

    2 + 365 % 7 = 2 + 1 = 3, 不信你查日历表。

因为 365 = 7 * x + 1, 因此,每过一年的同月同日星期数便加1。



3.

闰年有366天,因此如果月份大于2,则每过一年的同月同日星期数除了要加1,还要再加间隔的闰年数。



4.

每四年有一个闰年,每一百年要减去一个闰年,每四百年要加回一个闰年。

因此,今天是:

    (7 - 1) / 4 = 1

    (2 + (7 - 1) + 1) % 7 = 9 % 7 = 2, 不信你在窗口右下角的时间上双击鼠标看看是不是星期二。



5.

只要还有一点数学常识,星期的计算公式即可推导出来了。



至于用几代表星期几,你自己喜欢。

出0入0汤圆

发表于 2007-3-13 17:05:11 | 显示全部楼层
yeungxl :mod是“取模”的意思吗?在哪个GCC函数库里?

出0入0汤圆

发表于 2007-3-13 17:06:19 | 显示全部楼层
W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) % 7

出0入0汤圆

发表于 2007-3-13 17:07:15 | 显示全部楼层
用Excell 验证了几个日期





年        月        日        计算的星期

2007        3        13        1

2006        3        13        0

2005        3        13        6

2004        3        13        5

2003        3        13        3

2002        3        13        2

2001        3        13        1

2000        3        13        0

看来是对的
-----此内容被powerful于2007-03-13,17:08:43编辑过

出0入0汤圆

发表于 2007-3-13 17:11:54 | 显示全部楼层
哈哈,原来如此。谢谢。

出0入0汤圆

发表于 2007-3-13 17:27:06 | 显示全部楼层
不错,收下

出0入0汤圆

发表于 2007-3-14 00:33:38 | 显示全部楼层
算二月不对,其他月份似乎都对

出0入0汤圆

发表于 2007-3-14 08:29:23 | 显示全部楼层
转贴:



基姆拉尔森计算公式

算法如下:

基姆拉尔森计算公式

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



  在公式中d表示日期中的日数,m表示月份数,y表示年数。



注意:在公式中有个与其他公式不同的地方:



把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。



代码如下:

//y-年,m-月,d-日期

  string CaculateWeekDay(int y,int m, int d)

  {

  if(m==1) m=13;

  if(m==2) m=14;

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

  string weekstr="";

   switch(week)

   {

    case 1: weekstr="星期一"; break;

    case 2: weekstr="星期二"; break;

    case 3: weekstr="星期三"; break;

    case 4: weekstr="星期四"; break;

    case 5: weekstr="星期五"; break;

    case 6: weekstr="星期六"; break;

    case 7: weekstr="星期日"; break;

   }



          return weekstr;

  }





上面的是参考网上最流行的,用baidu搜到的几乎全都是这个,但是总是调试不对,所以自己改了一个,以供参考

fun1(y,m,d)

{

int k;

if(m==1||m==2){m+=12;y--;}

return (int)((d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)+1)%7;

}

调试了2007,很正确的输出了


-----此内容被steven于2007-03-14,08:38:31编辑过

出0入0汤圆

 楼主| 发表于 2007-3-14 08:46:50 | 显示全部楼层
呵呵,不错,谢谢朋友们了.

出0入0汤圆

发表于 2007-3-14 09:24:41 | 显示全部楼层
steven 独钓一江秋

的改法是对的:



年        月        日 计算的星期  实际星期

2006        13        14        6        6

2005        13        14        5        5

2004        13        14        4        4

2003        13        14        2        2

2002        13        14        1        1

2001        13        14        0        0

2000        13        14        6        6

1999        13        14        4        4



2006        14        14        2        2

2005        14        14        1        1

2004        14        14        0        0

2003        14        14        5        5

2002        14        14        4        4

2001        14        14        3        3

2000        14        14        2        2

1999        14        14        0        0



2007        3        14        2        2

2006        3        14        1        1

2005        3        14        0        0

2004        3        14        6        6

2003        3        14        4        4

2002        3        14        3        3

2001        3        14        2        2

2000        3        14        1        1

出0入0汤圆

发表于 2007-3-14 10:08:42 | 显示全部楼层
有人看懂d+2*m+3*(m+1)/5是怎么来的吗?

出0入0汤圆

 楼主| 发表于 2007-3-14 11:08:37 | 显示全部楼层
呵呵,现在只知道用,还不知道公式的由来,算是衣来伸手,饭来张口之类,有知道的不妨说说.

出0入0汤圆

发表于 2007-3-14 11:35:29 | 显示全部楼层
我想问一下7楼:"每四年有一个闰年,每一百年要减去一个闰年,每四百年要加回一个闰年。

因此,今天是:  

    (7 - 1) / 4 = 1

    (2 + (7 - 1) + 1) % 7 = 9 % 7 = 2, 不信你在窗口右下角的时间上双击鼠标看看是不是星期二。 "是什么意思,怎么看不明白呢?

出0入0汤圆

发表于 2007-3-14 12:13:58 | 显示全部楼层
每四年有一个闰年,每一百年要减去一个闰年,每四百年要加回一个闰年。

---------------------

这个没什么问题吧?







(7 - 1) / 4 = 1

^   ^        ^

200(7) 200(1)年之间有(1)个闰年(2004年)





(2 + (7 - 1) + 1) % 7 = 9 % 7 = 2

^    ^   ^    ^

基础日是星期(2), 200(7) 200(1)年总共过了几年,总共有(1)个闰年,至于每一百年每四百年没有计算,因为还不到一百年嘛。一行写完, 完整的写法就是:

(2 + (2007 - 2001) + (2007 - 2001)/4 - (2007 - 2001)/100 + (2007 - 2001)/400 ) % 7



这是针对单片机的优化算法,可以参考一下我用m8做的电子日历的Calendar.cpp文件里的描述。

出0入0汤圆

发表于 2007-3-14 20:10:09 | 显示全部楼层
单片机用查表法即可。



星期计算

1。查表法

int e[]=new int[]{0,3,5,1,3,6,2,4,0,2,5,1};  

if (m<3){  

  m  +=  12;  

  --y;  

}  

int w = (d+2 + e[m-3] +y+(y/4)-y/100+y/400) % 7;



2。基姆拉尔森计算公式

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

在公式中d表示日期中的日数,m表示月份数,y表示年数。

约束条件:  m=1,m=2  时  m=m+12,y=y-1;

对应关系W=0,周日;1,周一;类推

  



闰年计算:         

if ((oYear mod 4=0 and oYear mod 100<>0) or oYear mod 400=0) then ....

出0入0汤圆

发表于 2007-3-14 22:55:26 | 显示全部楼层
顶啊!

出0入0汤圆

发表于 2007-3-15 13:05:26 | 显示全部楼层
基础日是星期(2), 200(7) 200(1)年总共过了几年,总共有(1)个闰年,至于每一百年每四百年没有计算,因为还不到一百年嘛。一行写完, 完整的写法就是:

(2 + (2007 - 2001) + (2007 - 2001)/4 - (2007 - 2001)/100 + (2007 - 2001)/400 ) % 7

假如2001年3月15日是星期4,按照你的公式2008年3月15日是星期5,而实际是星期6.

出0入0汤圆

发表于 2007-3-15 17:09:00 | 显示全部楼层
你说得一点都没错。如果要计算的那年是闰年,并且要计算的那天已经过了2月份,那么括号里是需要修正的,加个1即可。



这是计算21世纪的星期数的代码,看看是不是这么回事:

//计算星期

UCHAR CCalendar::GetWeekday(UCHAR year, UCHAR mon, UCHAR day)

{

    __flash static const UCHAR Weekdays[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};

                                         // 31 28 31 30 31 30 31 31 30 31 30

    return (6-1 + (year>>2) + year + Weekdays[mon-1] + day + (((year & 3) || mon > 2)? 1 : 0)) % 7;

    //完整的计算星期的公式:

    //(year>>2) - (year / 100) + (year/400) + year +

    //    Weekdays[mon-1] + day + ((!isLeap(year) || mon > 2)? 1 : 0)) % 7;

}

出0入0汤圆

发表于 2007-3-15 17:44:45 | 显示全部楼层
哦!!那问题就解决了!!

出0入0汤圆

发表于 2007-3-15 17:56:57 | 显示全部楼层
可是,你知道要修正的原因吗?



    上面描述计算原理里提到:要加间隔的闰年数,没有提到计算时的具体步骤。其实根据推算就了一知道了。

    我们看看01年3月到08年3月,01年到08年计算上是有(8-1)/4 = 1个闰年,但是实际上有04,08两个闰年,因此需要修正一下。

    但是如果是二月份,虽然有两个闰年,但是只经过了一个2月29日(04年),这跟计算式是对应的,因此如果要计算的那年是闰年,那天过了2月份,则需要加1。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-10 19:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表