关于公历农历互相转换的一个小程序的问题~~!
本程序中,公历转农历是网上找的,没有问题~~~农历转公历时,如果本年不是闰年的话,也没有问题~~~~
但是,当那一年是闰年时,农历转公历算出来就不对!
但是我也不知道到底该咋改~~~
请大家帮我看看~~~多谢了~~~
程序代码:
#include "stdio.h" static const unsigned short wMonthAdd[13]={0,31,59,90,120,151,181,212,243,273,304,334,365}; static const unsigned short wMonthAddy[13]={0,31,60,91,121,152,182,213,244,274,305,335,366}; static const unsigned long wNongliData[99]={/*农历数据*/ 0x41A95,0x00D4A,0x00DA5,0x20B55,0x0056A,0x7155B,0x0025D,0x0092D,0x5192B,0x00A95, 0x00B4A,0x416AA,0x00AD5,0x90AB5,0x004BA,0x00A5B,0x60A57,0x0052B,0x00A93,0x40E95, 0x006AA,0x00AD5,0x209B5,0x004B6,0x612AE,0x00A4E,0x00D26,0x51D26,0x00D53,0x005AA, 0x30D6A,0x0096D,0xB095D,0x004AD,0x00A4D,0x61A4B,0x00D25,0x00D52,0x51B54,0x00B5A, 0x0056D,0x2095B,0x0049B,0x71497,0x00A4B,0x00AA5,0x516A5,0x006D2,0x00ADA,0x30AB6, 0x00937,0x8092F,0x00497,0x0064B,0x60D4A,0x00EA5,0x006B2,0x4156C,0x00AAE,0x0092E, 0x3192E,0x00C96,0x71A95,0x00D4A,0x00DA5,0x50B55,0x0056A,0x00A6D,0x40A5D,0x0052D, 0x8152B,0x00A95,0x00B4A,0x616AA,0x00AD5,0x0055A,0x414BA,0x00A5B,0x0052B,0x31527, 0x00693,0x70E53,0x006AA,0x00AD5,0x509B5,0x004B6,0x00A57,0x40A4E,0x00D26,0x81D26, 0x00D52,0x00DAA,0x60D6A,0x0056D,0x004AE,0x4149D,0x00A4D,0x00D15,0x21B25}; typedef struct { int day; int month; int year; } CLK_DATE_T; CLK_DATE_T GetOldDay(CLK_DATE_T pSt) /*公历转换成农历*/ { static int wCurYear,wCurMonth,wCurDay; static int nIsEnd,m,k,n,i,nBit; static long nTheDate; CLK_DATE_T OldDay; int y; wCurYear = pSt.year; wCurMonth = pSt.month; wCurDay = pSt.day; y=wCurYear - 2001; /*计算该天到2001年正月初一有多少天*/ nTheDate =(y<<8)+(y<<6)+(y<<5)+(y<<3)+(y<<2)+y + (y>>2) + wCurDay + wMonthAdd[wCurMonth - 1] - 23; if((!(wCurYear & 0x0003)) && (wCurMonth > 2)) nTheDate++; nIsEnd = 0; m = 0; while(nIsEnd != 1){ if(wNongliData[m] < 4095) k = 11; else k = 12; n = k; while(n>=0){ nBit = wNongliData[m]; for(i=1;i<n+1;i++) nBit = (nBit>>1); nBit = (nBit & 0x0001); if (nTheDate <= (29 + nBit)) { nIsEnd = 1; break; } nTheDate = nTheDate - 29 - nBit; n--; } if(nIsEnd) break; m++; } wCurYear = 2001 + m; wCurMonth = k - n + 1; wCurDay = nTheDate; y=wNongliData[m] / 65536 + 1; /*计算该年闰月的月份+1*/ if (k == 12){ if (wCurMonth == y) wCurMonth = 1 - wCurMonth; else if (wCurMonth > y) wCurMonth = wCurMonth - 1; } OldDay.year =wCurYear; OldDay.month=wCurMonth; OldDay.day =wCurDay; return OldDay; } CLK_DATE_T GetNewDay(CLK_DATE_T pSt) /*农历转换成公历*/ { CLK_DATE_T Begin,NewDay; CLK_DATE_T ODay; int wCurMonth,wCurDay,nDate,monthdays[13]; int cc,k,i,yy,j,nBit,monthP,monthN,yyy,allday; long nTheDate; cc=pSt.year-2001; nDate=0; nTheDate=0; /************************************************************* ********* 我估计这里也有问题 **************** *************************************************************/ Begin.year=pSt.year; for(i=1;i<3;i++) /*计算该年正月初一到元旦的天数*/ { for(j=1;j<32;j++) { Begin.month=i; Begin.day=j; ODay = GetOldDay(Begin); if(ODay.month==1 && ODay.day==1) break; nDate++; } } /************************************************************* *************************************************************/ if(wNongliData[cc] < 4095) k = 11; else k = 12; j=k; while(j>=0) /*计算该年农历每月多少天*/ { nBit = wNongliData[cc]; for(i=1;i<j+1;i++) nBit = (nBit>>1); nBit = (nBit & 0x0001); monthdays[k-j]=29+nBit; j--; } wCurMonth = pSt.month; wCurDay = pSt.day; /************************************************************* ********* 我估计问题就在下面 **************** *************************************************************/ yy=wNongliData[cc] / 65536; if (k==12 && yy<wCurMonth) wCurMonth++; if (wCurMonth<0) wCurMonth=-1*wCurMonth+1; for(i=0;i<wCurMonth-1;i++) nTheDate+=monthdays[i]; /************************************************************* ********* 我估计问题就在上面 **************** *************************************************************/ nTheDate+=wCurDay+nDate; NewDay.year=pSt.year; yyy=(!(NewDay.year%4) && (NewDay.year%100)) || !(NewDay.year%400); if(yyy) allday=366; else allday=365; if(nTheDate>allday) { nTheDate-=allday; NewDay.year++; } for(i=1;i<13;i++) { if(yyy) { monthP = wMonthAddy[i-1]; monthN = wMonthAddy[i]; } else { monthP = wMonthAdd[i-1]; monthN = wMonthAdd[i]; } if(monthP<nTheDate && nTheDate<=monthN) { NewDay.month = i; NewDay.day = nTheDate-monthP; } } return NewDay; } void main() { CLK_DATE_T aaa,bbb; int i,j,k; printf("1:lunar to solar.\n2:solar to lunar.\n"); printf("Please Input Your Choose:"); scanf("%d",&k); printf("Input the date:\n"); scanf("%d %d %d",&aaa.year,&aaa.month,&aaa.day); switch(k) { case 2: bbb=GetOldDay(aaa);break; case 1: bbb=GetNewDay(aaa); } printf("%d %d %d\n",bbb.year,bbb.month,bbb.day); printf("***********************************************\n"); }
其中农历数据的含义如下:
程序代码:
每个数转成2进制,一共32位 低12/13位表示每个月的大小,高16位表示闰哪个月 比如2006年表中10进制464219,16进制0x7155b,二进制 0000 0000 0000 0111 0001 0101 0101 1011 |--------闰7月--------------|---1 2345 67*8 9---| (*闰月,这里闰7月) 比如2007年表中10进制605,16进制0x25D,二进制 0000 0000 0000 0000 0000 0010 0101 1011 |--------无闰月--------------|---- 1234 5678 9---|
[[it] 本帖最后由 ilylia 于 2008-3-3 12:11 编辑 [/it]]
change.rar
(2.22 KB)