卓泰科技 发表于 2015-2-17 23:00:21

【Joytag 小项目】智能小终端 (设想)

话说,一直想做这么个小东西。
主要功能用来显示时间。
既然都能显示时间了,那么加个闹钟功能貌似也不过分。
如果再加上星期、农历以及节气等,听起来似乎更加高大上。
然后如果加上天气预报显示,是不是会更加方便?
既然有预报了,那么要不要加个室内外温度度的实时数据呢?
然后.....

然后就整日沉浸在空想中,始终未能动手。
时间就这样流逝了,时钟还未诞生......

群里一哥们正在做一个时钟万年历,所以又勾起我做这个小终端的兴致。
那么先来明确一下需求吧:

显示功能

[*]时间显示:年月日时分秒,星期
[*]万年历显示:农历、节气、节日等
[*]天气预报显示:沈阳本地的当日天气预报 (空气质量)
[*]温湿度显示:实时显示室内外温湿度情况
[*]闹钟显示:显示是否设置闹钟,以及设置的闹钟时间等

设置功能


[*]时间设定
[*]闹钟设定
[*]温湿度限定设置

报警功能

[*]闹钟报警
[*]温湿度超限报警


基本方案

显示部分:

首先,因为要显示的内容比较多,所以摒弃1602等方案。
初步计划使用手头现有的串口液晶模块(使用比较方便)

设定部分:

使用按键比较麻烦,所以计划通过网络设置。
基本方案为使用ESP8266 WIFI模块将终端接入家庭网络。
时间设定部分,采取NTP自动校时。
其余设置部分:
1)终端使用AP+STA模式,自带web配置界面?
2)类似虚拟主机web界面,将数据存入,终端前去获取?
3)智能路由器方案
4)其它

时间存储以及农历显示
使用现有的RTC模块完成
(节日节气,应该可以自己查表实现)

天气预报:
难点在于如何找到可用并且稳定的数据源

报警功能:
报警功能计划使用声光报警两种方式
可以通过蜂鸣器报警以及LED闪烁实现。
另外,可以通过控制屏幕字体、背景等颜色,来显示温湿度超限等信息。

其它:
待补充

囧囧-科技大神粉 发表于 2015-2-17 23:48:06

;P 一个1602不行,来2个如何?还不行就3个,反正i2C,屏多线少


卓泰科技 发表于 2015-2-20 20:32:27

囧囧-科技大神粉 发表于 2015-2-17 23:48
一个1602不行,来2个如何?还不行就3个,反正i2C,屏多线少

:'(买不起好多1602

卓泰科技 发表于 2015-2-20 20:51:39

RTC

查了一下自己手头的器件

RTC模块有三款

[*]DS1302
[*]DS1307+AT24C32I2C接口
[*]DS3231+AT24C32   I2C接口

后两款使用I2C接口,貌似后边一种更高端,决定先用这个。


DS3231模块

模块参数:


[*]尺寸:38mm(长)*22mm(宽)*14mm(高)
[*]重量:8g
[*]工作电压:3.3--5.5V
[*]时钟芯片:高精度时钟芯片DS3231
[*]时钟精度:0-40℃范围内,精度2ppm,年误差约1分钟
[*]带2个日历闹钟
[*]可编程方波输出
[*]实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿
[*]芯片内部自带温度传感器,精度为±3℃
[*]存储芯片:AT24C32(存储容量32K)
[*]IIC总线接口,最高传输速度400KHz(工作电压为5V时)
[*]可级联其它IIC设备,24C32地址可通过短路A0/A1/A2修改,默认地址为0x57
[*]带电池CR2032,保证系统断电后,时钟任然正常走动


接线说明(以Arduino uno r3为例):


[*]SCL→A5
[*]SDA→A4
[*]VCC→5V
[*]GND→GND


卓泰科技 发表于 2015-2-20 21:05:23

DS3231简单例子:

DS3231_TEST.ino
/*
DS3231_test.pde
Eric Ayars
4/11

Test/demo of read routines for a DS3231 RTC.

Turn on the serial monitor after loading this to check if things are
working as they should.

*/

#include <DS3231.h>
#include <Wire.h>

DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;

byte year, month, date, DoW, hour, minute, second;

void setup() {
      // Start the I2C interface
      Wire.begin();
      Clock.setSecond(50);//Set the second
      Clock.setMinute(59);//Set the minute
      Clock.setHour(11);//Set the hour
      Clock.setDoW(5);    //Set the day of the week
      Clock.setDate(31);//Set the date of the month
      Clock.setMonth(5);//Set the month of the year
      Clock.setYear(13);//Set the year (Last two digits of the year)
      // Start the serial interface
      Serial.begin(115200);
}
void ReadDS3231()
{
int second,minute,hour,date,month,year,temperature;
second=Clock.getSecond();
minute=Clock.getMinute();
hour=Clock.getHour(h12, PM);
date=Clock.getDate();
month=Clock.getMonth(Century);
year=Clock.getYear();

temperature=Clock.getTemperature();

Serial.print("20");
Serial.print(year,DEC);
Serial.print('-');
Serial.print(month,DEC);
Serial.print('-');
Serial.print(date,DEC);
Serial.print(' ');
Serial.print(hour,DEC);
Serial.print(':');
Serial.print(minute,DEC);
Serial.print(':');
Serial.print(second,DEC);
Serial.print('\n');
Serial.print("Temperature=");
Serial.print(temperature);
Serial.print('\n');
}
void loop() {
ReadDS3231();
delay(1000);
}
AT24C32_TEST.ino
#include <Wire.h> //I2C library

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
}

// WARNING: address is a page address, 6-bit end will wrap around
// also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
      Wire.write(data);
    Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
}

// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
      if (Wire.available()) buffer = Wire.read();
}
void setup()
{
    int addr=0,i;   
    Wire.begin(); // initialise the connection
    Serial.begin(9600);   
    Serial.println("Write:");
    for(i=0;i<26;i++)
    {
   i2c_eeprom_write_byte(0x57,addr,i+65);
   addr++;
   addr=addr%26;   
   Serial.print(char(i+65));
   delay(10); //add a small delay
    }
    Serial.print('\n');   
}

