关于农历计算的源程序代码

来源:本站
导读:目前正在解读《关于农历计算的源程序代码》的相关信息,《关于农历计算的源程序代码》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《关于农历计算的源程序代码》的详细说明。
简介:近日对农历计算感兴趣,在网上找了一些源码看了看,发现一个广为流传的源码,好像是汉王的人所写。但是这个源码不但参数表太大,并且运算速度很慢,不适合于用到嵌入式产品中。后来看到一个不错的版本(可能为台湾人所写),于是对它的参数表进行了优化,得到了一个不错的程序,非常适合于嵌入式系统。

参数表所占存储空间为:30 + 4×支持年数

经在MSP430仿真测试,参数表占有154字节,代码占有622字节,执行一次的典型时间是1382个时钟周期。

// -----------------------------------------------------------------

// 农历计算:

// Copy From "西历农历转换程式 黄晓鸣 1995,7,25"

// Modify : Blove

// Date : 16:02 2005-12-1

// -----------------------------------------------------------------

typedef unsigned char INT8U;

typedef unsigned short INT16U;

typedef unsigned long INT32U;

typedef struct _SolarDate_Tag_

{

INT16U wYear;

INT8U chMonth;

INT8U chDate;

}sSolarDateTag;

typedef struct _LunarDate_Tag_

{

INT16U wYear;

INT8U chMonth;

INT8U chDate;

INT8U chKan;

INT8U chChi;

}sLunarDateTag;

// -------------------------------------------------------------------

// 农历计算参数位定义:

// 31-25 7 : ( BaseDays )到公历1月1日到农历正月初一的累积日数

// 24-20 5 : ( Intercalation)闰月月份. 0==此年没有闰月

// 19-13 7 : ( BaseKanChih )此年公历1月1日之干支序号减 1

// 12- 0 13 : ( MonthDays )此农历年每月之大小, 0==小月(29日), 1==大月(30日)

// -------------------------------------------------------------------

#define LPARA_MASK_BASE_DAYS 0xFE000000

#define LPARA_MASK_INTERCALATION 0x01F00000

#define LPARA_MASK_BASE_KANCHI 0x000FE000

#define LPARA_MASK_MONTH_DAYS 0x00001FFF

#define LPARA_SHIFT_BASE_DAYS 25

#define LPARA_SHIFT_INTERCALATION 20

#define LPARA_SHIFT_BASE_KANCHI 13

#define LPARA_SHIFT_MONTH_DAYS 0

#define LPara_GetBaseDays(i) ( (m_dwLunarParas[i]&LPARA_MASK_BASE_DAYS)>>LPARA_SHIFT_BASE_DAYS )

#define LPara_GetIntercalation(i) ( (m_dwLunarParas[i]&LPARA_MASK_INTERCALATION)>>LPARA_SHIFT_INTERCALATION )

#define LPara_GetBaseKanChi(i) ( (m_dwLunarParas[i]&LPARA_MASK_BASE_KANCHI)>>LPARA_SHIFT_BASE_KANCHI )

#define LPara_GetMonthDays(wYear,chMonth)

( (((m_dwLunarParas[wYear]&LPARA_MASK_MONTH_DAYS)>>LPARA_SHIFT_MONTH_DAYS)>>chMonth)&0x01 )

// -----------------------------------------------------------

// 农历计算参数表

// -----------------------------------------------------------

static const INT32U m_dwLunarParas[] =

{

0x2E47752B, 0x5400952B, 0x3E012A5B, 0x2A21D55A, 0x4E02956A, // 2005

0x38733B55, 0x6003DBA4, 0x4A047B49, 0x32553A93, 0x5805DA95,

0x4206752D, 0x2C470AAD, 0x50004AAD, 0x3C90F5AA, 0x620195D2, // 2015

0x4C022DA5, 0x3662FD4A, 0x5C038D4A, 0x46042C95, 0x3044D52E,

0x54059556, 0x3E062AB5, 0x2A26D5B2, 0x500776D2, 0x3860AEA5, // 2025

0x5E015725, 0x4801F64B, 0x32528C97, 0x56035CAB, 0x4203E55A,

0x2C348AD6 // 2031

};

#define FIRSTYEAR 2001 // 参数表中的第一年

