|
楼主 |
发表于 2010-4-14 09:41:36
|
显示全部楼层
///////////////////////////////////////////////////////////////////////////////////////////////////
//
//
// FILE NAME : main.c
// TARGET DEVICE : C8051F020
// IDE VER : KEIL C51V900
// CREATED ON : 10-04-11
// CREATED BY : BILLTIAN
//
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#define _IN_moondate_C_
///////////////////////////////////////////////////////////////////////////////////////////////////
// Includes
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "main.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////////////////////////////////////////////
//子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/
bit get_moon_day(uint8 month_p,uint16 table_addr)
{
uint8 temp;
switch (month_p){
case 1:{temp=year_code[table_addr]&0x08;
if (temp==0)return(0);else return(1);}
case 2:{temp=year_code[table_addr]&0x04;
if (temp==0)return(0);else return(1);}
case 3:{temp=year_code[table_addr]&0x02;
if (temp==0)return(0);else return(1);}
case 4:{temp=year_code[table_addr]&0x01;
if (temp==0)return(0);else return(1);}
case 5:{temp=year_code[table_addr+1]&0x80;
if (temp==0) return(0);else return(1);}
case 6:{temp=year_code[table_addr+1]&0x40;
if (temp==0)return(0);else return(1);}
case 7:{temp=year_code[table_addr+1]&0x20;
if (temp==0)return(0);else return(1);}
case 8:{temp=year_code[table_addr+1]&0x10;
if (temp==0)return(0);else return(1);}
case 9:{temp=year_code[table_addr+1]&0x08;
if (temp==0)return(0);else return(1);}
case 10:{temp=year_code[table_addr+1]&0x04;
if (temp==0)return(0);else return(1);}
case 11:{temp=year_code[table_addr+1]&0x02;
if (temp==0)return(0);else return(1);}
case 12:{temp=year_code[table_addr+1]&0x01;
if (temp==0)return(0);else return(1);}
case 13:{temp=year_code[table_addr+2]&0x80;
if (temp==0)return(0);else return(1);}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
//调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
//如:计算2004年10月16日Conversion(0,4,10,16);
//c_sun为世纪标志位,c_sun=0为21世纪,c_sun=1为20世纪
///////////////////////////////////////////////////////////////////////////////////////////////////
void Conversion(bit c,TimeDate * ps,TimeDate * pm)
{
uint8 temp1,temp2,temp3,month_p;
uint16 temp4,table_addr;
uint8 year,month,day;
bit flag2,flag_y;
year = ps->year;
month = ps->month;
day = ps->date;
//定位数据表地址
if(c==0)
{
table_addr=(year+0x64-1)*0x3;
}
else
{
table_addr=(year-1)*0x3;
}
//定位数据表地址完成
//取当年春节所在的公历月份
temp1=year_code[table_addr+2]&0x60;
temp1=_cror_(temp1,5);
//取当年春节所在的公历月份完成
//取当年春节所在的公历日
temp2=year_code[table_addr+2]&0x1f;
//取当年春节所在的公历日完成
//计算当年春年离当年元旦的天数,春节只会在公历1月或2月
if(temp1==0x1)
{
temp3=temp2-1;
}
else
{
temp3=temp2+0x1f-1;
}
//计算当年春年离当年元旦的天数完成
//计算公历日离当年元旦的天数
temp4 = day_code[month-1] + day - 1;
if ((month>0x2)&&(year%0x4==0))
{ //如果公历月大于2月并且该年的2月为闰月,天数加1
temp4+=1;
}
//计算公历日离当年元旦的天数完成
//判断公历日在春节前还是春节后
if (temp4>=temp3)
{ //公历日在春节后或就是春节当日使用下面代码进行运算
temp4-=temp3;
month=0x1;
month_p=0x1; //month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月
flag2=get_moon_day(month_p,table_addr); //检查该农历月为大小还是小月,大月返回1,小月返回0
flag_y=0;
if(flag2==0)
{
temp1=0x1d; //小月29天
}
else
{
temp1=0x1e; //大小30天
}
//从数据表中取该年的闰月月份,如为0则该年无闰月
temp2=year_code[table_addr]&0xf0;
temp2=_cror_(temp2,4);
while(temp4>=temp1)
{
temp4-=temp1;
month_p+=1;
if(month==temp2)
{ //是闰月
flag_y=~flag_y;
if(flag_y==0)
{
month+=1;
}
}
else
{
month+=1;
}
flag2=get_moon_day(month_p,table_addr);
if(flag2==0)
{
temp1=0x1d;
}
else
{
temp1=0x1e;
}
}
day=temp4+1;
}
else
{ //公历日在春节前使用下面代码进行运算
temp3-=temp4;
if (year==0x0)
{
year=0x63;
c=1;
}
else
{
year-=1;
}
table_addr-=0x3;
month=0xc;
temp2=year_code[table_addr]&0xf0;
temp2=_cror_(temp2,4);
if (temp2==0)
{
month_p=0xc;
}
else
{
month_p=0xd; //month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12
}
flag_y=0;
flag2=get_moon_day(month_p,table_addr);
if(flag2==0)
{
temp1=0x1d;
}
else
{
temp1=0x1e;
}
while(temp3>temp1)
{
temp3-=temp1;
month_p-=1;
if(flag_y==0)
{
month-=1;
}
if(month==temp2)
{
flag_y=~flag_y;
}
flag2=get_moon_day(month_p,table_addr);
if(flag2==0)
{
temp1=0x1d;
}
else
{
temp1=0x1e;
}
}
day=temp1-temp3+1;
}
pm->year=year;
pm->month=month;
pm->date=day;
}
//输入公元日期时间,计算天干地支年月日时,暂时只能计算2000年到2050的年份
uint8 tiangandizhi(TimeDate * p,TianganDizhiStruct * ptgdz)
{
uint16 temp;
uint8 springdate,flag; //flag=1,表示输入日期在立春前,0表示在立春后
uint8 yearindex,monthindex,dateindex,timeindex; //天干地支序号0~59;
TimeDate tt;
//获得立春日期,用2月1日去计算,天干地支纪年是从立春开始
tt.year = p->year;
tt.month = 2;
tt.date = 1;
GetJieQi(&tt,&springdate);
//计算年号
if((p->month>2) || ((2 == p->month)&&(p->date >= springdate)))
{ //日期在立春后
flag = 0;
}
else
{ //日期在立春前
flag = 1;
}
yearindex = (p->year+2000-4-flag)%60;
//计算月
//获得当月上半月节气日期
tt.year = p->year;
tt.month = p->month;
tt.date = 1;
GetJieQi(&tt,&springdate);
if(0 == flag)
{ //日期在立春后
if(p->date<springdate)
{//之前
monthindex = ((yearindex%5)*12 + p->month - 1)%60;
}
else
{//当日或之后
monthindex = ((yearindex%5)*12 + p->month)%60;
}
}
else
{ //日期在立春前
if(2 == p->month)
{
monthindex = (((yearindex-1)%5)*12 + (p->month-1) +12)%60;
}
else if(1 == p->month)
{
if(p->date<springdate)
{//之前,按去年12月计算
monthindex = ((yearindex%5)*12 + 12)%60;
}
else
{//当日或之后,
monthindex = (((yearindex-1)%5)*12 + (p->month) +12)%60;
}
}
}
//计算日
//暂时没找到好的方法,暂时用2000年1月1日(戊午,54)做为参考计算
//计算距离参考日的天数
if(0 == p->year)
{
temp = (day_code[p->month - 1]) + (p->date -1);
if(p->month>2)
{ //2000年为闰年
temp += 1;
}
}
else
{
temp = ((p->year)*365 + p->year/4 + 1) + (day_code[p->month - 1]) + (p->date -1);
}
dateindex = (temp+54)%60;
//计算时
if(0 == p->hour)
{ //0点按前一天计算
timeindex = ((dateindex+59)%60)%5 * 12;
}
else if(23 == p->hour)
{ //23点按明天计算
timeindex = ((dateindex+1)%60)%5 * 12;
}
else
{
timeindex = (dateindex%5)*12 + ((p->hour-1)/2 + 1);
}
ptgdz->year = yearindex;
ptgdz->month = monthindex;
ptgdz->date = dateindex;
ptgdz->time = timeindex;
return 0;
}
//获得节气日期
uint8 GetJieQi(TimeDate * p,uint8 *JQdate)
{
uint8 bak1,value,JQ;
uint16 year;
year = p->year + 2000;
if((year<2000)||(year>2050))
{
return 0;
}
if((p->month==0) ||(p->month>12))
{
return 0;
}
JQ = (p->month-1) *2 ; //获得节气顺序标号(0~23)
if(p->date >= 15) JQ++; //判断是否是上半月
bak1=YearMonthBit[(year-2000)*3+JQ/8]; //获得节气日期相对值所在字节
value =((bak1<<(JQ%8))&0x80); //获得节气日期相对值状态
*JQdate=days[JQ];
if( value != 0 )
{
//判断年份,以决定节气相对值1代表1,还是-1。
if( (JQ==1||JQ==11||JQ==18||JQ==21) && (year< 2044))
{
(*JQdate)++;
}
else
{
(*JQdate)--;
}
}
return 1;
} |
|