void loop()
{
    int i,b;
    int addr=0; //first address   
    Serial.println("Read:");
    for(i=0;i<26;i++)
    {   
      b = i2c_eeprom_read_byte(0x57, i); //access an address from the memory
      Serial.print(char(b));
}
   Serial.print('\n');
    delay(2000);
}

Arduino库以及芯片资料:
DS3231 Arduino库:
DS3231 芯片资料:
AT24C32芯片资料:

卓泰科技 发表于 2015-2-20 21:26:09

关于闰年

因为万年历(农历)问题涉及到闰年,这个是小学生的知识,但是早就还给体育老师了。所以复习了一下。


闰年知识

闰年(Leap Year)是为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差而设立的。补上时间差的年份为闰年。
闰年有366天。

通常的解释是说一年有多少天多少小时多少分,取整数365还有多余的,累积达到一天24小时后,就多加一天的年是闰年。这个解释只是告诉了大家怎么计算,是人为设置的东西。

最根本的原因是:地球绕太阳运行周期为365天5小时48分46秒(合365.24219天)即一回归年(tropical year)。公历的平年只有365日,比回归年短约0.2422 日,所余下的时间约为四年累计一天,故四年于2月加1天,使当年的历年长度为366日,这一年就为闰年。现行公历中每400年有97个闰年。按照每四年一个闰年计算,平均每年就要多算出0.0078天,这样经过四百年就会多算出大约3天来。因此每四百年中要减少三个闰年。所以公历规定:年份是整百数时,必须是400的倍数才是闰年;不是400的倍数的年份,即使是4的倍数也是平年。

这就是通常所说的:四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,1900年则是平年。

公历闰年计算

(按一回归年365天5小时48分45.5秒)
①、普通年能被4整除且不能被100整除的为闰年。(如2004年就是闰年,1900年不是闰年)
②、世纪年能被400整除的是闰年。(如2000年是闰年,1900年不是闰年)
③、对于数值很大的年份,这年如果能被3200整除,并且能被172800整除则是闰年。如172800年是闰年,86400年不是闰年(因为虽然能被3200整除,但不能被172800整除)(此按一回归年365天5h48'45.5''计算)。

根据需求,我们只需考虑简单的情况。


计算方式

符合如下条件为闰年,否则为平年:
if((year%4==0 && year%100!=0) || year%400==0)


卓泰科技 发表于 2015-2-20 23:00:43

公历农历转换

百度了一下,没发现啥简单的算法。
一般公历农历转换代码的本质都是查表。

网上找到几组,贴过来以免忘记


1)最精简的公历农历转换程序(C源程序)
原帖地址:http://bbs.21ic.com/icview-137951-1-1.html
此程序为本人所写,免费供有需要的人使用,无版权纠纷;
程序的功能是输入2000年2月5日(正月初一)至2100年12月31日之间的公历日期,输出对应的农历日期(闰月以月份+128表示);
该程序比较精简,适合资源紧张的MCU场合。由IAR编译成MSP430的目标代码,大约占用600个字节的程序空间,如改用汇编,去除多余的头尾,应该可以缩减到500字节以内;

程序特色在于用101个16位字表述了101年的农历大小月及闰月的数据。低12位表示对应12个月的月大或月小,最低位为正月,1表示月大;高4位为0时表示当年及下一年无闰月;高4位为1~12时表示下一年度的相应月存在闰月;高4位为13或14时,分别表示当前年的闰月为月小或月大。按照这个结构可以扩充到更多年份,但程序中对非闰年的公历1900,2200,2300,2500年份未作处理,仅对2100作为特例处理。另外,扩展到更多年份后某些变量可能存在溢出。
为简化程序,在转换函数内对输入日期的合法性未作判别,如输入1810-2-15、2008-6-31、2135-1-1等,将导致不可预料的输出结果。
提醒:程序仅对二三十个比较典型的日期进行了抽样测试,未做逐月验证,对于相近农历月大小颠倒的情况不能排除,如作为产品使用,请再次确认转换表数据的正确性。

//Lunar calendar convert program
//Designed by QQ984809120, 2009-10-6
/*
convert table(2000~2100) structure:
D15~D12=0000Current and next year no leap month
D15~D12=0001~1100 leap month number of next year
D11~D0 = days of 12 months, 1: 30 days; 0: 29 days
D15~D12=111030 days in leap month of current year
D15~D12=110129 days in leap month of current year
*/
const unsigned int table = {0x4693,
0xDA9B, 0x052B, 0x2A5B, 0xDAAE, 0x756A, 0xDDD5, 0x0BA4, 0x5B49, 0xDD53, 0x0A95,
0x452D, 0xD55D, 0x9AB5, 0xDBAA, 0x05D2, 0x6DA5, 0xEE8A, 0x0D4A, 0x4C95, 0xDA9E,
0x0556, 0x2AB5, 0xDADA, 0x66D2, 0xD765, 0x0725, 0x564B, 0xD657, 0x0CAB, 0x355A,
0xD56E, 0xBB69, 0xDF52, 0x0B52, 0x5B25, 0xDD2B, 0x0A4B, 0x54AB, 0xD2BB, 0x05AD,
0x2B6A, 0xDDAA, 0x7D92, 0xDEA5, 0x0D25, 0x5A55, 0xEA4D, 0x04B6, 0x35B5, 0xE6D2,
0x8EC9, 0xDF92, 0x0E92, 0x6D26, 0xE516, 0x0A57, 0x44D6, 0xE365, 0x0755, 0x3749,
0xD74B, 0x7693, 0xDAAB, 0x052B, 0x5A5B, 0xDABA, 0x056A, 0x4B65, 0xDBAA, 0x8B4A,
0xDD95, 0x0A95, 0x652D, 0xD56D, 0x0AB5, 0x55AA, 0xE5C5, 0x0DA5, 0x3D4A, 0xDE4D,
0x7C96, 0xDCCE, 0x0556, 0x5AB5, 0xEAD2, 0x06D2, 0x5EA5, 0xD72A, 0x868B, 0xD697,
0x04AB, 0x655B, 0xE556, 0x0B6A, 0x4752, 0xDB95, 0x0B25, 0x2A8B, 0xDA4F, 0x04AB};
/*Convert routine
00<yy<=100, 1<=mm<=12, 1<=dd<=31
*/

