打印日历程序

由于工作需要在嵌入式平台上绘制日历,在网上查找了相关日历的算法和公式,现在总结如下:

首先给出通过指定日期,算出该天是星期几的两个常用公式:


其中最著名的是蔡勒(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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值