命令行下的calendar工具
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
/****************************
*
* 模仿Linux 下的 cal命令
*
* cal
* 无参数显示当前月日历
* -h 帮助信息
* -m 指定月(1--12)
* -y 指定年(>1900)
* -j 显示本年的第几天,默认显示日期
* -y,-m 缺省为当前年、月
*
* for example:
*
* $>cal -y 1997 -m 12
* $>cal -y 1997
* $>cal -m 12
* $>cal -y 2008 -j
*
*
* 操作系统对year的限制不同
* Window :一般从1970~2038
* Linux : 基本没有限制
*
*
*
* author:zhanglihai
* date : 2008/02/20
* **************************/
//定义月的英文描述
char *month_name_en[12]={"January","February","March","April","May","June","July","August","September","October","November","December"};
char *week_name_en[7]={"Sun", "Mon", "Tue","Wed", "Thu", "Fri", "Sat"};
char *animals[12] = { "鼠", "牛", "虎", "兔",
"龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
int month_max_day[12]={31,28,31,30,31,30,31,31,30,31,30,31};
typedef struct tm Date;
typedef struct tm *PDate;
void printHelp(){
printf("\n模仿Linux 下的 cal命令"
"\n\n"
"cal\n"
"无参数显示当前月日历"
"\n\n"
"-h 帮助信息\n"
"-m 指定月(1--12)\n"
"-y 指定年(>1900)\n"
"-j 显示本年的第几天,默认显示日期\n"
"\n\n"
"-y,-m 缺省为当前年、月\n"
"\n"
"for example:\n"
"$>cal -y 1997 -m 12\n"
"$>cal -y 1997\n"
"$>cal -m 12\n"
"$>cal -y 2008 -j \n"
"\n"
"操作系统对year的限制不同\n"
"Window :一般从1970~2038\n"
"Linux : 基本没有限制\n"
"\n\n"
" author : zhanglihai\n"
" date : 2008/02/20\n");
}
int monthMaxDay(int y,int m){
int y1=y+1900;
if(m==1)
{
if((y1%400==0)||(y1%4==0&&y1%100!=0))
return 29;
}
return month_max_day[m];
}
void printYearCal(PDate pdate,int fmt)
{
int i,j,w,left;
int m_len;
int max_day1,max_day2;
int day1,day2,gday1,gday2;
int wday1,wday2;
int year=pdate->tm_year;
time_t _tm;
PDate _pdate;
pdate->tm_mon=0;
pdate->tm_mday=1;
_tm=mktime(pdate);
if(_tm==-1)
{
printf("can't mktime . \n");
printf("-h help info.\n");
return;
}
printf("\n%*d %s\n\n",(27*2-4*2-4)/2+10,pdate->tm_year+1900,animals[((pdate->tm_year+1900)-4)%12]);
_pdate=localtime(&_tm);
wday1=_pdate->tm_wday;
day1=day2=gday1=gday2=1;
for(i=0;i<12;i+=2)
{
day1=day2=1;
max_day1=monthMaxDay(year,i);
max_day2=monthMaxDay(year,i+1);
wday2=(max_day1-(7-wday1))%7;
//输出月英文名字
m_len=strlen(month_name_en[i]);
left=(27-m_len)/2+m_len;
printf("%*s",left,month_name_en[i]);
//剩下的位置用空格补齐
for(j=0;j<27-left;j++)
printf(" ");
//输出4个空格作为间隔
for(j=0;j<4;j++)
printf(" ");
//输出横排第二个月的名字
m_len=strlen(month_name_en[i+1]);
left=(27-m_len)/2+m_len;
printf("%*s\n",left,month_name_en[i+1]);
//开始输出星期的英文名字
printf("%s",week_name_en[0]);
for(j=1;j<7;j++)
{
printf("%4s",week_name_en[j]);
}
for(j=0;j<4;j++)
printf(" ");
printf("%s",week_name_en[0]);
for(j=1;j<7;j++)
{
printf("%4s",week_name_en[j]);
}
printf("\n");
//星期的英文名字输出完毕
//开始输出当前月的日期
//一行一行的输出,同时输出两个月的
//每个月的日期是一个6*7的方形矩阵
//先输出第一个行,
if(i!=0){
gday2=gday1+max_day1;
}
else
gday2=1+max_day1;
//输出站位空字符
for(w=0;w<wday1;w++)
{
if(w==0)
printf("%3s"," ");
else
printf("%4s"," ");
}
//输出日期
for(;w<7;w++)
{
if(w==0){
printf("%3d",fmt?gday1:day1);
}
else{
printf("%4d",fmt?gday1:day1);
}
day1++;
gday1++;
}
//第一个月的第一行输出完毕
//输出4个空格作为间隔
printf("%4s"," ");
//输出第二个月的第一行
//此处应该可以根据上一个月算出从第几个开始
//输出站位空字符
for(w=0;w<wday2;w++)
{
if(w==0)
printf("%3s"," ");
else
printf("%4s"," ");
}
//输出日期
for(;w<7;w++)
{
if(w==0){
printf("%3d",fmt?gday2:day2);
}
else{
printf("%4d",fmt?gday2:day2);
}
day2++;
gday2++;
}
printf("\n");
//开始下面的输出
for(j=1;j<6;j++)
{
//第一个矩阵
//开始输出日期
for(w=0;w<7;w++)
{
if(day1<=max_day1)
{
if(w==0){
printf("%3d",fmt?gday1:day1);
}
else{
printf("%4d",fmt?gday1:day1);
}
day1++;
gday1++;
}else{
if(w==0)
printf("%3s"," ");
else
printf("%4s"," ");
}
}
printf("%4s"," ");
//第二个矩阵
//gday2=gday1+max_day1;
for(w=0;w<7;w++)
{
if(day2<=max_day2)
{
if(w==0)
printf("%3d",fmt?gday2:day2);
else
printf("%4d",fmt?gday2:day2);
day2++;
gday2++;
}else{
if(w==0)
printf("%3s"," ");
else
printf("%4s"," ");
}
}
printf("\n");
}
gday1=gday2;
wday1=(max_day1-(7-wday2)) % 7;
}
printf("\n");
}
void printMonthOnYearCal(PDate date,int fmt){
int i;
int m_len;
int day;
int max_day;
int p=1;
max_day=monthMaxDay(date->tm_year,date->tm_mon);
printf("%*s %d %s\n",(27-(m_len=strlen(month_name_en[date->tm_mon])))/2+m_len-4,month_name_en[date->tm_mon],date->tm_year+1900,animals[((date->tm_year+1900)-4)%12]);
printf(week_name_en[0]);
for(i=1;i<7;i++)
{
printf("%*s",4,week_name_en[i]);
}
printf("\n");
for(i=0;i<date->tm_wday;i++)
{
if(i==0)
printf("%*s",3," ");
else
printf("%*s",4," ");
}
day=1;
if(fmt==1)
day=date->tm_yday+1;
for(;i<7;i++){
if(i==0)
printf("%*d",3,day++);
else
printf("%*d",4,day++);
if(i==6){
i=-1;
printf("\n");
}
if(p++>=max_day)
break;
}
printf("\n");
}
int main(int argc,char *argv[]){
int y;
int m;
int fmt;
fmt=0;
y=-1;
m=-1;
time_t c_tm;
time_t c_tm2;
PDate pdate;
PDate pdate2;
int i;
for(i=1;i<argc;)
{
if(!strcmp(argv[i],"-m")&&(i+1<argc))
{
m=atoi(argv[i+1])-1;
if(m<0||m>11)
{
printf("month range (1~12)\n");
printf("-h help info.\n");
exit(0);
return 0;
}
i+=2;
}
else if(!strcmp(argv[i],"-y") && (i+1<argc)){
y = atoi(argv[i+1])-1900;
if(y<=0)
{
printf("year range (>1900)\n");
printf("-h help info.\n");
exit(0);
return 0;
}
i+=2;
}else if(!strcmp(argv[i],"-j"))
{
i++;
fmt=1;
}else if(!strcmp(argv[i],"-h"))
{
printHelp();
exit(0);
return 0;
}else {
printHelp();
exit(0);
return 0;
}
}
time(&c_tm);
pdate=localtime(&c_tm);
if(m==-1)
{
if(y>0)
{
pdate->tm_year=y;
printYearCal(pdate,fmt);
}else{
printMonthOnYearCal(pdate,fmt);
}
}else{
if(y>0)
{
pdate->tm_year=y;
pdate->tm_mon=m;
pdate->tm_mday=1;
c_tm2=mktime(pdate);
if(c_tm2==-1)
{
printf("can't mktime . \n");
printf("-h help info.\n");
exit(0);
return 0;
}
pdate2=localtime(&c_tm2);
printMonthOnYearCal(pdate2,fmt);
}else{
printMonthOnYearCal(pdate,fmt);
}
}
return 0;
}
update:
增加了一个小功能,可以在控制台输出带颜色的字体。
引用windows.h文件调用里面的
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if(h)
SetConsoleTextAttribute(h,color);
可以达到效果,只更新了-h,及月视图的颜色,如果年视图带颜色感觉有点乱了:)
看截图及最新代码下载
http://www.zhanglihai.com/b//uploadfiles/cal_69841.c
屏幕带颜色的代码
http://www.zhanglihai.com/b//uploadfiles/cal_41820.c
EXE文件下载。
http://www.zhanglihai.com/b//uploadfiles/cal_exe_57206.zip