date_cvt (unsigned char yy, unsigned char mm, unsigned char dd, unsigned char *buff)
{ unsigned char i,j,leap;
unsigned int days1,days2,x;
   days1 = yy * 365 + ((yy+3)>>2) + (mm-1)*30 + dd;
   if ((mm >2) && ((yy & 3) == 0) && (yy != 100))
       days1 ++;
   switch(mm)
    {
   case 3:days1--;
            break;
   case 11:
   case 12: days1 ++;
   case 9:
   case 10: days1 ++;
   case 8:days1 ++;
   case 2:
   case 6:
   case 7:days1 ++;
    }   //------days from 1999-12-31
   days1 -=35;
   days2=0;
   leap=0xFF;
   for (i=0; i<=100; i++)
    {x=table;
   for (j=0; j<12; j++)
       {
         days2 += 29 + (x & 1);
         if (days2 >= days1)
         break;

         if (j==leap)
         {
         days2 += 16 + (table >> 12);
            if (days2 >= days1)
               {j |= 0x80;
                  x = ~(table >> 12);
                  break;
                }
         }
         x >>= 1;
       }
   if (days2 >= days1)
       break;
   
   leap = x-1;
    }
   * buff++ = i;//output result
   * buff++ = j+1;
   * buff   = (unsigned char) (29 + (x & 1) -(days2-days1));
}
main()   /*main program*/
{ unsigned char buff; //Save year(xx:20xx),month,day
date_cvt( 9, 10, 6, &buff);  //Only for example
}

卓泰科技 发表于 2015-2-20 23:14:40

2)

公历转农历C程序 收藏
注意只能到2049年!



#define uchar unsigned char
#define uint unsigned int
#include <intrins.h>
/*
公历年对应的农历数据,每年三字节,
格式第一字节BIT7-4 位表示闰月月份,值为0 为无闰月,BIT3-0 对应农历第1-4 月的大小
第二字节BIT7-0 对应农历第5-12 月大小,第三字节BIT7 表示农历第13 个月大小
月份对应的位为1 表示本农历月大(30 天),为0 表示小(29 天)
第三字节BIT6-5 表示春节的公历月份,BIT4-0 表示春节的公历日期
*/
code uchar year_code={
                  0x04,0xAe,0x53,    //1901 0
                  0x0A,0x57,0x48,    //1902 3
                  0x55,0x26,0xBd,    //1903 6
                  0x0d,0x26,0x50,    //1904 9
                  0x0d,0x95,0x44,    //1905 12
                  0x46,0xAA,0xB9,    //1906 15
                  0x05,0x6A,0x4d,    //1907 18
                  0x09,0xAd,0x42,    //1908 21
                  0x24,0xAe,0xB6,    //1909
                  0x04,0xAe,0x4A,    //1910
                  0x6A,0x4d,0xBe,    //1911
                  0x0A,0x4d,0x52,    //1912
                  0x0d,0x25,0x46,    //1913
                  0x5d,0x52,0xBA,    //1914
                  0x0B,0x54,0x4e,    //1915
                  0x0d,0x6A,0x43,    //1916
                  0x29,0x6d,0x37,    //1917
                  0x09,0x5B,0x4B,    //1918
                  0x74,0x9B,0xC1,    //1919
                  0x04,0x97,0x54,    //1920
                  0x0A,0x4B,0x48,    //1921
                  0x5B,0x25,0xBC,    //1922
                  0x06,0xA5,0x50,    //1923
                  0x06,0xd4,0x45,    //1924
                  0x4A,0xdA,0xB8,    //1925
                  0x02,0xB6,0x4d,    //1926
                  0x09,0x57,0x42,    //1927
                  0x24,0x97,0xB7,    //1928
                  0x04,0x97,0x4A,    //1929
                  0x66,0x4B,0x3e,    //1930
                  0x0d,0x4A,0x51,    //1931
                  0x0e,0xA5,0x46,    //1932
                  0x56,0xd4,0xBA,    //1933
                  0x05,0xAd,0x4e,    //1934
                  0x02,0xB6,0x44,    //1935
                  0x39,0x37,0x38,    //1936
                  0x09,0x2e,0x4B,    //1937
                  0x7C,0x96,0xBf,    //1938
                  0x0C,0x95,0x53,    //1939
                  0x0d,0x4A,0x48,    //1940
                  0x6d,0xA5,0x3B,    //1941
                  0x0B,0x55,0x4f,    //1942
                  0x05,0x6A,0x45,    //1943
                  0x4A,0xAd,0xB9,    //1944
                  0x02,0x5d,0x4d,    //1945
                  0x09,0x2d,0x42,    //1946
                  0x2C,0x95,0xB6,    //1947
                  0x0A,0x95,0x4A,    //1948
                  0x7B,0x4A,0xBd,    //1949
                  0x06,0xCA,0x51,    //1***
                  0x0B,0x55,0x46,    //1951
                  0x55,0x5A,0xBB,    //1952
                  0x04,0xdA,0x4e,    //1953
                  0x0A,0x5B,0x43,    //1954
                  0x35,0x2B,0xB8,    //1955
                  0x05,0x2B,0x4C,    //1956
                  0x8A,0x95,0x3f,    //1957
                  0x0e,0x95,0x52,    //1958
                  0x06,0xAA,0x48,    //1959
                  0x7A,0xd5,0x3C,    //1960
                  0x0A,0xB5,0x4f,    //1961
                  0x04,0xB6,0x45,    //1962
                  0x4A,0x57,0x39,    //1963
                  0x0A,0x57,0x4d,    //1964
                  0x05,0x26,0x42,    //1965
                  0x3e,0x93,0x35,    //1966
                  0x0d,0x95,0x49,    //1967
                  0x75,0xAA,0xBe,    //1968
                  0x05,0x6A,0x51,    //1969
                  0x09,0x6d,0x46,    //1970
                  0x54,0xAe,0xBB,    //1971
                  0x04,0xAd,0x4f,    //1972
                  0x0A,0x4d,0x43,    //1973
                  0x4d,0x26,0xB7,    //1974
                  0x0d,0x25,0x4B,    //1975
                  0x8d,0x52,0xBf,    //1976
                  0x0B,0x54,0x52,    //1977
                  0x0B,0x6A,0x47,    //1978
                  0x69,0x6d,0x3C,    //1979
                  0x09,0x5B,0x50,    //1980
                  0x04,0x9B,0x45,    //1981
                  0x4A,0x4B,0xB9,    //1982
                  0x0A,0x4B,0x4d,    //1983
                  0xAB,0x25,0xC2,    //1984
                  0x06,0xA5,0x54,    //1985
                  0x06,0xd4,0x49,    //1986
                  0x6A,0xdA,0x3d,    //1987
                  0x0A,0xB6,0x51,    //1988
                  0x09,0x37,0x46,    //1989
                  0x54,0x97,0xBB,    //1990
                  0x04,0x97,0x4f,    //1991
                  0x06,0x4B,0x44,    //1992
                  0x36,0xA5,0x37,    //1993
                  0x0e,0xA5,0x4A,    //1994
                  0x86,0xB2,0xBf,    //1995
                  0x05,0xAC,0x53,    //1996
                  0x0A,0xB6,0x47,    //1997
                  0x59,0x36,0xBC,    //1998
                  0x09,0x2e,0x50,    //1999 294
                  0x0C,0x96,0x45,    //2000 297
                  0x4d,0x4A,0xB8,    //2001
                  0x0d,0x4A,0x4C,    //2002
                  0x0d,0xA5,0x41,    //2003
                  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
                  0x5B,0x52,0xBA,    //2047
                  0x06,0xd2,0x4e,    //2048
                  0x0A,0xdA,0x42,    //2049
                  
};

