重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
void solar()
创新互联公司致力于互联网品牌建设与网络营销,包括成都网站设计、成都网站建设、外贸网站建设、SEO优化、网络推广、整站优化营销策划推广、电子商务、移动互联网营销等。创新互联公司为不同类型的客户提供良好的互联网应用定制及解决方案,创新互联公司核心团队十载专注互联网开发,积累了丰富的网站经验,为广大企业客户提供一站式企业网站建设服务,在网站建设行业内树立了良好口碑。
{
int nyear,nmonth,nday, gyear,gmonth,gday;
long int Ndata,c;
int wei=11,mt,nwhatday=0,runday,runmonth,nm,i,a,whatChunJie,ChunJieYear,zgwhatday,gyday,ms,cz,runt;
char YNrun;
system("cls");
cout"输入需查询的农历年月日(例:2005 05 25)"endl;
cinnyear;
cinnmonth;
cinnday;
if(judge(gyear,gmonth,gday)==0){
cout"error date"endl;
return;
}
runday=(NongliData[nyear-1899]/0x1000)%0x10; //取出判断闰月天数的值
runmonth=(NongliData[nyear-1899]/0x100)%0x10; //取出判断是否闰月闰几月的值
if(runday==1) runt=30;
else runt=29;
if(YNrun=='y')
nm=nmonth; //计算该月前面有几个月
else nm=nmonth-1;//计算在该农历年的第几天
Ndata=NongliData[nyear-1899];
c=Ndata/0x10000;
wei=11;
while(wei=0 nm0){
i=cwei~(~01);
if(i==1) mt=30;
else mt=29;
nwhatday=nwhatday+mt;
nm--;
wei--;
}
if(nmonthrunmonth runmonth!=0){
nwhatday=nwhatday+runt;
}
nwhatday=nwhatday+nday;//计算该年春节在公历年的第几天
ChunJieYear=NongliData[nyear-1899];
a=ChunJieYear%0x100;
whatChunJie=gPastday[a/100]+a%100;
if((ChunJieYear%4==0 ChunJieYear%100!=0 || ChunJieYear%400==0) (a/1002)) whatChunJie++;
zgwhatday=nwhatday+whatChunJie-1;//计算该公历年一年总天数
if(nyear%4==0 nyear%100!=0 || nyear%400==0){
gyday=366;
months[2]=29;
}
else{
gyday=365;
months[2]=28;
}
//换算出公历年份
if(zgwhatdaygyday){
gyear=nyear+1;
zgwhatday=zgwhatday-gyday;
}
else gyear=nyear;
//换算出公历月份
ms=1;
cz=zgwhatday;
gmonth=0;
while(ms13){
cz=cz-months[ms];
if(cz=0) {
gmonth++;
gday=cz+months[ms];
break;
}
gmonth++;
ms++;
}
coutendl"由农历转换成公历查询结果如下"endlendl;
cout"农历:" nyear"年"nmonth"月"nday"日"endl;
coutendl"公历: (公元)"gyear"年"gmonth"月"gday"日"endl;
getch();
}
Dim WeekName(7), MonthAdd(11), NongliData(99), TianGan(9), DiZhi(11), ShuXiang(11), DayName(30), MonName(12)
Dim curTime, curYear, curMonth, curDay, curWeekday
Dim GongliStr, WeekdayStr, NongliStr, NongliDayStr
Dim i, m, n, k, isEnd, bit, TheDate
Private Sub Form_Load()
'获取当前系统时间
curTime = Now()
'星期名
WeekName(0) = " * "
WeekName(1) = "星期日"
WeekName(2) = "星期一"
WeekName(3) = "星期二"
WeekName(4) = "星期三"
WeekName(5) = "星期四"
WeekName(6) = "星期五"
WeekName(7) = "星期六"
'天干名称
TianGan(0) = "甲"
TianGan(1) = "乙"
TianGan(2) = "丙"
TianGan(3) = "丁"
TianGan(4) = "戊"
TianGan(5) = "己"
TianGan(6) = "庚"
TianGan(7) = "辛"
TianGan(8) = "壬"
TianGan(9) = "癸"
'地支名称
DiZhi(0) = "子"
DiZhi(1) = "丑"
DiZhi(2) = "寅"
DiZhi(3) = "卯"
DiZhi(4) = "辰"
DiZhi(5) = "巳"
DiZhi(6) = "午"
DiZhi(7) = "未"
DiZhi(8) = "申"
DiZhi(9) = "酉"
DiZhi(10) = "戌"
DiZhi(11) = "亥"
'属相名称
ShuXiang(0) = "鼠"
ShuXiang(1) = "牛"
ShuXiang(2) = "虎"
ShuXiang(3) = "兔"
ShuXiang(4) = "龙"
ShuXiang(5) = "蛇"
ShuXiang(6) = "马"
ShuXiang(7) = "羊"
ShuXiang(8) = "猴" ;
ShuXiang(9) = "鸡"
ShuXiang(10) = "狗"
ShuXiang(11) = "猪"
'农历日期名
DayName(0) = "*"
DayName(1) = "初一"
DayName(2) = "初二"
DayName(3) = "初三"
DayName(4) = "初四"
DayName(5) = "初五"
DayName(6) = "初六"
DayName(7) = "初七"
DayName(8) = "初八"
DayName(9) = "初九"
DayName(10) = "初十"
DayName(11) = "十?quot;"
DayName(12) = "十二"
DayName(13) = "十三"
DayName(14) = "十四"
DayName(15) = "十五"
DayName(16) = "十六"
DayName(17) = "十七"
DayName(18) = "十八"
DayName(19) = "十九"
DayName(20) = "二十"
DayName(21) = "廿一"
DayName(22) = "廿二"
DayName(23) = "廿三"
DayName(24) = "廿四"
DayName(25) = "廿五"
DayName(26) = "廿六"
DayName(27) = "廿七"
DayName(28) = "廿八"
DayName(29) = "廿九"
DayName(30) = "三十"
'农历月份名
MonName(0) = "*"
MonName(1) = "正"
MonName(2) = "二"
MonName(3) = "三"
MonName(4) = "四"
MonName(5) = "五"
MonName(6) = "六"
MonName(7) = "七"
MonName(8) = "八"
MonName(9) = "九"
MonName(10) = "十"
MonName(11) = "十一"
MonName(12) = "腊"
'公历每月前面的天数
MonthAdd(0) = 0
MonthAdd(1) = 31
MonthAdd(2) = 59
MonthAdd(3) = 90
MonthAdd(4) = 120
MonthAdd(5) = 151
MonthAdd(6) = 181
MonthAdd(7) = 212
MonthAdd(8) = 243
MonthAdd(9) = 273
MonthAdd(10) = 304
MonthAdd(11) = 334
'农历数据
NongliData(0) = 2635
NongliData(1) = 333387
NongliData(2) = 1701
NongliData(3) = 1748
NongliData(4) = 267701
NongliData(5) = 694
NongliData(6) = 2391
NongliData(7) = 133423
NongliData(8) = 1175
NongliData(9) = 396438
NongliData(10) = 3402
NongliData(11) = 3749
NongliData(12) = 331177
NongliData(13) = 1453
NongliData(14) = 694
NongliData(15) = 201326
NongliData(16) = 2350
NongliData(17) = 465197
NongliData(18) = 3221
NongliData(19) = 3402
NongliData(20) = 400202
NongliData(21) = 2901
NongliData(22) = 1386
NongliData(23) = 267611
NongliData(24) = 605
NongliData(25) = 2349
NongliData(26) = 137515
NongliData(27) = 2709
NongliData(28) = 464533
NongliData(29) = 1738
NongliData(30) = 2901
NongliData(31) = 330421
NongliData(32) = 1242
NongliData(33) = 2651
NongliData(34) = 199255
NongliData(35) = 1323
NongliData(36) = 529706
NongliData(37) = 3733
NongliData(38) = 1706
NongliData(39) = 398762
NongliData(40) = 2741
NongliData(41) = 1206
NongliData(42) = 267438
NongliData(43) = 2647
NongliData(44) = 1318
NongliData(45) = 204070
NongliData(46) = 3477
NongliData(47) = 461653
NongliData(48) = 1386
NongliData(49) = 2413
NongliData(50) = 330077
NongliData(51) = 1197
NongliData(52) = 2637
NongliData(53) = 268877
NongliData(54) = 3365
NongliData(55) = 531109
NongliData(56) = 2900
NongliData(57) = 2922
NongliData(58) = 398042
NongliData(59) = 2395
NongliData(60) = 1179
NongliData(61) = 267415
NongliData(62) = 2635
NongliData(63) = 661067
NongliData(64) = 1701
NongliData(65) = 1748
NongliData(66) = 398772
NongliData(67) = 2742
NongliData(68) = 2391
NongliData(69) = 330031
NongliData(70) = 1175
NongliData(71) = 1611
NongliData(72) = 200010
NongliData(73) = 3749
NongliData(74) = 527717
NongliData(75) = 1452
NongliData(76) = 2742
NongliData(77) = 332397
NongliData(78) = 2350
NongliData(79) = 3222
NongliData(80) = 268949
NongliData(81) = 3402
NongliData(82) = 3493
NongliData(83) = 133973
NongliData(84) = 1386
NongliData(85) = 464219
NongliData(86) = 605
NongliData(87) = 2349
NongliData(88) = 334123
NongliData(89) = 2709
NongliData(90) = 2890
NongliData(91) = 267946
NongliData(92) = 2773
NongliData(93) = 592565
NongliData(94) = 1210
NongliData(95) = 2651
NongliData(96) = 395863
NongliData(97) = 1323
NongliData(98) = 2707
NongliData(99) = 265877
'生成当前公历年、月、日 == GongliStr
curYear = Year(curTime)
curMonth = Month(curTime)
curDay = Day(curTime)
GongliStr = curYear "年"
If (curMonth 10) Then
GongliStr = GongliStr "0" curMonth "月"
Else
GongliStr = GongliStr curMonth "月"
End If
If (curDay 10) Then
GongliStr = GongliStr "0" curDay "日"
Else
GongliStr = GongliStr curDay "日"
End If
'生成当前公历星期 == WeekdayStr
curWeekday = Weekday(curTime)
WeekdayStr = WeekName(curWeekday)
'计算到初始时间1921年2月8日的天数:1921-2-8(正月初一)
TheDate = (curYear - 1921) * 365 + Int((curYear - 1921) / 4) + curDay + MonthAdd(curMonth - 1) - 38
If ((curYear Mod 4) = 0 And curMonth 2) Then
TheDate = TheDate + 1
End If
'计算农历天干、地支、月、日
isEnd = 0
m = 0
Do
If (NongliData(m) 4095) Then
k = 11
Else
k = 12
End If
n = k
Do
If (n 0) Then
Exit Do
End If
'获取NongliData(m)的第n个二进制位的值
bit = NongliData(m)
For i = 1 To n Step 1
bit = Int(bit / 2)
Next
bit = bit Mod 2
If (TheDate = 29 + bit) Then
isEnd = 1
Exit Do
End If
TheDate = TheDate - 29 - bit
n = n - 1
Loop
If (isEnd = 1) Then
Exit Do
End If
m = m + 1
Loop
curYear = 1921 + m
curMonth = k - n + 1
curDay = TheDate
If (k = 12) Then
If (curMonth = (Int(NongliData(m) / 65536) + 1)) Then
curMonth = 1 - curMonth
ElseIf (curMonth (Int(NongliData(m) / 65536) + 1)) Then
curMonth = curMonth - 1
End If
End If
'生成农历天干、地支、属相 == NongliStr
NongliStr = "农历" TianGan(((curYear - 4) Mod 60) Mod 10) DiZhi(((curYear - 4) Mod 60) Mod 12) "年"
NongliStr = NongliStr "(" ShuXiang(((curYear - 4) Mod 60) Mod 12) ")"
'生成农历月、日 == NongliDayStr
If (curMonth 1) Then
NongliDayStr = "闰" MonName(-1 * curMonth)
Else
NongliDayStr = MonName(curMonth)
End If
NongliDayStr = NongliDayStr "月"
NongliDayStr = NongliDayStr DayName(curDay)
MsgBox NongliStr NongliDayStr
End Sub
excess elements in char array initializer 的意思是:在char数组初始化时,设置了多余的元素。如:
const char ChDay[] = { //这里定义的是一个一维字符数组,并进行初始化,一维数组的元素只能是单个的字符,而下面的数据却是字符串,所以,在编译时会报错误。
"","初一","初二","初三","初四","初五",
"初六","初七","初八","初九","初十",
"十一","十二","十三","十四","十五",
"十六","十七","十八","十九","二十",
"廿一","廿二","廿三","廿四","廿五",
"廿六","廿七","廿八","廿九","三十"
};
正确的代码应该为:
const char * ChDay[] = { //定义一个字符串数组(字符指针数组),其元素为字符串( 字符指针 )
"","初一","初二","初三","初四","初五",
"初六","初七","初八","初九","初十",
"十一","十二","十三","十四","十五",
"十六","十七","十八","十九","二十",
"廿一","廿二","廿三","廿四","廿五",
"廿六","廿七","廿八","廿九","三十"
};
或,定义成二维数组,因一个汉字最多占三个字节,初始化数据中,最长的只有两个汉字,所以,可以进行如下定义:
const char ChDay[][7] = { //列宽最大为7(两个汉字加一个字符串结束符)
"","初一","初二","初三","初四","初五",
"初六","初七","初八","初九","初十",
"十一","十二","十三","十四","十五",
"十六","十七","十八","十九","二十",
"廿一","廿二","廿三","廿四","廿五",
"廿六","廿七","廿八","廿九","三十"
};
一、 原理篇
1. 公历转换农历的算法
公历(Gregorian Calendar)与农历(Chinese Lunar Calendar)的转换关系不是一个简单的公式就可以完成,其中的转换比较复杂,原因是农历的制定相当复杂,是根据天文观测进行指定的。
比较常用并且比较简单的公历转换农历算法就是查表方法。首先要保存公历农历的转换信息:以任何一年作为起点,把从这一年起若干年的农历信息保存起来(在我的C++类中,是从1900年作为起点的。选择一个起始点的思想十分重要,在下面的干支纪法和二十四节气中也体现到了)。回想一下,我们平时是怎样来转换公历农历的呢?是查阅历书,历书中有每一天的公历农历,直接一查就可以了。那么我们可不可以也这样做呢?当然可以,但是这样做要收录每一天的信息,工作量就会很大,所以我们要简化这些信息。如何简化呢?
要保存一年的信息,其实只要两个信息就可以了:(1)农历每个月的大小;(2)今年是否有闰月,闰几月以及闰月的大小。用一个整数来保存这些信息就足够了。具体的方法是:用一位来表示一个月的大小,大月记为1,小月记为0,这样就用掉了12位,再用低四位来表示闰月的月份,没有闰月记为0。比如说,2000年的信息数据是0x0c960,转化成二进制就是1100100101100000,表示的含义是1、2、5、8、10、11月大,其余月小,低四位为0说明没有闰月。2001年的农历信息数据是0x0d954,其中的4表示该年闰4月,月份大小信息就是0x0d95,具体的就是1、2、4、5、8、10、12月大,其余月小。这样就可以用一个数组来保存这些信息。在我的C++类中是用m_lunarInfo这个数组来保存这些信息的。
下面就是公历转换成农历的具体算法:
(1) 计算所求时间到起始年正月初一的天数。
(2) 从起始年份开始,减去每一月的天数,一直到剩余天数没有下一个月多为止。此时,m_lunarInfo的下标到了多少,就是减去了多少年,用起始年份加上这个下标就可以得到农历年份,然后看减去了几个月。如果本年不闰月或者闰月还在后面,就可以直接得到农历月份,如果在闰月月份数后面一个月,则这个月就是闰月。剩余的天数就是农历日。(具体实现时有所改进。)
2. 利于泰勒公式巧算星期
在应用数学中有一个计算某一天是星期几的公式,这就是泰勒公式。公式如下:w = [c÷4] - 2c + y + [y÷4] + [26(m+1)÷10] + d - 1,其中w就是所求日期的星期数。如果求得的数大于(小于)7,就减去(加上)7的倍数,直到余数小于7为止。式子中c是指公元年份的前两位数字,y是后两位数字,m是月数,d是日数。方括弧[]表示对于括号中的数字取整。还有一个特别要注意的地方:所求的月份如果是1月或2月,则应视为上一年的13月或14月,也就是公式中m的取值范围是从3到14而不是从1到12。
3. 干支纪法
天干有十个,就是甲、乙、丙、丁、戊、己、庚、辛、壬、癸,地支有十二个,依次是子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥。古人把它们按照一定的顺序而不重复地搭配起来,从甲子到癸亥共六十对,叫做六十甲子。我国古人用这六十对干支来表示年、月、日、时的序号,周而复始,不断循环,这就是干支纪法。
0甲子
1乙丑
2丙寅
3丁卯
4戊辰
5己已
6庚午
7辛未
8壬申
9癸酉10甲戌
11乙亥
12丙子
13丁丑
14戊寅
15己卯
16庚辰
17辛已
18壬午
19癸未20甲申
21乙酉
22丙戌
23丁亥
24戊子
25己丑
26庚寅
27辛卯
28壬辰
29癸已30甲午
31乙未
32丙申
33丁酉
34戊戌
35已亥
36庚子
37辛丑
38壬寅
39癸卯40甲辰
41乙已
42丙午
43丁未
44戊申
45己酉
46庚戌
47辛亥
48壬子
49癸丑50甲寅
51乙卯
52丙辰
53丁已
54戊午
55己未
56庚申
57辛酉
58壬戌
59癸亥得到年、月、日的干支表示原理是相同的,即所求的年、月、日到起始年、月、日所经历的年数、月数、天数,加上起始年、月、日干支表示在上表中的序号,与10取模得到天干的序号,与12取模得到地支的序号。以年为例,1900年立春后为庚子年,查上表可知,庚子年为六十甲子的第36位,所以所求年份m_year到1900年的年数为m_year-1900+36-1(如果月份m_month小于等于2月)或m_year-1900+36(如果月份m_month大于2月)。同理,可以得到月、日的干支表示。最后,还要依据节气(立春)调整二月份的干支纪年;依据每月的第一个节气的日期调整月的干支表示,具体情况源程序中有详细的说明。
古人根据太阳升起的时间, 将一昼夜区分为十二个时辰,用十二地支为代号。如果用m_hour表示公历现在的小时数(二十四表示法),则(m_hour+1)/2就得到时间的地支表示(其实是地支的序号)。
4. 二十四节气
节气就实质而言是属于阳历范畴,从天文学意义来讲,二十四节气是根据地球绕太阳运行的轨道(黄道)360度,以春分点为0点,分为二十四等分点,两等分点相隔15度,每个等分点设有专名,含有气候变化、物候特点、农作物生长情况等意义。二十四节气即立春、雨水、惊蜇、春分、清明、谷雨、立夏、小满、芒种、夏至、小暑、大暑、立秋、处暑、白露、秋分、寒露、霜降、立冬、小雪、大雪、冬至、小寒、大寒。以上依次顺属,逢单的均为"节气",通常简称为"节",逢双的则为"中气",简称为"气",合称为"节气"。现在一般统称为二十四节气。
自古节气的推算是由一年平分24等分所得的平节气。旧历用平气法推算二十四气,此法将一回归年均分成二十四等分,从冬至开始等间隔地依次相间安排各个节气及中气,而各气之间太阳所运行的度数因此并不相等。新历推算则用定气法,此法将黄道上的周天度数等分成二十四份,太阳移至某一分点时,即定为某一节气的日期,由于太阳的视运动迟速不均,因此各节气间相隔的时间亦不等。但不论新历或旧历,均取冬至为二十四气之首,故在春、秋分时彼此的差别最大。为何中国传统历家早知推算定气,却又习用平气注历?此主要或由于平气易于计算所致,因在此法之下,各节气与节气间或中气与中气间相隔固定为三十日五时辰又二刻。
本C++类中实现二十四节气的计算,使用的是平节气的简单算法。用数组sTermInfo记录从小寒开始的各个节气相对于小寒所经历的分钟数,并用int sTerm(int y, int n)函数得到某年y的第n个节气为所在月的第几日(n从0小寒起算)。由于没有考虑岁差与章动,所以精确度不是很高。