/***************************************************************************************************
哈尔滨市闲人无事发呆有限公司
鼓 捣 所
鼓捣总部
Q Q:958415720
Email:[email protected]
说 明: 经过几天日子的鼓捣,弄出来了这个万年历阳历转换阴历的转换代码,由于网上很多的代码写的
很乱,起初也不懂关于一些天文的知识,看的迷糊,让我很是无奈就想还是自己写吧偶尔在网上
找到了一个PDF文档叫《公历与农历日期的转换》 让我明白了许多 从而就开始花了一天的时间写
出来了。希望想要做万年历的人拿去用 这是在VC++ 6.0 平台的 直接就可以移植到51,AVR,STM32等等上
的。
作 者: 崔殿川
***************************************************************************************************/
#include
#include "test.h" //年份数据表包含头文件
#include "mytype.h"//数据类型宏定义包含头文件(UINT8 UINT16 UINT32....)
UINT8 LunarYearNum=0,LunarMonNum=0,LunarDayNum=0;//转化回来的阴历数值就存在相应的变量中(全局的)
UINT16 DayDataBase[12]={0,32,59,90,120,151,181,212,243,273,304,334};
/**********************************************************************************
函 数 名:获取农历的大小月份
入口参数:Mon: 当年的月份数(农历的0~13) YearOffsetAdd: 年份数据表里的偏移地址 返 回 值:0:大月份(30天) 1:小月份(29天)
说 明:大小月的获取主要是从年份数据表里三个字节的高13位当中获取 如果对应为是1则
是大月30天,小月29天
************************************************************************************/
UINT8 GetLunBig_LitMon(UINT8 Mon,UINT16 YearOffsetAdd)
{
UINT8 i=0;
(YearDataBase[YearOffsetAdd][(Mon>(Mon-5))):(0x08>>(Mon-1))))? (i=1):(i=0);
return (i);
}
/**********************************************************************************
函 数 名:公历到农历的转换
入口参数:对应着公历(阳历)的年(0~99),月(0~12),日(0~31)
返 回 值:0
***********************************************************************************/
UINT8 Solar2Luner(UINT8 SolarYearNum,UINT8 SolarMonNum,UINT8 SolarDayNum) {
UINT8 LeapMonVal=0; //农历闰月天数值变量
UINT8 NewYearToYuanDan_Mon=0,NewYearToYuanDan_Day=0; //定义春节所在的月份数(不是1月就是2月)
UINT8 YearFlag=0,MonPointer=0; //农历年的缓存标志和月份的偏移量
UINT8 temp=0; //春节距离元旦的天数
UINT16 TarGetDayT0YuanDan=0,YearOffsetAdd=0; //目标日期到元旦天数和年数据表的偏移地址
YearOffsetAdd=(SolarYearNum-1); //获取数据表地址
NewYearToYuanDan_Mon=(YearDataBase[YearOffsetAdd][2]&0x60)>>5; //计算春节所在的月份(不是1月就是2月)
NewYearToYuanDan_Day=(YearDataBase[YearOffsetAdd][2]&0x1f); //从年数据表里获取最后一个字节的第五位只要是计算春节到元旦的日期(Day的天数值)
(NewYearToYuanDan_Mon==1)?(temp=NewYearToYuanDan_Day-1):(temp=NewYearToYuanDan_Day+31-1); //temp这才是通过上面得到的春节所在的月份之后最终计算出来春节距离元旦的总天数
TarGetDayT0YuanDan=DayDataBase[SolarMonNum-1]+SolarDayNum-1;//得到目标日期到元旦天数
if ((SolarMonNum>2) && !(SolarYearNum%4))//如果是闰年则加目标天数1
TarGetDayT0YuanDan+=1;
//==============================转化分两块(以春节作为转换中心) 目标日期距离春节前或者春节后=========================//
if(TarGetDayT0YuanDan>=temp) //目标日期在春节之后
{
TarGetDayT0YuanDan-=temp; //求2个天数的差值
SolarMonNum=1;
MonPointer=1; //这时目标值一定是在一月
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29); //判断闰月的月份是大月还是小月
while(TarGetDayT0YuanDan>=LeapMonVal) //目标日期大于等于闰月(大小月)天数 {
TarGetDayT0YuanDan-=LeapMonVal;
MonPointer+=1;
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
if(SolarMonNum==YearDataBase[YearOffsetAdd][0]>>4) //获取第一字节的高四位 (闰月月份的获取)
{
YearFlag=~YearFlag;
if(!YearFlag)
SolarMonNum+=1;
}
else
SolarMonNum+=1;
}
SolarDayNum=TarGetDayT0YuanDan+1; //最后农历日期天数的获取
}
else //目标日期在春节前
{
temp-=TarGetDayT0YuanDan;
SolarYearNum-=1;
YearOffsetAdd-=3;
SolarMonNum=12;
(YearDataBase[YearOffsetAdd][0]>>4)?(MonPointer=13):(MonPointer=12);
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
while(temp>LeapMonVal)
{
temp-=LeapMonVal;
MonPointer-=1;
if(!YearFlag)
SolarMonNum-=1;
if(SolarMonNum==NewYearToYuanDan_Day)
YearFlag=~YearFlag;
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
}
SolarDayNum=LeapMonVal-temp+1; //最后农历日期天数的获取
}
LunarYearNum=SolarYearNum;
LunarMonNum =SolarMonNum;
LunarDayNum =SolarDayNum;
return (0);
}
/***********************************************************************************************
-函 数 名:星期修正
-入口参数:对应着公历(阳历)的年(0~99),月(0~12),日(0~31)
-返 回 值:当天的星期
说 明:
公历日是非常有规律的所以公历日所对应的星期天可以通过计算直接得到理论上公元0 年1 月1 日为星期日
只要求得公历日离公元0 年1 月1 日的日子数除7 后的余数就是星期天为了简化计算采用月校正法根据公历
的年月日可直接计算出星期天其算法是日期年份所过闰年数月校正数之和除7 的余数就是星期天但如果是在
闰年又不到3 月份上述之和要减一天再除7 其1~12月的校正数据为6,2,2,5,0,3,5,1,4,6,2,4在本程序中采
用1 个字节表示年份闰年数也只计算1900 年以后的闰年数所以实际校正数据也和上述数据不同
详见PDF《公历与农历日期的转换》文档
************************************************************************************************/
#ifdef WEEKREVISE
UINT8 WeekDataBase[12]={6,2,2,5,0,3,5,1,4,6,2,4}; //月修正数据表
UINT8 WeekRevise(UINT8 SolarYearNum,UINT8 SolarMonNum,UINT8 SolarDayNum) {
return (!(SolarYearNum%4) && SolarMonNum
}
#endif
int main()
{
Solar2Luner(13,3,23);
printf("%d %d %d \n",LunarYearNum,LunarMonNum,LunarDayNum);
return 0;
}
//***************************************************************************** 下面是数据类型宏定义.h文件
******************************************************************************* #ifndef _MYTYPE_H_
#define _MYTYPE_H_
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
#define INT8 char
#define INT16 int
#define INT32 long
#endif
//***************************************************************************** 下面是年份数据表h文件
因为这里是在VC平台上的 就没有把数据表定义在ROM里 如果大家想要移植到51或者AVR等等处理器上 请自己更改、、、
******************************************************************************* #define WEEKREVISE //如果不使用星期修正注释掉这里
unsigned char YearDataBase[99][3]=
{
{0x4d,0x4A,0xB8}, //2001
{0x0d,0x4A,0x4C}, //2002
{0x25,0xAA,0xB6}, //2004 {0x05,0x6A,0x49}, //2005 {0x7A,0xAd,0xBd}, //2006 {0x02,0x5d,0x52}, //2007 {0x09,0x2d,0x47}, //2008 {0x5C,0x95,0xBA}, //2009 {0x0A,0x95,0x4e}, //2010 {0x0B,0x4A,0x43}, //2011 {0x4B,0x55,0x37}, //2012 {0x0A,0xd5,0x4A}, //2013 {0x95,0x5A,0xBf}, //2014 {0x04,0xBA,0x53}, //2015 {0x0A,0x5B,0x48}, //2016 {0x65,0x2B,0xBC}, //2017 {0x05,0x2B,0x50}, //2018 {0x0A,0x93,0x45}, //2019 {0x47,0x4A,0xB9}, //2020 {0x06,0xAA,0x4C}, //2021 {0x0A,0xd5,0x41}, //2022 {0x24,0xdA,0xB6}, //2023 {0x04,0xB6,0x4A}, //2024 {0x69,0x57,0x3d}, //2025 {0x0A,0x4e,0x51}, //2026 {0x0d,0x26,0x46}, //2027 {0x5e,0x93,0x3A}, //2028 {0x0d,0x53,0x4d}, //2029 {0x05,0xAA,0x43}, //2030 {0x36,0xB5,0x37}, //2031 {0x09,0x6d,0x4B}, //2032 {0xB4,0xAe,0xBf}, //2033 {0x04,0xAd,0x53}, //2034 {0x0A,0x4d,0x48}, //2035 {0x6d,0x25,0xBC}, //2036 {0x0d,0x25,0x4f}, //2037 {0x0d,0x52,0x44}, //2038 {0x5d,0xAA,0x38}, //2039 {0x0B,0x5A,0x4C}, //2040 {0x05,0x6d,0x41}, //2041 {0x24,0xAd,0xB6}, //2042 {0x04,0x9B,0x4A}, //2043 {0x7A,0x4B,0xBe}, //2044 {0x0A,0x4B,0x51}, //2045 {0x0A,0xA5,0x46}, //2046
{0x06,0xd2,0x4e}, //2048 {0x0A,0xdA,0x42}, //2049 {0x35,0x5B,0x37}, //2050 {0x09,0x37,0x4B}, //2051 {0x84,0x97,0xC1}, //2052 {0x04,0x97,0x53}, //2053 {0x06,0x4B,0x48}, //2054 {0x66,0xA5,0x3C}, //2055 {0x0e,0xA5,0x4f}, //2056 {0x06,0xB2,0x44}, //2057 {0x4A,0xB6,0x38}, //2058 {0x0A,0xAe,0x4C}, //2059 {0x09,0x2e,0x42}, //2060 {0x3C,0x97,0x35}, //2061 {0x0C,0x96,0x49}, //2062 {0x7d,0x4A,0xBd}, //2063 {0x0d,0x4A,0x51}, //2064 {0x0d,0xA5,0x45}, //2065 {0x55,0xAA,0xBA}, //2066 {0x05,0x6A,0x4e}, //2067 {0x0A,0x6d,0x43}, //2068 {0x45,0x2e,0xB7}, //2069 {0x05,0x2d,0x4B}, //2070 {0x8A,0x95,0xBf}, //2071 {0x0A,0x95,0x53}, //2072 {0x0B,0x4A,0x47}, //2073 {0x6B,0x55,0x3B}, //2074 {0x0A,0xd5,0x4f}, //2075 {0x05,0x5A,0x45}, //2076 {0x4A,0x5d,0x38}, //2077 {0x0A,0x5B,0x4C}, //2078 {0x05,0x2B,0x42}, //2079 {0x3A,0x93,0xB6}, //2080 {0x06,0x93,0x49}, //2081 {0x77,0x29,0xBd}, //2082 {0x06,0xAA,0x51}, //2083 {0x0A,0xd5,0x46}, //2084 {0x54,0xdA,0xBA}, //2085 {0x04,0xB6,0x4e}, //2086 {0x0A,0x57,0x43}, //2087 {0x45,0x27,0x38}, //2088 {0x0d,0x26,0x4A}, //2089 {0x8e,0x93,0x3e}, //2090
{0x0d,0xAA,0x47}, //2092 {0x66,0xB5,0x3B}, //2093 {0x05,0x6d,0x4f}, //2094 {0x04,0xAe,0x45}, //2095 {0x4A,0x4e,0xB9}, //2096 {0x0A,0x4d,0x4C}, //2097 {0x0d,0x15,0x41}, //2098 {0x2d,0x92,0xB5}, //2099 };
/***************************************************************************************************
哈尔滨市闲人无事发呆有限公司
鼓 捣 所
鼓捣总部
Q Q:958415720
Email:[email protected]
说 明: 经过几天日子的鼓捣,弄出来了这个万年历阳历转换阴历的转换代码,由于网上很多的代码写的
很乱,起初也不懂关于一些天文的知识,看的迷糊,让我很是无奈就想还是自己写吧偶尔在网上
找到了一个PDF文档叫《公历与农历日期的转换》 让我明白了许多 从而就开始花了一天的时间写
出来了。希望想要做万年历的人拿去用 这是在VC++ 6.0 平台的 直接就可以移植到51,AVR,STM32等等上
的。
作 者: 崔殿川
***************************************************************************************************/
#include
#include "test.h" //年份数据表包含头文件
#include "mytype.h"//数据类型宏定义包含头文件(UINT8 UINT16 UINT32....)
UINT8 LunarYearNum=0,LunarMonNum=0,LunarDayNum=0;//转化回来的阴历数值就存在相应的变量中(全局的)
UINT16 DayDataBase[12]={0,32,59,90,120,151,181,212,243,273,304,334};
/**********************************************************************************
函 数 名:获取农历的大小月份
入口参数:Mon: 当年的月份数(农历的0~13) YearOffsetAdd: 年份数据表里的偏移地址 返 回 值:0:大月份(30天) 1:小月份(29天)
说 明:大小月的获取主要是从年份数据表里三个字节的高13位当中获取 如果对应为是1则
是大月30天,小月29天
************************************************************************************/
UINT8 GetLunBig_LitMon(UINT8 Mon,UINT16 YearOffsetAdd)
{
UINT8 i=0;
(YearDataBase[YearOffsetAdd][(Mon>(Mon-5))):(0x08>>(Mon-1))))? (i=1):(i=0);
return (i);
}
/**********************************************************************************
函 数 名:公历到农历的转换
入口参数:对应着公历(阳历)的年(0~99),月(0~12),日(0~31)
返 回 值:0
***********************************************************************************/
UINT8 Solar2Luner(UINT8 SolarYearNum,UINT8 SolarMonNum,UINT8 SolarDayNum) {
UINT8 LeapMonVal=0; //农历闰月天数值变量
UINT8 NewYearToYuanDan_Mon=0,NewYearToYuanDan_Day=0; //定义春节所在的月份数(不是1月就是2月)
UINT8 YearFlag=0,MonPointer=0; //农历年的缓存标志和月份的偏移量
UINT8 temp=0; //春节距离元旦的天数
UINT16 TarGetDayT0YuanDan=0,YearOffsetAdd=0; //目标日期到元旦天数和年数据表的偏移地址
YearOffsetAdd=(SolarYearNum-1); //获取数据表地址
NewYearToYuanDan_Mon=(YearDataBase[YearOffsetAdd][2]&0x60)>>5; //计算春节所在的月份(不是1月就是2月)
NewYearToYuanDan_Day=(YearDataBase[YearOffsetAdd][2]&0x1f); //从年数据表里获取最后一个字节的第五位只要是计算春节到元旦的日期(Day的天数值)
(NewYearToYuanDan_Mon==1)?(temp=NewYearToYuanDan_Day-1):(temp=NewYearToYuanDan_Day+31-1); //temp这才是通过上面得到的春节所在的月份之后最终计算出来春节距离元旦的总天数
TarGetDayT0YuanDan=DayDataBase[SolarMonNum-1]+SolarDayNum-1;//得到目标日期到元旦天数
if ((SolarMonNum>2) && !(SolarYearNum%4))//如果是闰年则加目标天数1
TarGetDayT0YuanDan+=1;
//==============================转化分两块(以春节作为转换中心) 目标日期距离春节前或者春节后=========================//
if(TarGetDayT0YuanDan>=temp) //目标日期在春节之后
{
TarGetDayT0YuanDan-=temp; //求2个天数的差值
SolarMonNum=1;
MonPointer=1; //这时目标值一定是在一月
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29); //判断闰月的月份是大月还是小月
while(TarGetDayT0YuanDan>=LeapMonVal) //目标日期大于等于闰月(大小月)天数 {
TarGetDayT0YuanDan-=LeapMonVal;
MonPointer+=1;
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
if(SolarMonNum==YearDataBase[YearOffsetAdd][0]>>4) //获取第一字节的高四位 (闰月月份的获取)
{
YearFlag=~YearFlag;
if(!YearFlag)
SolarMonNum+=1;
}
else
SolarMonNum+=1;
}
SolarDayNum=TarGetDayT0YuanDan+1; //最后农历日期天数的获取
}
else //目标日期在春节前
{
temp-=TarGetDayT0YuanDan;
SolarYearNum-=1;
YearOffsetAdd-=3;
SolarMonNum=12;
(YearDataBase[YearOffsetAdd][0]>>4)?(MonPointer=13):(MonPointer=12);
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
while(temp>LeapMonVal)
{
temp-=LeapMonVal;
MonPointer-=1;
if(!YearFlag)
SolarMonNum-=1;
if(SolarMonNum==NewYearToYuanDan_Day)
YearFlag=~YearFlag;
(GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30):(LeapMonVal=29);
}
SolarDayNum=LeapMonVal-temp+1; //最后农历日期天数的获取
}
LunarYearNum=SolarYearNum;
LunarMonNum =SolarMonNum;
LunarDayNum =SolarDayNum;
return (0);
}
/***********************************************************************************************
-函 数 名:星期修正
-入口参数:对应着公历(阳历)的年(0~99),月(0~12),日(0~31)
-返 回 值:当天的星期
说 明:
公历日是非常有规律的所以公历日所对应的星期天可以通过计算直接得到理论上公元0 年1 月1 日为星期日
只要求得公历日离公元0 年1 月1 日的日子数除7 后的余数就是星期天为了简化计算采用月校正法根据公历
的年月日可直接计算出星期天其算法是日期年份所过闰年数月校正数之和除7 的余数就是星期天但如果是在
闰年又不到3 月份上述之和要减一天再除7 其1~12月的校正数据为6,2,2,5,0,3,5,1,4,6,2,4在本程序中采
用1 个字节表示年份闰年数也只计算1900 年以后的闰年数所以实际校正数据也和上述数据不同
详见PDF《公历与农历日期的转换》文档
************************************************************************************************/
#ifdef WEEKREVISE
UINT8 WeekDataBase[12]={6,2,2,5,0,3,5,1,4,6,2,4}; //月修正数据表
UINT8 WeekRevise(UINT8 SolarYearNum,UINT8 SolarMonNum,UINT8 SolarDayNum) {
return (!(SolarYearNum%4) && SolarMonNum
}
#endif
int main()
{
Solar2Luner(13,3,23);
printf("%d %d %d \n",LunarYearNum,LunarMonNum,LunarDayNum);
return 0;
}
//***************************************************************************** 下面是数据类型宏定义.h文件
******************************************************************************* #ifndef _MYTYPE_H_
#define _MYTYPE_H_
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
#define INT8 char
#define INT16 int
#define INT32 long
#endif
//***************************************************************************** 下面是年份数据表h文件
因为这里是在VC平台上的 就没有把数据表定义在ROM里 如果大家想要移植到51或者AVR等等处理器上 请自己更改、、、
******************************************************************************* #define WEEKREVISE //如果不使用星期修正注释掉这里
unsigned char YearDataBase[99][3]=
{
{0x4d,0x4A,0xB8}, //2001
{0x0d,0x4A,0x4C}, //2002
{0x25,0xAA,0xB6}, //2004 {0x05,0x6A,0x49}, //2005 {0x7A,0xAd,0xBd}, //2006 {0x02,0x5d,0x52}, //2007 {0x09,0x2d,0x47}, //2008 {0x5C,0x95,0xBA}, //2009 {0x0A,0x95,0x4e}, //2010 {0x0B,0x4A,0x43}, //2011 {0x4B,0x55,0x37}, //2012 {0x0A,0xd5,0x4A}, //2013 {0x95,0x5A,0xBf}, //2014 {0x04,0xBA,0x53}, //2015 {0x0A,0x5B,0x48}, //2016 {0x65,0x2B,0xBC}, //2017 {0x05,0x2B,0x50}, //2018 {0x0A,0x93,0x45}, //2019 {0x47,0x4A,0xB9}, //2020 {0x06,0xAA,0x4C}, //2021 {0x0A,0xd5,0x41}, //2022 {0x24,0xdA,0xB6}, //2023 {0x04,0xB6,0x4A}, //2024 {0x69,0x57,0x3d}, //2025 {0x0A,0x4e,0x51}, //2026 {0x0d,0x26,0x46}, //2027 {0x5e,0x93,0x3A}, //2028 {0x0d,0x53,0x4d}, //2029 {0x05,0xAA,0x43}, //2030 {0x36,0xB5,0x37}, //2031 {0x09,0x6d,0x4B}, //2032 {0xB4,0xAe,0xBf}, //2033 {0x04,0xAd,0x53}, //2034 {0x0A,0x4d,0x48}, //2035 {0x6d,0x25,0xBC}, //2036 {0x0d,0x25,0x4f}, //2037 {0x0d,0x52,0x44}, //2038 {0x5d,0xAA,0x38}, //2039 {0x0B,0x5A,0x4C}, //2040 {0x05,0x6d,0x41}, //2041 {0x24,0xAd,0xB6}, //2042 {0x04,0x9B,0x4A}, //2043 {0x7A,0x4B,0xBe}, //2044 {0x0A,0x4B,0x51}, //2045 {0x0A,0xA5,0x46}, //2046
{0x06,0xd2,0x4e}, //2048 {0x0A,0xdA,0x42}, //2049 {0x35,0x5B,0x37}, //2050 {0x09,0x37,0x4B}, //2051 {0x84,0x97,0xC1}, //2052 {0x04,0x97,0x53}, //2053 {0x06,0x4B,0x48}, //2054 {0x66,0xA5,0x3C}, //2055 {0x0e,0xA5,0x4f}, //2056 {0x06,0xB2,0x44}, //2057 {0x4A,0xB6,0x38}, //2058 {0x0A,0xAe,0x4C}, //2059 {0x09,0x2e,0x42}, //2060 {0x3C,0x97,0x35}, //2061 {0x0C,0x96,0x49}, //2062 {0x7d,0x4A,0xBd}, //2063 {0x0d,0x4A,0x51}, //2064 {0x0d,0xA5,0x45}, //2065 {0x55,0xAA,0xBA}, //2066 {0x05,0x6A,0x4e}, //2067 {0x0A,0x6d,0x43}, //2068 {0x45,0x2e,0xB7}, //2069 {0x05,0x2d,0x4B}, //2070 {0x8A,0x95,0xBf}, //2071 {0x0A,0x95,0x53}, //2072 {0x0B,0x4A,0x47}, //2073 {0x6B,0x55,0x3B}, //2074 {0x0A,0xd5,0x4f}, //2075 {0x05,0x5A,0x45}, //2076 {0x4A,0x5d,0x38}, //2077 {0x0A,0x5B,0x4C}, //2078 {0x05,0x2B,0x42}, //2079 {0x3A,0x93,0xB6}, //2080 {0x06,0x93,0x49}, //2081 {0x77,0x29,0xBd}, //2082 {0x06,0xAA,0x51}, //2083 {0x0A,0xd5,0x46}, //2084 {0x54,0xdA,0xBA}, //2085 {0x04,0xB6,0x4e}, //2086 {0x0A,0x57,0x43}, //2087 {0x45,0x27,0x38}, //2088 {0x0d,0x26,0x4A}, //2089 {0x8e,0x93,0x3e}, //2090
{0x0d,0xAA,0x47}, //2092 {0x66,0xB5,0x3B}, //2093 {0x05,0x6d,0x4f}, //2094 {0x04,0xAe,0x45}, //2095 {0x4A,0x4e,0xB9}, //2096 {0x0A,0x4d,0x4C}, //2097 {0x0d,0x15,0x41}, //2098 {0x2d,0x92,0xB5}, //2099 };