#define YEAR_NUMS ( sizeof(m_dwLunarParas) / sizeof(INT32U) )

#define LASTYEAR ( FIRSTYEAR + YEAR_NUMS - 1 ) // 参数表中的最后一年

// -----------------------------------------------------------

// 公历年每月天数标记表

// 由高位到低位为12-1月:1表示31天,0表示30天,二月除外

// 月份: 12 11 10 9 8 7 6 5 4 3 2 1

// 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 28, 31

// 1 0 1 0 1 1 0 1 0 1 0 1

// -----------------------------------------------------------

static const INT16U m_wSolarMonthDaysFlag = 0x0AD5;

// -----------------------------------------------------------

// 公历年每月累积天数, 平年与闰年

// -----------------------------------------------------------

static const INT16U m_wSolarDays[14] =

{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365, 396 };

// -----------------------------------------------------------

// 求此公历年是否为闰年, 返回 0 为平年, 1 为闰年

// -----------------------------------------------------------

BOOL Lunar_IsIntercalation( INT16U wYear )

{

if ( wYear % 400 == 0 )

return 1;

else if ( wYear % 100 == 0 )

return 0;

else if ( wYear % 4 == 0 )

return 1;

else

return 0;

}

// -----------------------------------------------------------

// 农历计算

// -----------------------------------------------------------

int Lunar_Cal( sSolarDateTag *psSolarDate, sLunarDateTag *psLunarDate )

{

INT16U wSolarMonth, wDaySum, wSolarDaysSum, im, wTmp1, wTmp2, i, wKanChiSum;

BOOL bLeapFlag;

INT8U chMonthDays, chYearIndex;

// 输入参数的有效性检查

if ( psSolarDate->wYear<=FIRSTYEAR || psSolarDate->wYear>LASTYEAR )

return 1;

wSolarMonth = psSolarDate->chMonth - 1;

if ( wSolarMonth > 11 )

return 2;

bLeapFlag = Lunar_IsIntercalation( psSolarDate->wYear );

if ( wSolarMonth == 1)

// 二月

{

chMonthDays = bLeapFlag + 28;

}

else

// 其他月份

{

chMonthDays = 30 + ((m_wSolarMonthDaysFlag>>wSolarMonth)&0x01);

}

if ( psSolarDate->chDate<1 || psSolarDate->chDate>chMonthDays )

return 3;

chYearIndex = psSolarDate->wYear - FIRSTYEAR;

wSolarDaysSum = m_wSolarDays[wSolarMonth];

if ( wSolarMonth > 1 )

wSolarDaysSum += bLeapFlag;

wDaySum = wSolarDaysSum + psSolarDate->chDate;

wKanChiSum = wDaySum + LPara_GetBaseKanChi(chYearIndex);

psLunarDate->chKan = wKanChiSum % 10;

psLunarDate->chChi = wKanChiSum % 12;

if ( wDaySum <= LPara_GetBaseDays(chYearIndex) )

{

chYearIndex--;

psLunarDate->wYear = psSolarDate->wYear - 1;

bLeapFlag = Lunar_IsIntercalation( psLunarDate->wYear );

wSolarMonth += 12;

wSolarDaysSum = m_wSolarDays[wSolarMonth];

if ( wSolarMonth > 1 )

wSolarDaysSum += bLeapFlag;

wDaySum = wSolarDaysSum + psSolarDate->chDate;

}

else

{

psLunarDate->wYear = psSolarDate->wYear;

}

wTmp1 = LPara_GetBaseDays(chYearIndex);

for ( i=0; i<13; i++ )

{

wTmp2 = wTmp1 + LPara_GetMonthDays( chYearIndex, i) + 29;

if ( wDaySum <= wTmp2 )

break;

wTmp1 = wTmp2;

}

psLunarDate->chMonth = i + 1;

psLunarDate->chDate = wDaySum - wTmp1;

im = LPara_GetIntercalation(chYearIndex);

if ( im != 0 && psLunarDate->chMonth > im)

psLunarDate->chMonth--;

if ( psLunarDate->chMonth > 12)

psLunarDate->chMonth -= 12;

return 0;

}

提醒:《关于农历计算的源程序代码》最后刷新时间 2024-03-14 01:02:40,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《关于农历计算的源程序代码》该内容的真实性请自行鉴别。