由于工作需要在嵌入式平台上绘制日历,在网上查找了相关日历的算法和公式,现在总结如下:
首先给出通过指定日期,算出该天是星期几的两个常用公式:
其中最著名的是蔡勒(Zeller)公式。即
w= y + [y / 4]+[c / 4] - 2c + [26(m + 1) / 10] + d - 1 (1)
公式中的符号含义如下,w:星期;c:世纪-1;y:年(两位数);m:月(m 大于等于 3,
小于等于 14,即在蔡勒公式中,某年的 1、2 月要看作上一年的 13、14 月来计算,比如 2003
年 1 月 1 日要看作 2002 年的 13 月 1 日来计算);d:日;[ ]代表取整,即只要整数部分。(C
是世纪数减一,y 是年份后两位,M 是月份,d 是日数。1 月和 2 月要按上一年的 13 月和 14
月来算,这时 C 和 y 均按上一年取值。)算出来的 W 除以 7,余数是几就是星期几。如果余数
是 0,则为星期日。
以 2049 年 10 月 1 日(100 周年国庆)为例,用蔡勒(Zeller)公式进行计算,过程如
下:
蔡勒(Zeller)公式: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 周年国庆)是星期 5。
通过推导公式(1), 人们得到了著名的、也是最常见到的计算星期几的公式。即
W = (Y-1) + [(Y - 1) / 4] - [( Y - 1) / 100] + [(Y - 1) / 400] + D. (2)
其中 D 是这个日子在这一年中的累积天数,把 W 用 7 除,余数是几,这一天就是星期几。
比如计算2013年1月1日是星期几,
W = 2013 - 1 + [(2013 - 1) / 4] - [(2013 - 1) / 100] + [(2013 - 1) / 400] + 1
= 2012 + 503 - 20 + 5 + 1
= 2501
W % 7 = 2501 % 7 = 2;所以得到2013年1月1日是星期二。
又如:算2004年5月1日:
W = (2004-1) + [(2004-1)/4] - [(2004-1)/100] + [(2004-1)/400] + (31+29+31+30+1)
=2610,
2610 / 7 = 104528……6,余数为六,说明这一天是星期六。这和事实是符合的。
源代码:http://download.csdn.net/detail/maimang1001/6640331
以下给出一个用C语言实现的程序:
$gcc calendar.c -o calendar
$./calendar 2012 12
程序输出入下:
the year is 2013
the month is 6
*** JUNE ***
SUN MON TUE WED THU FRI STA
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 2 0 21 22
23 24 25 26 27 28 29
30
以下是source code
/**************************************************************
** file name: calendar.c
** descriptor: print the year's calendar
***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int monthday[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char monthname[13][5] = {"", "JAN", "FEB", "MAR", "APR", "MAY", "JUNE", "JULY", "AUG", "SEP", "OCT", "NOV", "DEC"};
char weekday[8][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "STA", "SUN"};
int calendar[6][7];
int querymonth = 0;
int isLeapyear(int year)
{
return (((year % 4 == 0) && (year & 100 != 0)) || (year % 400 == 0));
}
void printCalendar(int month, int line)
{
int i, j;
printf("*** %s ***\n", monthname[month]);
for (i = 0; i <= 6; i++)
{
printf("%5s", weekday[i]);
}
printf("\n");
for (i = 0; i < line; i++)
{
for (j = 0; j <= 6; j++)
{
if (0 == calendar[i][j])
{
printf(" ");
}
else
{
printf("%5d", calendar[i][j]);
}
}
printf("\n");
}
}
void generateCalendar(int year)
{
int month;
int todayweek, today;
int line = 0;
if (isLeapyear(year))
{
monthday[2] = 29;
}
else
{
monthday[2] = 28;
}
/* calcualte the year first day, what the day it is */
todayweek = (year + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) % 7;
//printf("---------------- todayweek %d ------------\n", todayweek);
for (month = 1; month <= 12; month++)
{
memset((char *)calendar, 0, sizeof(calendar));
today = 1;/* the first day of the month */
line = 0;/* the first day of the must be at the calendar first line */
while (today <= monthday[month])
{
calendar[line][todayweek] = today;
todayweek++;
today++;
if (7 == todayweek)
{
todayweek = 0;
line++;
}
}
if ((today > monthday[month]) && (todayweek != 0))
{
line++;
}
if (querymonth) /* if user input the month then only print the month's calendar */
{
if (querymonth == month)
{
//printf("================= total line = %d ===============\n", line);
printCalendar(month, line);
}
}
else /* the user not input the month, print every month's calendar of the year */
{
//printf("================= total line = %d ===============\n", line);
printCalendar(month, line);
}
}
}
int main(int argc, char * argv[])
{
int year;
if (argc != 2 && argc != 3)
{
printf("Usage:\n%s year\n\tget the year's calendar of every month\
\n%s year month\n\tget the calendar of the month in the year\n", argv[0], argv[0]);
return;
}
year = atoi(argv[1]);
querymonth = 0;
printf("the year is %s\n", argv[1]);
if (3 == argc)
{
printf("the month is %s\n", argv[2]);
querymonth = atoi(argv[2]);
if (querymonth > 12 || querymonth <= 0)
{
printf("an error ocuur! the input month is invalid!\n");
return;
}
}
generateCalendar(year);
}