///月份数据表
code uchar day_code1={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
code uint day_code2={0x111,0x130,0x14e};

/*
函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
纪,c_sun=1为19世纪
调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
*/
bit c_moon;
data uchar year_moon,month_moon,day_moon,week;
/*子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/
bit get_moon_day(uchar month_p,uint table_addr)
{
uchar temp;
    switch (month_p){
      case 1:{temp=year_code&0x08;
             if (temp==0)return(0);else return(1);}
      case 2:{temp=year_code&0x04;
             if (temp==0)return(0);else return(1);}
      case 3:{temp=year_code&0x02;
             if (temp==0)return(0);else return(1);}
      case 4:{temp=year_code&0x01;
             if (temp==0)return(0);else return(1);}
      case 5:{temp=year_code&0x80;
             if (temp==0) return(0);else return(1);}
      case 6:{temp=year_code&0x40;
             if (temp==0)return(0);else return(1);}
      case 7:{temp=year_code&0x20;
             if (temp==0)return(0);else return(1);}
      case 8:{temp=year_code&0x10;
             if (temp==0)return(0);else return(1);}
      case 9:{temp=year_code&0x08;
             if (temp==0)return(0);else return(1);}
      case 10:{temp=year_code&0x04;
             if (temp==0)return(0);else return(1);}
      case 11:{temp=year_code&0x02;
             if (temp==0)return(0);else return(1);}
      case 12:{temp=year_code&0x01;
             if (temp==0)return(0);else return(1);}
      case 13:{temp=year_code&0x80;
             if (temp==0)return(0);else return(1);}
    }
}

/*
函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
纪,c_sun=1为19世纪
调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
*/

void Conversion(bit c,uchar year,uchar month,uchar day)
{                         //c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据
    uchar temp1,temp2,temp3,month_p;
    uint temp4,table_addr;
    bit flag2,flag_y;
    temp1=year/16;   //BCD->hex 先把数据转换为十六进制
    temp2=year%16;
    year=temp1*10+temp2;
    temp1=month/16;
    temp2=month%16;
    month=temp1*10+temp2;
    temp1=day/16;
    temp2=day%16;
    day=temp1*10+temp2;

    //定位数据表地址
    if(c==0){                  
      table_addr=(year+0x64-1)*0x3;
    }
    else {
      table_addr=(year-1)*0x3;
    }
    //定位数据表地址完成

    //取当年春节所在的公历月份
    temp1=year_code&0x60;
    temp1=_cror_(temp1,5);
    //取当年春节所在的公历月份完成

    //取当年春节所在的公历日
    temp2=year_code&0x1f;
    //取当年春节所在的公历日完成

    // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月
    if(temp1==0x1){
      temp3=temp2-1;
    }
    else{
      temp3=temp2+0x1f-1;      
    }
    // 计算当年春年离当年元旦的天数完成

    //计算公历日离当年元旦的天数,为了减少运算,用了两个表
    //day_code1,day_code2
    //如果公历月在九月或前,天数会少于0xff,用表day_code1,
    //在九月后,天数大于0xff,用表day_code2
    //如输入公历日为8月10日,则公历日离元旦天数为day_code1+10-1
    //如输入公历日为11月10日,则公历日离元旦天数为day_code2+10-1
    if (month<10){
      temp4=day_code1+day-1;
    }
    else{
      temp4=day_code2+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天
      temp2=year_code&0xf0;
      temp2=_cror_(temp2,4);//从数据表中取该年的闰月月份,如为0则该年无闰月
      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&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;
    }
    c_moon=c;               //HEX->BCD ,运算结束后,把数据转换为BCD数据
    temp1=year/10;
    temp1=_crol_(temp1,4);
    temp2=year%10;
    year_moon=temp1|temp2;
    temp1=month/10;
    temp1=_crol_(temp1,4);
    temp2=month%10;
    month_moon=temp1|temp2;
    temp1=day/10;
    temp1=_crol_(temp1,4);
    temp2=day%10;
    day_moon=temp1|temp2;
}
/*
函数功能:输入BCD阳历数据,输出BCD星期数据(只允许1901-2099年)
调用函数示例:Conver_week(c_sun,year_sun,month_sun,day_sun)
如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
纪,c_sun=1为19世纪
调用函数后,原有数据不变,读week得出阴历BCD数据
*/
code uchar table_week={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
/*
算法:日期+年份+所过闰年数+月较正数之和除7 的余数就是星期但如果是在
闰年又不到3 月份上述之和要减一天再除7
星期数为0
*/

void Conver_week(bit c,uchar year,uchar month,uchar day)
{//c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据
    uchar temp1,temp2;
    temp1=year/16;   //BCD->hex 先把数据转换为十六进制
    temp2=year%16;
    year=temp1*10+temp2;
    temp1=month/16;
    temp2=month%16;
    month=temp1*10+temp2;
    temp1=day/16;
    temp2=day%16;
    day=temp1*10+temp2;
    if (c==0){year+=0x64;}//如果为21世纪,年份数加100
    temp1=year/0x4;//所过闰年数只算1900年之后的
    temp2=year+temp1;
    temp2=temp2%0x7;//为节省资源,先进行一次取余,避免数大于0xff,避免使用整型数据
    temp2=temp2+day+table_week;
    if (year%0x4==0&&month<3)temp2-=1;
    week=temp2%0x7;
}

//test
uchar c_sun,year_sun,month_sun,day_sun;
void main(){
c_sun=1;
year_sun=0x2;
month_sun=0x11;
day_sun=0x3;
Conver_week(c_sun,year_sun,month_sun,day_sun);
Conversion(c_sun,year_sun,month_sun,day_sun);
while(1);
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lengshine/archive/2010/04/10/5470616.asp



卓泰科技 发表于 2015-2-20 23:15:48

3)

#include <stdio.h>
#include <afx.h>
#include <windows.h>

const WORD START_YEAR =1901;
const WORD END_YEAR   =2050;


/******************************************************************************
下面为阴历计算所需的数据,为节省存储空间,所以采用下面比较变态的存储方法.
   
*******************************************************************************/
//数组gLunarDay存入阴历1901年到2100年每年中的月天数信息,
//阴历每月只能是29或30天,一年用12(或13)个二进制位表示,对应位为1表30天,否则为29天
WORD gLunarMonthDay[]=
{
      //测试数据只有1901.1.1 --2050.12.31
0X4ae0, 0Xa570, 0X5268, 0Xd260, 0Xd950, 0X6aa8, 0X56a0, 0X9ad0, 0X4ae8, 0X4ae0,   //1910
0Xa4d8, 0Xa4d0, 0Xd250, 0Xd548, 0Xb550, 0X56a0, 0X96d0, 0X95b0, 0X49b8, 0X49b0,   //1920
0Xa4b0, 0Xb258, 0X6a50, 0X6d40, 0Xada8, 0X2b60, 0X9570, 0X4978, 0X4970, 0X64b0,   //1930
0Xd4a0, 0Xea50, 0X6d48, 0X5ad0, 0X2b60, 0X9370, 0X92e0, 0Xc968, 0Xc950, 0Xd4a0,   //1940
0Xda50, 0Xb550, 0X56a0, 0Xaad8, 0X25d0, 0X92d0, 0Xc958, 0Xa950, 0Xb4a8, 0X6ca0,   //1950
0Xb550, 0X55a8, 0X4da0, 0Xa5b0, 0X52b8, 0X52b0, 0Xa950, 0Xe950, 0X6aa0, 0Xad50,   //1960
0Xab50, 0X4b60, 0Xa570, 0Xa570, 0X5260, 0Xe930, 0Xd950, 0X5aa8, 0X56a0, 0X96d0,   //1970
0X4ae8, 0X4ad0, 0Xa4d0, 0Xd268, 0Xd250, 0Xd528, 0Xb540, 0Xb6a0, 0X96d0, 0X95b0,   //1980
0X49b0, 0Xa4b8, 0Xa4b0, 0Xb258, 0X6a50, 0X6d40, 0Xada0, 0Xab60, 0X9370, 0X4978,   //1990
0X4970, 0X64b0, 0X6a50, 0Xea50, 0X6b28, 0X5ac0, 0Xab60, 0X9368, 0X92e0, 0Xc960,   //2000
0Xd4a8, 0Xd4a0, 0Xda50, 0X5aa8, 0X56a0, 0Xaad8, 0X25d0, 0X92d0, 0Xc958, 0Xa950,   //2010
0Xb4a0, 0Xb550, 0Xb550, 0X55a8, 0X4ba0, 0Xa5b0, 0X52b8, 0X52b0, 0Xa930, 0X74a8,   //2020
0X6aa0, 0Xad50, 0X4da8, 0X4b60, 0X9570, 0Xa4e0, 0Xd260, 0Xe930, 0Xd530, 0X5aa0,   //2030
0X6b50, 0X96d0, 0X4ae8, 0X4ad0, 0Xa4d0, 0Xd258, 0Xd250, 0Xd520, 0Xdaa0, 0Xb5a0,   //2040
0X56d0, 0X4ad8, 0X49b0, 0Xa4b8, 0Xa4b0, 0Xaa50, 0Xb528, 0X6d20, 0Xada0, 0X55b0,   //2050
   
};

//数组gLanarMonth存放阴历1901年到2050年闰月的月份,如没有则为0,每字节存两年
BYTEgLunarMonth[]=
{
      0X00, 0X50, 0X04, 0X00, 0X20,   //1910
      0X60, 0X05, 0X00, 0X20, 0X70,   //1920
      0X05, 0X00, 0X40, 0X02, 0X06,   //1930
      0X00, 0X50, 0X03, 0X07, 0X00,   //1940
      0X60, 0X04, 0X00, 0X20, 0X70,   //1950
      0X05, 0X00, 0X30, 0X80, 0X06,   //1960
      0X00, 0X40, 0X03, 0X07, 0X00,   //1970
      0X50, 0X04, 0X08, 0X00, 0X60,   //1980
      0X04, 0X0a, 0X00, 0X60, 0X05,   //1990
      0X00, 0X30, 0X80, 0X05, 0X00,   //2000
      0X40, 0X02, 0X07, 0X00, 0X50,   //2010
      0X04, 0X09, 0X00, 0X60, 0X04,   //2020
      0X00, 0X20, 0X60, 0X05, 0X00,   //2030
      0X30, 0Xb0, 0X06, 0X00, 0X50,   //2040
      0X02, 0X07, 0X00, 0X50, 0X03    //2050
};



BOOL IsLeapYear(WORD iYear) {return !(iYear%4)&&(iYear%100) || !(iYear%400);}


WORDMonthDays(WORD iYear, WORD iMonth)
{
      switch(iMonth)
      {
      case 1:case 3:case 5:case 7:case 8:case 10:case 12:
                return 31;
                break;
      case 4:case 6:case 9:case 11:
                return 30;
                break;
      case 2:
                //如果是闰年
                if(IsLeapYear(iYear))
                        return 29;
                else
                        return 28;
                break;
      }
      return 0;
}

WORDGetLeapMonth(WORD iLunarYear)
{
      BYTE &flag = gLunarMonth[(iLunarYear - START_YEAR)/2];
      return(iLunarYear - START_YEAR)%2 ? flag&0x0f : flag>>4;
}

LONGLunarMonthDays(WORD iLunarYear, WORD iLunarMonth)
{
      if(iLunarYear < START_YEAR)
                return 30L;

      WORD height =0 ,low =29;
      int iBit = 16 - iLunarMonth;

    if(iLunarMonth > GetLeapMonth(iLunarYear) && GetLeapMonth(iLunarYear))
                   iBit --;

      if(gLunarMonthDay & (1<<iBit))
                low ++;
            
      if(iLunarMonth == GetLeapMonth(iLunarYear))
                if(gLunarMonthDay & (1<< (iBit -1)))
                     height =30;
                else
                         height =29;

      return MAKELONG(low, height);
}

WORDLunarYearDays(WORD iLunarYear)
{
      /*
      WORD days=348 ; //12*29
      intmonth = 12 ;

      //如果iYear年有闰月,则为13个月
    if(gLanarMonth)
                month ++;
    //如果某月是三十天则days++
      while(month >=0 && (gLanarMonthDay & (1 << (16 - month))))
      {   
                days ++;
            month --;
      }
      return days;
      */
      WORD days =0;
      for(WORDi=1; i<=12; i++)
      {
      LONGtmp = LunarMonthDays(iLunarYear ,i);
                days += HIWORD(tmp);
                days += LOWORD(tmp);
      }
    return days;
}


// add by handong: 显示 生肖及 干支 纪年 :   pShX(兔(又名得到之兔))pGZhi 甲子
void FormatShengXiao(WORDiYear, char *pShX, char *pGZhi)
{      
      char szText1[]="甲乙丙丁戊己庚辛壬癸";
      char szText2[]="子丑寅卯辰巳午未申酉戌亥";
      char szText3[]="鼠牛虎免龙蛇马羊猴鸡狗猪";
      char szText4[]="屋上之鼠海内之牛山林之虎";
      memcpy(pGZhi,szText1+((iYear-4)%10)*2,2);
      memcpy(pGZhi+2,szText2+((iYear-4)%12)*2,2);
      pGZhi=0;
         
      memcpy(pShX,szText3+((iYear-4)%12)*2,2);
      strcpy(pShX+2,"(又名:)");
         
}         

voidl_CalcLunarDate(WORD &iYear, WORD &iMonth ,WORD &iDay, LONG iSpanDays)
{
      //阳历1901年2月19日为阴历1901年正月初一
      //阳历1901年1月1日到2月19日共有49天
      if(iSpanDays <49)
      {
                iYear= START_YEAR-1;
                if(iSpanDays <19)
                {
                  iMonth = 11;   
                  iDay   = 11+WORD(iSpanDays);
                }
                else
                {
                        iMonth = 12;
                        iDay   =WORD(iSpanDays) -18;
                }
                return ;
      }
      //下面从阴历1901年正月初一算起
      iSpanDays -=49;
    iYear= START_YEAR;
      iMonth = 1;
      iDay   = 1;
      //计算年
      LONG tmp = LunarYearDays(iYear);
      while(iSpanDays >= tmp)
      {
                iSpanDays -= tmp;
                tmp = LunarYearDays(++iYear);
      }
    //计算月
      tmp = LOWORD(LunarMonthDays(iYear, iMonth));
      while(iSpanDays >= tmp)
      {
                iSpanDays -= tmp;
            if(iMonth == GetLeapMonth(iYear))
                {
                        tmp= HIWORD(LunarMonthDays(iYear, iMonth));
                        if(iSpanDays < tmp)      
                              break;
                        iSpanDays -= tmp;
                }
                tmp = LOWORD(LunarMonthDays(iYear, ++iMonth));
      }
      //计算日
      iDay += WORD(iSpanDays);
}
LONGCalcDateDiff(WORD iEndYear, WORD iEndMonth, WORD iEndDay,
                                    WORDiStartYear, WORD iStartMonth, WORD iStartDay)
{
      WORD monthday[]={0, 31, 59 ,90, 120, 151, 181, 212, 243, 273, 304, 334};

      //计算两个年份1月1日之间相差的天数
      LONG iDiffDays =(iEndYear - iStartYear)*365;
      iDiffDays += (iEndYear-1)/4 - (iStartYear-1)/4;
      iDiffDays -= ((iEndYear-1)/100 - (iStartYear-1)/100);
      iDiffDays += (iEndYear-1)/400 - (iStartYear-1)/400;

    //加上iEndYear年1月1日到iEndMonth月iEndDay日之间的天数
    iDiffDays += monthday +
                                           (IsLeapYear(iEndYear)&&iEndMonth>2? 1: 0);
    iDiffDays += iEndDay;

      //减去iStartYear年1月1日到iStartMonth月iStartDay日之间的天数
      iDiffDays -= (monthday +
                                  (IsLeapYear(iStartYear)&&iStartMonth>2 ? 1: 0));
    iDiffDays -= iStartDay;      
      return iDiffDays;
}

void GetLunarDate(WORD iYear, WORD iMonth, WORD iDay,
                                     WORD &iLunarYear, WORD &iLunarMonth, WORD &iLunarDay)
{
   l_CalcLunarDate(iLunarYear, iLunarMonth, iLunarDay,
                                    CalcDateDiff(iYear, iMonth, iDay,1901,01,01));

}


//获取农历LunarY年LunarM月LunarD日公历日期(Y年M月D日)
void CovertLunarToSolar(WORD LunarY,WORD LunarM,WORD LunarD,WORD &Y,WORD &M,WORD &D)
{
      CTime TmpDate(LunarY,LunarM,LunarD,12,12,12);
      CTime Up,Down;
      CTimeSpan       InterveDate(60,0,0,0); //前后2个月天搜索
      CTimeSpan       OneDay(1,0,0,0);
      WORD Year, Mon, Day;
      WORD LunarYear,LunarMon,LunarDay;
         
      Up = TmpDate + InterveDate;
      Down = TmpDate - InterveDate;
         
      CTimeSpan Days=Up-Down;
         
      int Len = Days.GetDays();
      TmpDate=Down;
      for(int i=0; i<Len; i++)
      {
                TmpDate = TmpDate + OneDay;
                Year = TmpDate.GetYear(); Mon = TmpDate.GetMonth();Day = TmpDate.GetDay();
                GetLunarDate(Year, Mon, Day, LunarYear, LunarMon, LunarDay);
                if( (LunarYear==LunarY) && (LunarMon==LunarM) && (LunarDay==LunarD) )//found
                {
                        Y=Year; M=Mon; D=Day;
                        return;                                          
                }
      }

}
//格式化农历中的year
void FormatLunarYear(WORDiYear, char *pBuffer)
{      
      char szText1[]="甲乙丙丁戊己庚辛壬癸";
      char szText2[]="子丑寅卯辰巳午未申酉戌亥";
      char szText3[]="鼠牛虎免龙蛇马羊猴鸡狗猪";

      memcpy(pBuffer,szText1+((iYear-4)%10)*2,2);
      memcpy(pBuffer+2,szText2+((iYear-4)%12)*2,2);
      pBuffer=' ';
      memcpy(pBuffer+5,szText3+((iYear-4)%12)*2,2);
      strcpy(pBuffer+7,"年");
}
//格式化农历中的month
void FormatMonth(WORD iMonth, char *pBuffer, BOOL bLunar)
{
   if(!bLunar && iMonth==1)
   {
         strcpy(pBuffer, " 正月");
         return;
   }

   char szText[]="正二三四五六七八九十";
   if(iMonth<=10)
   {
         memcpy(pBuffer, " ", 2);
       memcpy(pBuffer+2, szText + (iMonth -1)*2, 2);
       strcpy(pBuffer+4 , "月");
         return;
   }
   if (iMonth == 11)
         strcpy(pBuffer, "冬月");
   else
         strcpy(pBuffer, "腊月");
    //strcpy(pBuffer+4 , "月");

   
}
//格式化农历中的day
void FormatLunarDay(WORDiDay, char *pBuffer)
{
    char szText1[]="初十廿三";
      char szText2[]="一二三四五六七八九十";
      if(iDay != 20 && iDay !=30)
      {
                memcpy(pBuffer, szText1 + (iDay-1)/10*2 ,2);
                memcpy(pBuffer+2, szText2 + ((iDay-1)%10)*2 ,2);
                pBuffer='\0';
      }
      else
      {
      memcpy(pBuffer, szText1 + iDay/10*2, 2);
                strcpy(pBuffer+2, szText2 +18);
      }
}


int main()
{
    WORD year,iyear;
    WORD month,imonth;
    WORD day,iday;
    char pybuffer={'\0'};
    char pmbuffer={'\0'};
    char pdbuffer={'\0'};
    GetLunarDate(2013,01,28,year,month,day);
    FormatLunarYear(year,pybuffer);
    FormatMonth(month,pmbuffer,true);
    FormatLunarDay(day,pdbuffer);
    printf("%s %s %s\n",pybuffer,pmbuffer,pdbuffer);
    CovertLunarToSolar(2012,12,17,iyear,imonth,iday);
    printf("%d %d %d\n",iyear,imonth,iday);
    return 0;
}
http://my.bccn.net/paste/487/

卓泰科技 发表于 2015-2-20 23:19:35

4)

    #include <time.h>
    #include <stdio.h>
    #include <string.h>
      
    unsigned int LunarCalendarDay;
    unsigned int LunarCalendarTable =
    {
      0x04AE53,0x0A5748,0x5526BD,0x0D2650,0x0D9544,0x46AAB9,0x056A4D,0x09AD42,0x24AEB6,0x04AE4A,/*1901-1910*/
      0x6A4DBE,0x0A4D52,0x0D2546,0x5D52BA,0x0B544E,0x0D6A43,0x296D37,0x095B4B,0x749BC1,0x049754,/*1911-1920*/
      0x0A4B48,0x5B25BC,0x06A550,0x06D445,0x4ADAB8,0x02B64D,0x095742,0x2497B7,0x04974A,0x664B3E,/*1921-1930*/
      0x0D4A51,0x0EA546,0x56D4BA,0x05AD4E,0x02B644,0x393738,0x092E4B,0x7C96BF,0x0C9553,0x0D4A48,/*1931-1940*/
      0x6DA53B,0x0B554F,0x056A45,0x4AADB9,0x025D4D,0x092D42,0x2C95B6,0x0A954A,0x7B4ABD,0x06CA51,/*1941-1950*/
      0x0B5546,0x555ABB,0x04DA4E,0x0A5B43,0x352BB8,0x052B4C,0x8A953F,0x0E9552,0x06AA48,0x6AD53C,/*1951-1960*/
      0x0AB54F,0x04B645,0x4A5739,0x0A574D,0x052642,0x3E9335,0x0D9549,0x75AABE,0x056A51,0x096D46,/*1961-1970*/
      0x54AEBB,0x04AD4F,0x0A4D43,0x4D26B7,0x0D254B,0x8D52BF,0x0B5452,0x0B6A47,0x696D3C,0x095B50,/*1971-1980*/
      0x049B45,0x4A4BB9,0x0A4B4D,0xAB25C2,0x06A554,0x06D449,0x6ADA3D,0x0AB651,0x093746,0x5497BB,/*1981-1990*/
      0x04974F,0x064B44,0x36A537,0x0EA54A,0x86B2BF,0x05AC53,0x0AB647,0x5936BC,0x092E50,0x0C9645,/*1991-2000*/
      0x4D4AB8,0x0D4A4C,0x0DA541,0x25AAB6,0x056A49,0x7AADBD,0x025D52,0x092D47,0x5C95BA,0x0A954E,/*2001-2010*/
      0x0B4A43,0x4B5537,0x0AD54A,0x955ABF,0x04BA53,0x0A5B48,0x652BBC,0x052B50,0x0A9345,0x474AB9,/*2011-2020*/
      0x06AA4C,0x0AD541,0x24DAB6,0x04B64A,0x69573D,0x0A4E51,0x0D2646,0x5E933A,0x0D534D,0x05AA43,/*2021-2030*/
      0x36B537,0x096D4B,0xB4AEBF,0x04AD53,0x0A4D48,0x6D25BC,0x0D254F,0x0D5244,0x5DAA38,0x0B5A4C,/*2031-2040*/
      0x056D41,0x24ADB6,0x049B4A,0x7A4BBE,0x0A4B51,0x0AA546,0x5B52BA,0x06D24E,0x0ADA42,0x355B37,/*2041-2050*/
      0x09374B,0x8497C1,0x049753,0x064B48,0x66A53C,0x0EA54F,0x06B244,0x4AB638,0x0AAE4C,0x092E42,/*2051-2060*/
      0x3C9735,0x0C9649,0x7D4ABD,0x0D4A51,0x0DA545,0x55AABA,0x056A4E,0x0A6D43,0x452EB7,0x052D4B,/*2061-2070*/
      0x8A95BF,0x0A9553,0x0B4A47,0x6B553B,0x0AD54F,0x055A45,0x4A5D38,0x0A5B4C,0x052B42,0x3A93B6,/*2071-2080*/
      0x069349,0x7729BD,0x06AA51,0x0AD546,0x54DABA,0x04B64E,0x0A5743,0x452738,0x0D264A,0x8E933E,/*2081-2090*/
      0x0D5252,0x0DAA47,0x66B53B,0x056D4F,0x04AE45,0x4A4EB9,0x0A4D4C,0x0D1541,0x2D92B5          /*2091-2099*/
    };
    int MonthAdd = {0,31,59,90,120,151,181,212,243,273,304,334};
    int LunarCalendar(int year,int month,int day)
    {
      int Spring_NY,Sun_NY,StaticDayCount;
      int index,flag;
      //Spring_NY 记录春节离当年元旦的天数。
      //Sun_NY 记录阳历日离当年元旦的天数。
      if ( ((LunarCalendarTable & 0x0060) >> 5) == 1)
            Spring_NY = (LunarCalendarTable & 0x001F) - 1;
      else
            Spring_NY = (LunarCalendarTable & 0x001F) - 1 + 31;
      Sun_NY = MonthAdd + day - 1;
      if ( (!(year % 4)) && (month > 2))
            Sun_NY++;
      //StaticDayCount记录大小月的天数 29 或30
      //index 记录从哪个月开始来计算。
      //flag 是用来对闰月的特殊处理。
      //判断阳历日在春节前还是春节后
      if (Sun_NY >= Spring_NY)//阳历日在春节后(含春节那天)
      {
            Sun_NY -= Spring_NY;
            month = 1;
            index = 1;
            flag = 0;
            if ( ( LunarCalendarTable & (0x80000 >> (index-1)) ) ==0)
                StaticDayCount = 29;
            else
                StaticDayCount = 30;
            while (Sun_NY >= StaticDayCount)
            {
                Sun_NY -= StaticDayCount;
                index++;
                if (month == ((LunarCalendarTable & 0xF00000) >> 20) )
                {
                  flag = ~flag;
                  if (flag == 0)
                        month++;
                }
                else
                  month++;
                if ( ( LunarCalendarTable & (0x80000 >> (index-1)) ) ==0)
                  StaticDayCount=29;
                else
                  StaticDayCount=30;
            }
            day = Sun_NY + 1;
      }
      else //阳历日在春节前
      {
            Spring_NY -= Sun_NY;
            year--;
            month = 12;
            if ( ((LunarCalendarTable & 0xF00000) >> 20) == 0)
                index = 12;
            else
                index = 13;
            flag = 0;
            if ( ( LunarCalendarTable & (0x80000 >> (index-1)) ) ==0)
                StaticDayCount = 29;
            else
                StaticDayCount = 30;
            while (Spring_NY > StaticDayCount)
            {
                Spring_NY -= StaticDayCount;
                index--;
                if (flag == 0)
                  month--;
                if (month == ((LunarCalendarTable & 0xF00000) >> 20))
                  flag = ~flag;
                if ( ( LunarCalendarTable & (0x80000 >> (index-1)) ) ==0)
                  StaticDayCount = 29;
                else
                  StaticDayCount = 30;
            }
            day = StaticDayCount - Spring_NY + 1;
      }
      LunarCalendarDay |= day;
      LunarCalendarDay |= (month << 6);
      if (month == ((LunarCalendarTable & 0xF00000) >> 20))
            return 1;
      else
            return 0;
    }
    main()
    {
      const char *ChDay[] = {"*","初一","初二","初三","初四","初五",
                               "初六","初七","初八","初九","初十",
                               "十一","十二","十三","十四","十五",
                               "十六","十七","十八","十九","二十",
                               "廿一","廿二","廿三","廿四","廿五",
                               "廿六","廿七","廿八","廿九","三十"
                              };
      const char *ChMonth[] = {"*","正","二","三","四","五","六","七","八","九","十","十一","腊"};
      struct tm * Local;
      long t;
      int year,month,day;
      char str = "";
    #if 0
      t = time(NULL);
      Local = localtime(&t);
      year = Local->tm_year + 1900;
      month = Local->tm_mon + 1;
      day = Local-> tm_mday;
    #else
      year = 2013;
      month = 2;
      day = 10;
      printf("请依次输入公历的年月日(例如2013年1月2日,输入:2013-1-2)");
      scanf("%d-%d-%d", &year, &month, &day);   
    #endif
      printf("%d年%d月%d日\t",year,month,day);
      if (LunarCalendar(year,month,day))
      {
            strcat(str,"闰");
            strcat(str,ChMonth[(LunarCalendarDay & 0x3C0) >> 6]);
      }
      else
            strcat(str,ChMonth[(LunarCalendarDay & 0x3C0) >> 6]);
      strcat(str,"月");
      strcat(str,ChDay);
      puts(str);
      getchar();
    }
http://blog.csdn.net/syrchina/article/details/8538516

页: [1] 2
查看完整版本: 【Joytag 小项目】智能小终端 (设想)