搜索
bottom↓
楼主: hexixiaomao

一个非常简洁的 程序 计算2000~2099年任一天是星期几【恢复】

[复制链接]

出0入0汤圆

发表于 2010-1-12 20:04:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-12 20:16:40 | 显示全部楼层
一个比一个强呀

出0入0汤圆

发表于 2010-1-12 20:39:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-23 20:45:52 | 显示全部楼层
收到 谢谢

出0入0汤圆

发表于 2010-2-23 20:56:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-23 21:00:44 | 显示全部楼层
28楼的程序貌似在闰年的二月时星期不对

出0入0汤圆

发表于 2010-2-23 23:30:43 | 显示全部楼层
用得着,顶啊!

出0入0汤圆

发表于 2010-2-24 13:36:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-24 14:22:44 | 显示全部楼层
回复【楼主位】hexixiaomao 猫云澜
-----------------------------------------------------------------------

hao

出0入0汤圆

发表于 2010-2-24 17:27:20 | 显示全部楼层
mark!

出0入0汤圆

发表于 2010-2-24 19:11:04 | 显示全部楼层
大号!

出0入0汤圆

发表于 2010-2-24 19:38:42 | 显示全部楼层
号号

出0入0汤圆

发表于 2010-2-24 20:43:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-24 23:09:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-25 00:17:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-25 14:23:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-25 14:30:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-25 14:43:06 | 显示全部楼层
公式:从某个基准日开始,算到你要计算的那天的总天数,再MOD 7就行了。

    比如:作为200年1月1日起始日(这天是周六),到2010年2月25日,则总天数为:

    (((2010-2000)/4)*(365*3 +366)+((2010-2000)%4)*365 +1) +1*31 +25 = 3708天

    (3708+6) % 7 = 4,表示2010年2月25日是周四。

    说明:中间的那个1,是因为4年周期的第1年是闰年,要多一天,如果是算2008年的话,这一天就不要加了。

出0入0汤圆

发表于 2010-2-25 14:54:18 | 显示全部楼层
完整的万年历程序如下:
#define ONE_YEAR                ((u32)365)
#define FOUR_YEAR                ((u32)365*3 + 366)
#define ONE_DAY                 ((u32)60*60*24)
#define ONE_HOUR                ((u32)60*60)
#define ONE_MINUTE                ((u32)60)

