#include "stdafx.h"
#include "string.h"
#include "math.h"
#include "string"
#include "time.h"
#include "math.h"
#include <windows.h>
using namespace std;
// Calendar.cpp : Defines the entry point for the console application.
//
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
long lYearDays(long y) ;
long leapMonth(long y);
long leapDays(long y);
long monthDays(long y, long m);
//====================== 中文日期
string cDay(unsigned char day);
typedef struct
{
unsigned short year;
unsigned char month;
unsigned char day;
bool isLeap;
} MyDate;
void Lunar(MyDate& dateIn, MyDate & dateOut);
void Lunar(long offset, MyDate & dateOut);
// ---------------------------------------------------------------------------
/*
万年历全集
程序可以实现如下三种功能:
求某个日期对应的星期
求某年某月有的天数
输出某年的日历.
例如,打印2008年日历如下:
-------------------------------------------------------------------------
2008 年
--------------------------------------------------------------------------
一 月 二 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 2 3 4 5 1 2
6 7 8 9 10 11 12 3 4 5 6 7 8 9
13 14 15 16 17 18 19 10 11 12 13 14 15 16
20 21 22 23 24 25 26 17 18 19 20 21 22 23
27 28 29 30 31 24 25 26 27 28 29
三 月 四 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 1 2 3 4 5
2 3 4 5 6 7 8 6 7 8 9 10 11 12
9 10 11 12 13 14 15 13 14 15 16 17 18 19
16 17 18 19 20 21 22 20 21 22 23 24 25 26
23 24 25 26 27 28 29 27 28 29 30
30 31
五 月 六 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 2 3 1 2 3 4 5 6 7
4 5 6 7 8 9 10 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30
七 月 八 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 2 3 4 5 1 2
6 7 8 9 10 11 12 3 4 5 6 7 8 9
13 14 15 16 17 18 19 10 11 12 13 14 15 16
20 21 22 23 24 25 26 17 18 19 20 21 22 23
27 28 29 30 31 24 25 26 27 28 29 30
31
九 月 十 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 2 3 4 5 6 1 2 3 4
7 8 9 10 11 12 13 5 6 7 8 9 10 11
14 15 16 17 18 19 20 12 13 14 15 16 17 18
21 22 23 24 25 26 27 19 20 21 22 23 24 25
28 29 30 26 27 28 29 30 31
十一 月 十二 月
周日 周一 周二 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六
1 1 2 3 4 5 6
2 3 4 5 6 7 8 7 8 9 10 11 12 13
9 10 11 12 13 14 15 14 15 16 17 18 19 20
16 17 18 19 20 21 22 21 22 23 24 25 26 27
23 24 25 26 27 28 29 28 29 30 31
30
// 二,打印版(:即既能输出到屏幕,又可输出到文件)
/*万年历全集:程序可以实现如下三种功能:
求某个日期对应的星期
求某年某月有的天数
输出某年的日历
*/
/*2006-1-2 梁见斌*/
#include <stdlib.h>
#include <stdio.h>
struct mon
{
int maxdata;
int data;
};
void SeekWeekDay(void); //求某个日期对应的星期函数
int WeekDay(int year, int month, int day); //根据输入的日期,返回对应的星期
void HowManyDays(void);//求某年某月有的天数函数
int MonthDays(int year, int month);//根据输入的年号和月份,返回该月的天数
void PrintWeek(int weekday, FILE *fp);//打印星期几
void PrintMonth(int month, FILE *fp); //打印月份
void PrintData(); //打印日历
void TestYear();
int main(void)
{
int choice;
// 400年中有97个闰年
// int j = 0;
// for (int i=1900; i<2299; ++i)
// {
// if (isleap(i))
// {
// printf("%d ", i);
// ++j;
// if ((j%10)==0)
// {
// printf("/n");
// }
// }
// }
// printf("/n");
while (1) {
TestYear();
}
while(1)
{
puts("------------------------------------------");
puts("请输入您的选择:");
puts("输入1求某个日期对应的星期");
puts("输入2求某年某月有的天数");
puts("输入3输出某年的日历");
puts("输入4结束程序");
puts("------------------------------------------");
scanf("%d", &choice); fflush(stdin);
switch(choice)
{
case 1: SeekWeekDay(); break;
case 2: HowManyDays(); break;
case 3: PrintData(); break;
case 4: return 0;
default: puts("输入错误,请重新输入"); break;
}
printf("/n"); printf("/n");
}
system("pause");
return 0;
}
// 求某年某月有的天数函数
void HowManyDays(void)
{
int year, month, days;
puts("请输入年号和月份:");
scanf("%d%d", &year, &month); fflush(stdin);
printf("你的输入为 %d年%d月,", year, month);
days = MonthDays(year, month); // 根据输入的年号和月份,返回该月的天数
printf(" %d年%d月有%d天/n", year, month, days);
}
// 求某个日期对应的星期函数
void SeekWeekDay(void)
{
FILE *fp;
int year, month, day, weekday;
if ( (fp=fopen("wnlweek.txt","w+")) == NULL)
{
fprintf(stderr,"/nError opening file/n");
exit(1);
}
puts("请输入年,月, 日:");
scanf("%d%d%d", &year, &month, &day); fflush(stdin);
printf("你的输入为 %d年%d月%d日/n", year, month, day);
weekday = WeekDay(year, month, day); // 根据输入的日期,返回对应的星期
printf("这天是 ");
PrintWeek(weekday, fp); // 打印星期几
}
// 打印星期几
void PrintWeek(int weekday, FILE *fp)
{
switch(weekday)
{
case 0 : fprintf(stdout, "%s","周日 "); fprintf(fp, "%s","周日 "); break;
case 1 : fprintf(stdout, "%s","周一 "); fprintf(fp, "%s","周一 "); break;
case 2 : fprintf(stdout, "%s","周二 "); fprintf(fp, "%s","周二 "); break;
case 3 : fprintf(stdout, "%s","周三 "); fprintf(fp, "%s","周三 "); break;
case 4 : fprintf(stdout, "%s","周四 "); fprintf(fp, "%s","周四 "); break;
case 5 : fprintf(stdout, "%s","周五 "); fprintf(fp, "%s","周五 "); break;
case 6 : fprintf(stdout, "%s","周六 "); fprintf(fp, "%s","周六 "); break;
}
}
void PrintMonth(int month, FILE *fp) //打印月份
{
switch(month)
{
case 1 : fprintf(stdout, "%s","一 月 "); fprintf(fp, "%s","一 月 ");break;
case 2 : fprintf(stdout, "%s","二 月 "); fprintf(fp, "%s","二 月 ");break;
case 3 : fprintf(stdout, "%s","三 月 "); fprintf(fp, "%s","三 月 ");break;
case 4 : fprintf(stdout, "%s","四 月 "); fprintf(fp, "%s","四 月 ");break;
case 5 : fprintf(stdout, "%s","五 月 "); fprintf(fp, "%s","五 月 ");break;
case 6 : fprintf(stdout, "%s","六 月 "); fprintf(fp, "%s","六 月 ");break;
case 7 : fprintf(stdout, "%s","七 月 "); fprintf(fp, "%s","七 月 ");break;
case 8 : fprintf(stdout, "%s","八 月 "); fprintf(fp, "%s","八 月 ");break;
case 9 : fprintf(stdout, "%s","九 月 "); fprintf(fp, "%s","九 月 ");break;
case 10: fprintf(stdout, "%s","十 月 "); fprintf(fp, "%s","十 月 ");break;
case 11: fprintf(stdout, "%s","十一 月 "); fprintf(fp, "%s","十一 月 ");break;
case 12: fprintf(stdout, "%s","十二 月 "); fprintf(fp, "%s","十二 月 ");break;
}
}
// 根据输入的日期,返回对应的星期
int WeekDay(int year, int month, int day)
{
int i;
int run=0, ping=0; // 闰年和平年个数
long sum;
// for(i=1; i<year; i++) {
// if(i%4==0 && i%100!=0 || i%400==0)
// run++;
// else
// ping++;
// }
// // 计算总天数
// sum = 366*run + 365*ping;
// for(i=1; i<month; i++)
// sum += MonthDays(year, i);
// sum += day;
/*
万年历的公式:S=X-1+(X-1)/4-(X-1)/100+(X-1)/400+C
说明:X为公元年数;
C为从元旦起,到要算的那天总天数(如:2003年2月13日,C=31+13=44)
S/7余数为星期几(如余数为0,1,2,3,4,5,6。分别为星期天,星期一,二,
三,四,五,六)
*/
sum = year-1 + (year-1)/4 - (year-1)/100 + (year-1)/400;
for(i=1; i<month; i++)
sum += MonthDays(year, i);
sum += day;
return (int)sum%7;
}
// 根据输入的年号和月份,返回该月的天数
int MonthDays(int year, int month)
{
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12: return 31;
case 4:
case 6:
case 9:
case 11: return 30;
case 2:
if(year%4==0 && year%100!=0 || year%400==0)
return 29;
else
return 28;
default: puts("这是一个错误的月份!"); system("pause"); return 0;
}
}
// 打印日历,对输出格式的控制较复杂
void PrintData(void)
{
FILE *fp;
struct mon month[13];
int i, j, k;
int year, mon, week;
if ( (fp=fopen("wnldata.txt","w+")) == NULL)
{
fprintf(stderr,"/nError opening file/n");
exit(1);
}
puts("请输入年号:");
scanf("%d", &year);
fprintf(stdout, "--------------------------------------------------------------------------/n");
fprintf(fp, "--------------------------------------------------------------------------/n");
fprintf(stdout, "%35d %s/n", year, "年"); fprintf(fp, "%35d %s/n", year,"年");
fprintf(stdout, "--------------------------------------------------------------------------/n");
fprintf(fp, "--------------------------------------------------------------------------/n");
for(i=1; i<13; i++) //存储该年每个月的总天数和初始日期
{
month[i].data = 1;
month[i].maxdata = MonthDays(year, i);
}
for(i=0; i<6; i++) //总共输出6排
{
for(j=1; j<=2; j++)//每排输出2个月
{
mon = 2*i + j;
fprintf(stdout, "%15s", " "); fprintf(fp, "%15s", " ");
PrintMonth(mon, fp); //第一行打印月份
fprintf(stdout, "%15s", " "); fprintf(fp, "%15s", " ");
if(j==1)
{ fprintf(stdout, "/t"); fprintf(fp, "/t"); }
}
fprintf(stdout, "/n"); fprintf(stdout, "/n"); fprintf(fp, "/n"); fprintf(fp, "/n");
for(j=1; j<=2; j++)
{
for(k=0; k<7; k++)
{
PrintWeek(k, fp); //第2行打印星期
}
fprintf(stdout, "/t"); fprintf(fp, "/t");
}
printf("/n"); fprintf(fp, "/n");
for(j=1; j<=2; j++)
{
mon = 2*i + j;
week = WeekDay(year, mon, 1); //根据输入的日期,返回对应的星期
//控制输出格式,把每月的1日打印在对应星期的下面
fprintf(stdout, "%*d ", week*5+2, month[mon].data); fprintf(fp, "%*d ", week*5+2, month[mon].data);
month[mon].data++;
week++;
while(week < 7) //接着在该行打印该周剩余的日期
{
fprintf(stdout, "%2d ", month[mon].data); fprintf(fp, "%2d ", month[mon].data);
month[mon].data++;
week++;
}
if(j==1)
{ fprintf(stdout, "/t"); fprintf(fp, "/t"); }
}
fprintf(stdout, "/n"); fprintf(stdout, "/n"); fprintf(fp, "/n"); fprintf(fp, "/n");
//从第4行起打印该月剩余的日期,每7个一行;直至该月日期打印完毕
while(month[2*i+1].data<=month[2*i+1].maxdata || month[2*i+2].data<=month[2*i+2].maxdata)
{
for(j=1; j<=2; j++)
{
mon = 2*i + j;
for(k=0; k<7; k++)
{
if(month[mon].data<=month[mon].maxdata)
{ //如果该月日期未打印完,打印该日期
fprintf(stdout, "%2d ", month[mon].data);
fprintf(fp, "%2d ", month[mon].data);
month[mon].data++;
}
else //否则输出空格
{ fprintf(stdout, " "); fprintf(fp," "); }
}
if(j==1)
{ fprintf(stdout, "/t"); fprintf(fp, "/t"); }
}
fprintf(stdout, "/n"); fprintf(stdout, "/n"); fprintf(fp, "/n"); fprintf(fp, "/n");
}
fprintf(stdout, "/n"); fprintf(fp, "/n");
}
fclose(fp);
}
/*
求一个万年历的算法。输入年,就可输出该年的年历
----------------------------------------------------------------------
lunar calendar 阴历
现在网上有不少万年历的网页,大部分是jsp写的,你查看它的源码就清楚了。大意是将
每年阴历月份的信息记录在一个数组内。然后按图索骥……关键是这组数据。我这有一组
现成的:
1900 ——+150 = 2050
*/
/*
数组中每个数字表示1年,第一个数字0x04bd8代表1900年。
每个数字17bit,前(最高位)1个bit表示闰月(如果有闰月的话)是否大月;
接着的12bit表示每月是否大月;
1表示大月,30天,0表示小月,29天。
最后4个bit表示是否有闰月和闰哪个月(不等于0即代表所闰月的月号)
*/
//int solarYear = 1900; // 公历 1900.1.31 对应农历1900年元月初一
int baseYear = 1899; // 公历 1900.1.1对应的农历:1899.12.1
int DistanceDays = 41; // 公历1989.2.10号是农历1989.1.1号
long lunarInfo[] = {
0x0ab50,
0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2, // 农历1900-1909
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977, // 1910
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970, // 1920
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950, // 1930
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557, // 1940
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0, // 1950
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6, // 1970
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0, // 1990
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5, // 2000-2009
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930, // 2010
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530, // 2020-2029
0x05aa0,0x076a3,0x096d0,0x04afb,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0, // 2040-2049
0x14B63,0x09370,0x049F8
};
int TotalYear = sizeof(lunarInfo)/sizeof(long) + baseYear;
// 传回农历 y年的总天数
long lYearDays(long y)
{
long i, sum = 348; // 29 * 12
for(i=0x8000; i>0x8; i>>=1)
sum += (lunarInfo[y-baseYear] & i)? 1: 0 ;
return(sum+leapDays(y));
}
// 传回农历 y年闰月的天数
long leapDays(long y)
{
if(leapMonth(y))
return((lunarInfo[y-baseYear] & 0x10000)? 30: 29);
else
return(0);
}
// 传回农历 y年闰哪个月 1-12 , 没闰传回 0
long leapMonth(long y)
{
return(lunarInfo[y-baseYear] & 0xf);
}
// 传回农历 y年m月的总天数
long monthDays(long y, long m)
{
return( (lunarInfo[y-baseYear] & (0x10000>>m))? 30: 29 );
}
//------------------------------------------------------------------------------
// 天干, 地支
char Gan[][3] = {"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"};
char Zhi[][3] = {"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};
//============================== 传入 offset 传回干支, 0=甲子
void cyclical(long offset, char GanZhi[5]) {
strcpy(GanZhi, Gan[offset%10]);
strcat(GanZhi, Zhi[offset%12]);
}
char solarTerm[][5] ={"小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"};
// 先给节气进行编号,从近日点开始的第一个节气编为0,编号如下及其相应的月份如下:
// 0 小寒 腊月 6 清明 三月 12 小暑 六月 18 寒露 九月
// 1 大寒 腊月 7 谷雨 三月 13 大暑 六月 19 霜降 九月
// 2 立春 正月 8 立夏 四月 14 立秋 七月 20 立冬 十月
// 3 雨水 正月 9 小满 四月 15 处暑 七月 21 小雪 十月
// 4 惊蛰 二月 10 芒种 五月 16 白露 八月 22 大雪 冬月
// 5 春分 二月 11 夏至 五月 17 秋分 八月 23 冬至 冬月
// 把当天和1900年1月0日(星期日)的差称为积日,那么第y年(1900年算第0年)第x 个节气的积日是
// F = 365.242 * y + 6.2 + 15.22 * x - 1.9 * sin(0.262 * x)
//------------------------------------------------------------------------------
// 算出农历, 传入日期物件, 传回农历日期物件
// 该物件属性有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
void LunarByTerm(long year, int nTerm, MyDate & dateOut)
{
long sum = 365.2422*(year-1900) + 6.2 + 15.22*nTerm - 1.9*sin(0.262*nTerm);
Lunar(sum+365-DistanceDays, dateOut);
}
void TestYear()
{
long day = 0;
printf("请输入公历的年号 月 日 第几个节气(0-23):/n");
long year, m, d, nTerm;
scanf("%d%d%d%d", &year, &m, &d, &nTerm);
printf("你输入的是%d年。/n",year);
printf("%d年的数据为%x。/n",year, lunarInfo[year-baseYear]);
printf("%d年的总天数:%d/n", year, lYearDays(year));
printf("闰月为:%d,天数为:%d/n", leapMonth(year), leapDays(year) );
day += leapDays(year);
for (long i=1; i< 13; i++) {
printf("%d月有%d天。/n", i, monthDays(year, i));
day += monthDays(year, i);
}
printf("总天数:%d/n/n", day);
MyDate d1, d2;
d1.year = 2008;
d1.month = 1;
d1.day = 23;
d1.year = year;
d1.month = m;
d1.day = d;
Lunar(d1, d2);
printf("公历%d年%d月%d日对应的农历为:/n", d1.year, d1.month, d1.day);
char GanZhi[5];
cyclical(d2.year-1864, GanZhi);
printf("农历%d年(%s)%s%d月%s/n", d2.year, GanZhi,
d2.isLeap?"润":"",
d2.month,
cDay(d2.day).c_str()
);
MyDate d3;
LunarByTerm(d1.year, nTerm, d3);
printf("%s为:农历 %d年%s%d月%d日/n/n", solarTerm[nTerm], d3.year,
d3.isLeap?"润":"", d3.month, d3.day);
}
// 算出农历, 传入日期物件, 传回农历日期物件
// 该物件属性有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
void Lunar(MyDate& dateIn, MyDate & dateOut)
{
int i;
int run=0, ping=0; // 闰年和平年个数
long sum;
// 计算当前时间dateIn 和 baseYear 年1月1号 之间的天数差
for(i=baseYear; i<dateIn.year; i++) {
if(i%4==0 && i%100!=0 || i%400==0)
run++;
else
ping++;
}
// 计算总天数
sum = 366*run + 365*ping;
for(i=1; i<dateIn.month; i++)
sum += MonthDays(dateIn.year, i);
sum += dateIn.day;
sum -= DistanceDays;
Lunar(sum, dateOut);
}
void Lunar(long offset, MyDate & dateOut)
{
int i;
long temp;
for(i=baseYear; i<TotalYear && offset>0; i++)
{
temp = lYearDays(i);
offset -= temp;
}
if(offset<0)
{
offset += temp;
i--;
}
dateOut.year = i;
int leap = leapMonth(i); // 闰哪个月
dateOut.isLeap = false;
for(i=1; i<13 && offset>0; i++)
{
// 闰月
if(leap>0 && (i==leap+1) && !dateOut.isLeap)
{
--i;
dateOut.isLeap = true;
temp = leapDays(dateOut.year);
}
else
{
temp = monthDays(dateOut.year, i);
}
// 解除闰月
if(dateOut.isLeap && (i==leap+1))
dateOut.isLeap = false;
offset -= temp;
}
if(offset==0 && leap>0 && (i==leap+1))
{
if(dateOut.isLeap)
{
dateOut.isLeap = false;
}
else
{
dateOut.isLeap = true;
--i;
}
}
if(offset<0)
{
offset += temp;
--i;
}
dateOut.month = i;
dateOut.day = offset + 1;
}
//====================== 中文日期
string cDay(unsigned char day)
{
string s;
static char nStr1[][3] = {"日","一","二","三","四","五","六","七","八","九","十"};
static char nStr2[][3] = {"初","十","廿","卅"};
switch (day) {
case 10:
s = "初十"; break;
case 20:
s = "二十"; break;
break;
case 30:
s = "三十"; break;
break;
default :
s = nStr2[(int)floor(day/10)];
s+= nStr1[day%10];
}
return(s);
}