uc16        pp1[] = {0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
uc16        pp2[] = {0,31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};

typedef struct
{
        u16        year;
        u8        mon;
        u8        day;
        u8        hour;
        u8        min;
        u8        sec;
        u8        week;
}RT_Time;

void GetCurrentTime(RT_Time* p, u32 seconds)                                // 以秒换算日期
{                                                                                                                                // 以2000年1月1日0点为起点,周六
        u32 day, tmp, tmp1;
        u16 const *t;

        day         = seconds / ONE_DAY;                                        // 天数
        seconds        = seconds % ONE_DAY;
        p->hour        = seconds / ONE_HOUR;                                        // 小时
        seconds        = seconds % ONE_HOUR;
        p->min        = seconds / ONE_MINUTE;                                        // 分
        p->sec        = seconds % ONE_MINUTE;                                        // 秒
        p->week        = (day+6) %7;

        tmp = (day / FOUR_YEAR)<<2;                                        // 4年为一个计算周期
        day = day % FOUR_YEAR;                                                // 以4年为周期的余数
        tmp1= day / ONE_YEAR;                                                / 余数的年数

        if(tmp1 == 4)                                                        // 唯一的可能:4年为周期的最后一天,12月31日
        {
                p->year = 2000 + tmp + 3;                                // 实际年份 = 2000年 + 4年期 + 4年期余数
                p->mon        = 12;                                                // 12月
                p->day        = 31;                                                // 31日
                return;                                                                       
        }
        else if(tmp1 == 0)
        {
                p->year = 2000 + tmp ;                                        // 年份 = 2000 + 4年的周期年数
                t = pp2;                                                // 用闰年的日期来计算
        }
        else
        {
                p->year = 2000 + tmp + tmp1;                                // 年份 = 2000 + 4年的周期年数 + 余数的年数
                day = day - (ONE_YEAR*tmp1) -1;                                // 第0年有366天,要多减1天
                t = pp1;                                                // 用非闰年的日期来计算
        }

        for(tmp =1; tmp <13; tmp++)                                        // 月份从1开始,不超过12
        {
                if(day < t[tmp])                                        // 如果在这个月内
                {
                        p->mon = tmp;                                        // 置月份
                        p->day = day - t[tmp-1] +1;                        // 计算日期
                        return;
                }
        }
}

u32 SetTime(RT_Time* p)                                                        // 以日期换算成秒
{
        u32 tmp,tmp1, day, year;
        u16 const *t;

        year= p->year - 2000;
        tmp = year>>2;                                                        // 把年换算成4年周期
        tmp1= year %4;                                                        // 4年周期的余数

        if(tmp1 != 0)                                                        // 如果不是4年周期的第1年
        {
                day= tmp * FOUR_YEAR + tmp1 * ONE_YEAR +1;                // 整年天数 = 4年周期数 * 4年天数 + 4年周期的余数*非闰年天数 +1(第1年为闰年,多1天)
                t = pp1;                                                // 以非闰年计数在本年内的天数
        }
        else                                                                // 如果是4年周期的第1年
        {
                day = tmp * FOUR_YEAR;                                        // 整年天数 = 4年周期数 * 4年天数
                t = pp2;                                                // 以闰年计算在本年内的天数
        }

        day = day + t[p->mon-1] + p->day;                                // 天数 = 整年天数 +本年内天数

        return (day* ONE_DAY + p->hour*ONE_HOUR + p->min*ONE_MINUTE +p->sec);        
}

    上述万年历计算中,与具体的器件无关的。2个函数,一个以秒换算成年、月、日、时、分、秒,另一个是以年、月、日、时、分、秒换算成秒。

    以32位的秒数,可以支持136年,从2000年开始计算,可以支持到2136年。

出0入0汤圆

发表于 2010-2-25 17:03:36 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-2-25 19:02:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-25 23:28:01 | 显示全部楼层
学习学习,星期的计算,万年历的计算,有没有谁可以给出最简单的算法呢

出0入0汤圆

发表于 2010-2-25 23:40:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-27 09:20:30 | 显示全部楼层
好东西。。。我写了有几十行

出0入0汤圆

发表于 2010-3-2 15:59:47 | 显示全部楼层
mark了

出50入0汤圆

发表于 2010-3-2 16:28:41 | 显示全部楼层
回复【楼主位】hexixiaomao 猫云澜
// 计算2000~2099年任一天星期几
// year    : 00-99
// month: 01-12
// day     : 01-31
unsigned char GetWeekFromDay(unsigned char year,unsigned char month,unsigned char day)
{
    if( month == 1 || month == 2 )   
    {
        month += 12;
        if( year&gt; 0 )
            year--;
        else
            year = 4;
    }
    // 返回星期几(星期一用1表示,而星期天用7表示)
    return 1+(( day + 2*month + 3*(mont......
-----------------------------------------------------------------------

根据年月日可以算星期
原理是 从2000年1月1日开始计算到输入的日期共有多少天 1个星期有7天 。。。这样可以计算出星期几
当然 闰年也必须考虑

出0入0汤圆

发表于 2010-3-2 17:32:46 | 显示全部楼层
好帖收藏

出0入0汤圆

发表于 2010-3-2 17:50:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-2 21:34:37 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-3 10:03:44 | 显示全部楼层
回复【128楼】tonydh
-----------------------------------------------------------------------

在这里学习了很多也发个天数计算。。。。菜鸟
   #include "stdio.h"
#include "math.h"
int CheckLeap( year)  /*闰年的判断*/
{
        if((year%4 == 0 && year%100 != 0 )|| year%400 == 0)
                return 1;
        else
                return 0;
}
main()   
{
        int iyear,imonth,idate;
        int sumYear = 0,sumMonth = 0,sumDate = 0;
        int i,total=0,month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
       
        while(1)
        {
                printf("please input (iyear-imonth-iday) :       ");
                scanf("%d,%d,%d",&iyear,&imonth,&idate);
                if (!((iyear<0)||(imonth>12)||(imonth<1)))
                if(CheckLeap(iyear))
                {
                        if(imonth==2)
                        if(idate-month[2]-1<=0)
                        break;
                        if (idate-month[imonth]<=0)
                        break;
                }
        else
                {
                        if(idate-month[imonth]<=0)
                        break;
                }       
        }           
   
                                                
        if(CheckLeap(iyear))  
    i=1;
    else
    i=0;
    if(imonth==1)
    sumMonth=idate;
    else if (imonth== 2)
    sumMonth=31+idate;
    else
    sumMonth=13*(imonth+1)/5-7+(imonth-1)*28+idate+i; /*月在那一年中所占的天数*/
    total=sumMonth; /*总共相差的天数*/       
        printf("total=%d\n",total);

}

出0入0汤圆

发表于 2010-3-3 10:11:25 | 显示全部楼层
回复【129楼】tdctdc
-----------------------------------------------------------------------

我的程序不知道在DEBUG的时候很慢,不知道是什么原因。但是程序运行的结果是对的。希望哪位高手解惑下~

出0入0汤圆

发表于 2010-3-16 14:56:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-29 19:29:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-30 01:00:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-30 08:28:34 | 显示全部楼层
markj

出0入0汤圆

发表于 2010-4-10 21:29:03 | 显示全部楼层
本程序绝对正中,只要输入有效的年月日即可得出正确的星期数。我在好多工程上都是用的这个算法从来没出问题ourdev_545407.rar(文件大小:8K) (原文件名:weekconvter.rar)

出0入0汤圆

发表于 2010-4-10 21:59:02 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-4-11 13:52:59 | 显示全部楼层
回复【28楼】wqsjob
-----------------------------------------------------------------------

28楼的楼主你好!我想请问2000.2.29日。  是星期三吗?好像是星期二吧。你的这个程序是有问题的。

出0入0汤圆

发表于 2010-4-11 14:01:22 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-4-11 14:57:38 | 显示全部楼层
人才

出0入0汤圆

发表于 2010-4-11 14:57:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-11 15:15:39 | 显示全部楼层
mark~

出0入0汤圆

发表于 2010-4-11 16:09:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-11 21:18:00 | 显示全部楼层
good

出0入0汤圆

发表于 2010-4-12 14:02:06 | 显示全部楼层
mark在看

出0入0汤圆

发表于 2010-4-13 15:57:14 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-4-14 13:08:56 | 显示全部楼层
顶起来

出0入0汤圆

发表于 2010-5-3 08:54:08 | 显示全部楼层
值得学习

出0入0汤圆

发表于 2010-5-3 22:06:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-5 08:42:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-5 08:57:48 | 显示全部楼层
标记一下。

出0入0汤圆

发表于 2010-5-5 09:35:52 | 显示全部楼层
不错

出0入0汤圆

发表于 2010-5-5 09:51:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-5 11:33:20 | 显示全部楼层
马克

出0入0汤圆

发表于 2010-5-5 11:51:38 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-5-5 14:27:46 | 显示全部楼层
马克  嘿嘿

出0入0汤圆

发表于 2010-5-5 15:53:06 | 显示全部楼层
验证后
怎么不准呢
过了一天

出0入0汤圆

发表于 2010-5-5 15:57:24 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2010-5-5 21:27:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-29 17:06:00 | 显示全部楼层
好好研究一下

出0入0汤圆

发表于 2010-6-29 18:13:50 | 显示全部楼层
回复【楼主位】hexixiaomao 猫云澜
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2010-6-29 18:57:39 | 显示全部楼层
回复【28楼】wqsjob
//我一直在用的代码,呵呵,至少我觉得比楼主的效率高,不论空间还是时间,另外,扩展个几千年也很容易。
//51的话,可以定义在code,不光省ram,还节省代码空间(少一条mov指令)。
uchar        weekdata[]={0,3,3,6,1,4,6,2,5,0,3,5};
/*2000-2099*/
unsigned char getweekday(unsigned char year,unsigned char month,unsigned char day)  
{
        return        ((6+weekdata[month-1]+year+day+year/4)%7);
}
刚才忘了说了,这里0代表星期天,使用者应该加上日前限定的功能。<font color=#699bcd>
本贴被 wqsjob 编辑过,最后修改时间:2008-......
-----------------------------------------------------------------------

我现在使用的方法与你相似!

出0入0汤圆

发表于 2010-6-29 19:07:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-29 19:34:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-29 21:30:17 | 显示全部楼层
MARK 星期算法

出0入0汤圆

发表于 2010-6-30 09:15:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-30 15:02:35 | 显示全部楼层
非常好,喜欢这样的算法分析

出0入0汤圆

发表于 2010-6-30 15:24:57 | 显示全部楼层
谢谢分享!!!

出0入0汤圆

发表于 2010-8-20 19:34:30 | 显示全部楼层
强 很强

出0入0汤圆

发表于 2010-8-20 19:51:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-20 21:02:46 | 显示全部楼层
回复【161楼】hubertboy  
-----------------------------------------------------------------------
还是你的这个代码更好,而且一看就明白怎么回事

出0入0汤圆

发表于 2010-8-20 21:06:57 | 显示全部楼层
makeyixia

出0入0汤圆

发表于 2010-8-20 21:51:33 | 显示全部楼层
老帖子了

出0入0汤圆

发表于 2010-8-21 00:00:41 | 显示全部楼层
必须马克

出0入0汤圆

发表于 2010-8-21 00:11:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-21 02:04:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-21 08:33:18 | 显示全部楼层
蔡勒(Zeller)公式:是一个计算星期的公式。
随便给一个日期,就能用这个公式推算出是星期几。

蔡勒公式如下:
W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1

公式中的符号含义如下:
w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六
c:世纪-1(前两位数)
y:年(后两位数)
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余2,注意对负数的取模运算!)

不过,以上的公式都只适合于1582年(我国明朝万历十年)10月15日之后的情形。罗马教皇格里高利十三世在1582年组织了一批天文学家,根据哥白尼日心说计算出来的数据,对儒略历作了修改。将1582年10月5日到14日之间的10天宣布撤销,继10月4日之后为10月15日。
后来人们将这一新的历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历或公历。

出0入0汤圆

发表于 2010-8-21 08:35:17 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-8-21 10:45:27 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-21 11:25:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-22 10:00:49 | 显示全部楼层
回复【楼主位】hexixiaomao 猫云澜
-----------------------------------------------------------------------

貌似return后面的1要去掉才对

出0入0汤圆

发表于 2010-8-22 10:18:57 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-9-5 10:33:43 | 显示全部楼层
好贴,非常感谢,使用上了,呵呵……

出0入0汤圆

发表于 2010-9-5 11:39:26 | 显示全部楼层
mark!

出20入186汤圆

发表于 2010-9-5 12:13:33 | 显示全部楼层
mark 日期算法

出0入0汤圆

发表于 2010-9-5 13:53:47 | 显示全部楼层
标记

出0入0汤圆

发表于 2010-9-5 14:49:09 | 显示全部楼层
回复【176楼】gentlerain
-----------------------------------------------------------------------

你太强悍了啊,一直在研究这个啊

出0入0汤圆

发表于 2010-9-6 10:31:23 | 显示全部楼层
受教了,谢谢各位强人

出0入0汤圆

发表于 2010-9-9 15:56:52 | 显示全部楼层
TUWEN

出0入0汤圆

发表于 2010-9-9 16:24:41 | 显示全部楼层
有用的

出0入0汤圆

发表于 2010-9-16 16:03:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-7 22:05:16 | 显示全部楼层
马上用

出0入0汤圆

发表于 2010-10-8 07:03:54 | 显示全部楼层
thx 4 share。

出0入0汤圆

发表于 2010-10-8 08:23:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 12:18:29 | 显示全部楼层
我也转贴一下

一:常用公式

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

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

二:蔡勒(Zeller)公式

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

  公式中的符号含义如下,w:星期;c:世纪;y:年(两位数); m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。

   相比于通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。

三:对蔡勒(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)公式中的含义相同。

四:基姆拉尔森计算公式

  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来代入公式计算。好像就是公式

出0入0汤圆

发表于 2010-10-8 13:56:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 15:15:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 18:45:59 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 19:26:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-8 22:19:57 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-16 04:04

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

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