请选择 进入手机版 | 继续访问电脑版

狗趴(GodPub),开源硬件学习与实践

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 20749|回复: 13

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

[复制链接]

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
发表于 2015-2-17 23:00:21 | 显示全部楼层 |阅读模式
话说,一直想做这么个小东西。
主要功能用来显示时间。
既然都能显示时间了,那么加个闹钟功能貌似也不过分。
如果再加上星期、农历以及节气等,听起来似乎更加高大上。
然后如果加上天气预报显示,是不是会更加方便?
既然有预报了,那么要不要加个室内外温度度的实时数据呢?
然后.....

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

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

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

设置功能

  • 时间设定
  • 闹钟设定
  • 温湿度限定设置

报警功能
  • 闹钟报警
  • 温湿度超限报警


基本方案

显示部分:

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

设定部分:

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

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

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

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

其它:
待补充

天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

5

主题

36

帖子

141

积分

QQ群用户

积分
141
发表于 2015-2-17 23:48:06 | 显示全部楼层
一个1602不行,来2个如何?还不行就3个,反正i2C,屏多线少

4bed2e738bd4b31c9f175b3887d6277f9e2ff80e.jpg

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 2015-2-20 20:32:27 | 显示全部楼层
囧囧-科技大神粉 发表于 2015-2-17 23:48
一个1602不行,来2个如何?还不行就3个,反正i2C,屏多线少

买不起好多1602
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 2015-2-20 20:51:39 | 显示全部楼层
RTC

查了一下自己手头的器件

RTC模块有三款
  • DS1302
  • DS1307+AT24C32  I2C接口
  • 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


天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 2015-2-20 21:05:23 | 显示全部楼层
DS3231简单例子:

DS3231_TEST.ino
  1. /*
  2. DS3231_test.pde
  3. Eric Ayars
  4. 4/11

  5. Test/demo of read routines for a DS3231 RTC.

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

  8. */

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

  11. DS3231 Clock;
  12. bool Century=false;
  13. bool h12;
  14. bool PM;
  15. byte ADay, AHour, AMinute, ASecond, ABits;
  16. bool ADy, A12h, Apm;

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

  18. void setup() {
  19.         // Start the I2C interface
  20.         Wire.begin();
  21.         Clock.setSecond(50);//Set the second
  22.         Clock.setMinute(59);//Set the minute
  23.         Clock.setHour(11);  //Set the hour
  24.         Clock.setDoW(5);    //Set the day of the week
  25.         Clock.setDate(31);  //Set the date of the month
  26.         Clock.setMonth(5);  //Set the month of the year
  27.         Clock.setYear(13);  //Set the year (Last two digits of the year)
  28.         // Start the serial interface
  29.         Serial.begin(115200);
  30. }
  31. void ReadDS3231()
  32. {
  33.   int second,minute,hour,date,month,year,temperature;
  34.   second=Clock.getSecond();
  35.   minute=Clock.getMinute();
  36.   hour=Clock.getHour(h12, PM);
  37.   date=Clock.getDate();
  38.   month=Clock.getMonth(Century);
  39.   year=Clock.getYear();
  40.   
  41.   temperature=Clock.getTemperature();
  42.   
  43.   Serial.print("20");
  44.   Serial.print(year,DEC);
  45.   Serial.print('-');
  46.   Serial.print(month,DEC);
  47.   Serial.print('-');
  48.   Serial.print(date,DEC);
  49.   Serial.print(' ');
  50.   Serial.print(hour,DEC);
  51.   Serial.print(':');
  52.   Serial.print(minute,DEC);
  53.   Serial.print(':');
  54.   Serial.print(second,DEC);
  55.   Serial.print('\n');
  56.   Serial.print("Temperature=");
  57.   Serial.print(temperature);
  58.   Serial.print('\n');
  59. }
  60. void loop() {
  61.   ReadDS3231();
  62.   delay(1000);
  63. }
复制代码

AT24C32_TEST.ino
  1. #include <Wire.h> //I2C library

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

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

  21.   byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  22.     byte rdata = 0xFF;
  23.     Wire.beginTransmission(deviceaddress);
  24.     Wire.write((int)(eeaddress >> 8)); // MSB
  25.     Wire.write((int)(eeaddress & 0xFF)); // LSB
  26.     Wire.endTransmission();
  27.     Wire.requestFrom(deviceaddress,1);
  28.     if (Wire.available()) rdata = Wire.read();
  29.     return rdata;
  30.   }

  31.   // maybe let's not read more than 30 or 32 bytes at a time!
  32.   void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  33.     Wire.beginTransmission(deviceaddress);
  34.     Wire.write((int)(eeaddress >> 8)); // MSB
  35.     Wire.write((int)(eeaddress & 0xFF)); // LSB
  36.     Wire.endTransmission();
  37.     Wire.requestFrom(deviceaddress,length);
  38.     int c = 0;
  39.     for ( c = 0; c < length; c++ )
  40.       if (Wire.available()) buffer[c] = Wire.read();
  41.   }
  42.   void setup()
  43.   {
  44.     int addr=0,i;   
  45.     Wire.begin(); // initialise the connection
  46.     Serial.begin(9600);   
  47.     Serial.println("Write:");
  48.     for(i=0;i<26;i++)
  49.     {
  50.      i2c_eeprom_write_byte(0x57,addr,i+65);
  51.      addr++;
  52.      addr=addr%26;     
  53.      Serial.print(char(i+65));
  54.      delay(10); //add a small delay
  55.     }
  56.     Serial.print('\n');   
  57.   }

  58.   void loop()
  59.   {
  60.     int i,b;
  61.     int addr=0; //first address   
  62.     Serial.println("Read:");
  63.     for(i=0;i<26;i++)
  64.     {     
  65.       b = i2c_eeprom_read_byte(0x57, i); //access an address from the memory
  66.       Serial.print(char(b));  
  67.   }
  68.      Serial.print('\n');
  69.     delay(2000);
  70.   }
复制代码

Arduino库以及芯片资料:
DS3231 Arduino库: DS3231.zip (5.87 KB, 下载次数: 2)
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 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)


天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 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=0000  Current 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=1110  30 days in leap month of current year
D15~D12=1101  29 days in leap month of current year
*/
const unsigned int table[101] = {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[3]; //Save year(xx:20xx),month,day
  date_cvt( 9, 10, 6, &buff[0]);  //Only for example
}

天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 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[597]={
                    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[9]={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
code uint day_code2[3]={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[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);}
    }
}

/*
函数功能:输入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[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;        
    }
    // 计算当年春年离当年元旦的天数完成

    //计算公历日离当年元旦的天数,为了减少运算,用了两个表
    //day_code1[9],day_code2[3]
    //如果公历月在九月或前,天数会少于0xff,用表day_code1[9],
    //在九月后,天数大于0xff,用表day_code2[3]
    //如输入公历日为8月10日,则公历日离元旦天数为day_code1[8-1]+10-1
    //如输入公历日为11月10日,则公历日离元旦天数为day_code2[11-10]+10-1
    if (month<10){
        temp4=day_code1[month-1]+day-1;
    }
    else{
        temp4=day_code2[month-10]+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[table_addr]&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[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;
    }
    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[12]={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[month-1];
    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



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 2015-2-20 23:15:48 | 显示全部楼层
3)

  1. #include <stdio.h>
  2. #include <afx.h>
  3. #include <windows.h>

  4. const WORD START_YEAR =1901;
  5. const WORD END_YEAR   =2050;


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

  32. //数组gLanarMonth存放阴历1901年到2050年闰月的月份,如没有则为0,每字节存两年
  33. BYTE  gLunarMonth[]=
  34. {
  35.         0X00, 0X50, 0X04, 0X00, 0X20,   //1910
  36.         0X60, 0X05, 0X00, 0X20, 0X70,   //1920
  37.         0X05, 0X00, 0X40, 0X02, 0X06,   //1930
  38.         0X00, 0X50, 0X03, 0X07, 0X00,   //1940
  39.         0X60, 0X04, 0X00, 0X20, 0X70,   //1950
  40.         0X05, 0X00, 0X30, 0X80, 0X06,   //1960
  41.         0X00, 0X40, 0X03, 0X07, 0X00,   //1970
  42.         0X50, 0X04, 0X08, 0X00, 0X60,   //1980
  43.         0X04, 0X0a, 0X00, 0X60, 0X05,   //1990
  44.         0X00, 0X30, 0X80, 0X05, 0X00,   //2000
  45.         0X40, 0X02, 0X07, 0X00, 0X50,   //2010
  46.         0X04, 0X09, 0X00, 0X60, 0X04,   //2020
  47.         0X00, 0X20, 0X60, 0X05, 0X00,   //2030
  48.         0X30, 0Xb0, 0X06, 0X00, 0X50,   //2040
  49.         0X02, 0X07, 0X00, 0X50, 0X03    //2050
  50. };



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


  52. WORD  MonthDays(WORD iYear, WORD iMonth)
  53. {
  54.         switch(iMonth)
  55.         {
  56.         case 1:case 3:case 5:case 7:case 8:case 10:case 12:
  57.                 return 31;
  58.                 break;
  59.         case 4:case 6:case 9:case 11:
  60.                 return 30;
  61.                 break;
  62.         case 2:
  63.                 //如果是闰年
  64.                 if(IsLeapYear(iYear))
  65.                         return 29;
  66.                 else
  67.                         return 28;
  68.                 break;
  69.         }
  70.         return 0;
  71. }

  72. WORD  GetLeapMonth(WORD iLunarYear)
  73. {
  74.         BYTE &flag = gLunarMonth[(iLunarYear - START_YEAR)/2];
  75.         return  (iLunarYear - START_YEAR)%2 ? flag&0x0f : flag>>4;
  76. }

  77. LONG  LunarMonthDays(WORD iLunarYear, WORD iLunarMonth)
  78. {
  79.         if(iLunarYear < START_YEAR)  
  80.                 return 30L;

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

  83.     if(iLunarMonth > GetLeapMonth(iLunarYear) && GetLeapMonth(iLunarYear))
  84.                    iBit --;

  85.         if(gLunarMonthDay[iLunarYear - START_YEAR] & (1<<iBit))
  86.                 low ++;
  87.             
  88.         if(iLunarMonth == GetLeapMonth(iLunarYear))
  89.                 if(gLunarMonthDay[iLunarYear - START_YEAR] & (1<< (iBit -1)))
  90.                      height =30;
  91.                 else  
  92.                          height =29;

  93.         return MAKELONG(low, height);
  94. }

  95. WORD  LunarYearDays(WORD iLunarYear)
  96. {
  97.         /*
  98.         WORD days=348 ; //12*29
  99.         int  month = 12 ;

  100.         //如果iYear年有闰月,则为13个月
  101.     if(gLanarMonth[iYear - START_YEAR])  
  102.                 month ++;
  103.     //如果某月是三十天则days++
  104.         while(month >=0 && (gLanarMonthDay[iYear - START_YEAR] & (1 << (16 - month))))
  105.         {   
  106.                 days ++;  
  107.             month --;
  108.         }
  109.         return days;
  110.         */
  111.         WORD days =0;
  112.         for(WORD  i=1; i<=12; i++)
  113.         {  
  114.         LONG  tmp = LunarMonthDays(iLunarYear ,i);  
  115.                 days += HIWORD(tmp);
  116.                 days += LOWORD(tmp);
  117.         }
  118.     return days;
  119. }


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

  135. void  l_CalcLunarDate(WORD &iYear, WORD &iMonth ,WORD &iDay, LONG iSpanDays)
  136. {
  137.         //阳历1901年2月19日为阴历1901年正月初一
  138.         //阳历1901年1月1日到2月19日共有49天
  139.         if(iSpanDays <49)
  140.         {
  141.                 iYear  = START_YEAR-1;
  142.                 if(iSpanDays <19)
  143.                 {  
  144.                   iMonth = 11;   
  145.                   iDay   = 11+WORD(iSpanDays);
  146.                 }
  147.                 else
  148.                 {
  149.                         iMonth = 12;
  150.                         iDay   =  WORD(iSpanDays) -18;
  151.                 }
  152.                 return ;
  153.         }
  154.         //下面从阴历1901年正月初一算起
  155.         iSpanDays -=49;
  156.     iYear  = START_YEAR;
  157.         iMonth = 1;
  158.         iDay   = 1;
  159.         //计算年
  160.         LONG tmp = LunarYearDays(iYear);  
  161.         while(iSpanDays >= tmp)
  162.         {
  163.                 iSpanDays -= tmp;
  164.                 tmp = LunarYearDays(++iYear);
  165.         }
  166.     //计算月
  167.         tmp = LOWORD(LunarMonthDays(iYear, iMonth));
  168.         while(iSpanDays >= tmp)
  169.         {
  170.                 iSpanDays -= tmp;
  171.             if(iMonth == GetLeapMonth(iYear))
  172.                 {
  173.                         tmp  = HIWORD(LunarMonthDays(iYear, iMonth));
  174.                         if(iSpanDays < tmp)      
  175.                                 break;
  176.                         iSpanDays -= tmp;
  177.                 }
  178.                 tmp = LOWORD(LunarMonthDays(iYear, ++iMonth));
  179.         }
  180.         //计算日
  181.         iDay += WORD(iSpanDays);
  182. }
  183. LONG  CalcDateDiff(WORD iEndYear, WORD iEndMonth, WORD iEndDay,
  184.                                     WORD  iStartYear, WORD iStartMonth, WORD iStartDay)
  185. {
  186.         WORD monthday[]={0, 31, 59 ,90, 120, 151, 181, 212, 243, 273, 304, 334};  

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

  192.     //加上iEndYear年1月1日到iEndMonth月iEndDay日之间的天数
  193.     iDiffDays += monthday[iEndMonth-1] +
  194.                                            (IsLeapYear(iEndYear)&&iEndMonth>2? 1: 0);
  195.     iDiffDays += iEndDay;

  196.         //减去iStartYear年1月1日到iStartMonth月iStartDay日之间的天数
  197.         iDiffDays -= (monthday[iStartMonth-1] +  
  198.                                   (IsLeapYear(iStartYear)&&iStartMonth>2 ? 1: 0));
  199.     iDiffDays -= iStartDay;      
  200.         return iDiffDays;
  201. }

  202. void GetLunarDate(WORD iYear, WORD iMonth, WORD iDay,
  203.                                      WORD &iLunarYear, WORD &iLunarMonth, WORD &iLunarDay)
  204. {
  205.    l_CalcLunarDate(iLunarYear, iLunarMonth, iLunarDay,  
  206.                                       CalcDateDiff(iYear, iMonth, iDay,1901,01,01));

  207. }


  208. //获取农历LunarY年LunarM月LunarD日公历日期(Y年M月D日)
  209. void CovertLunarToSolar(WORD LunarY,WORD LunarM,WORD LunarD,WORD &Y,WORD &M,WORD &D)
  210. {
  211.         CTime TmpDate(LunarY,LunarM,LunarD,12,12,12);
  212.         CTime Up,Down;
  213.         CTimeSpan       InterveDate(60,0,0,0); //前后2个月天搜索
  214.         CTimeSpan       OneDay(1,0,0,0);
  215.         WORD Year, Mon, Day;
  216.         WORD LunarYear,LunarMon,LunarDay;
  217.          
  218.         Up = TmpDate + InterveDate;
  219.         Down = TmpDate - InterveDate;
  220.          
  221.         CTimeSpan Days=Up-Down;
  222.          
  223.         int Len = Days.GetDays();
  224.         TmpDate=Down;
  225.         for(int i=0; i<Len; i++)
  226.         {
  227.                 TmpDate = TmpDate + OneDay;
  228.                 Year = TmpDate.GetYear(); Mon = TmpDate.GetMonth();  Day = TmpDate.GetDay();
  229.                 GetLunarDate(Year, Mon, Day, LunarYear, LunarMon, LunarDay);
  230.                 if( (LunarYear==LunarY) && (LunarMon==LunarM) && (LunarDay==LunarD) )//found
  231.                 {
  232.                         Y=Year; M=Mon; D=Day;
  233.                         return;                                          
  234.                 }
  235.         }
  236.   
  237. }
  238. //格式化农历中的year
  239. void FormatLunarYear(WORD  iYear, char *pBuffer)
  240. {        
  241.         char szText1[]="甲乙丙丁戊己庚辛壬癸";
  242.         char szText2[]="子丑寅卯辰巳午未申酉戌亥";
  243.         char szText3[]="鼠牛虎免龙蛇马羊猴鸡狗猪";

  244.         memcpy(pBuffer,  szText1+((iYear-4)%10)*2,2);
  245.         memcpy(pBuffer+2,szText2+((iYear-4)%12)*2,2);
  246.         pBuffer[4]=' ';
  247.         memcpy(pBuffer+5,szText3+((iYear-4)%12)*2,2);
  248.         strcpy(pBuffer+7,"年");
  249. }
  250. //格式化农历中的month
  251. void FormatMonth(WORD iMonth, char *pBuffer, BOOL bLunar)
  252. {
  253.    if(!bLunar && iMonth==1)
  254.    {
  255.            strcpy(pBuffer, " 正月");
  256.            return;
  257.    }

  258.    char szText[]="正二三四五六七八九十";
  259.    if(iMonth<=10)
  260.    {
  261.            memcpy(pBuffer, " ", 2);
  262.        memcpy(pBuffer+2, szText + (iMonth -1)*2, 2);
  263.        strcpy(pBuffer+4 , "月");
  264.            return;
  265.    }
  266.    if (iMonth == 11)
  267.            strcpy(pBuffer, "冬月");
  268.    else
  269.            strcpy(pBuffer, "腊月");
  270.     //strcpy(pBuffer+4 , "月");

  271.    
  272. }
  273. //格式化农历中的day
  274. void FormatLunarDay(WORD  iDay, char *pBuffer)
  275. {
  276.     char szText1[]="初十廿三";
  277.         char szText2[]="一二三四五六七八九十";
  278.         if(iDay != 20 && iDay !=30)
  279.         {
  280.                 memcpy(pBuffer, szText1 + (iDay-1)/10*2 ,2);
  281.                 memcpy(pBuffer+2, szText2 + ((iDay-1)%10)*2 ,2);
  282.                 pBuffer[4]='\0';
  283.         }
  284.         else
  285.         {
  286.         memcpy(pBuffer, szText1 + iDay/10*2, 2);
  287.                 strcpy(pBuffer+2, szText2 +18);
  288.         }
  289. }


  290. int main()
  291. {
  292.     WORD year,iyear;
  293.     WORD month,imonth;
  294.     WORD day,iday;
  295.     char pybuffer[20]={'\0'};
  296.     char pmbuffer[20]={'\0'};
  297.     char pdbuffer[20]={'\0'};
  298.     GetLunarDate(2013,01,28,year,month,day);
  299.     FormatLunarYear(year,pybuffer);
  300.     FormatMonth(month,pmbuffer,true);
  301.     FormatLunarDay(day,pdbuffer);
  302.     printf("%s %s %s\n",pybuffer,pmbuffer,pdbuffer);
  303.     CovertLunarToSolar(2012,12,17,iyear,imonth,iday);
  304.     printf("%d %d %d\n",iyear,imonth,iday);
  305.     return 0;
  306. }
复制代码

http://my.bccn.net/paste/487/
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
 楼主| 发表于 2015-2-20 23:19:35 | 显示全部楼层
4)

  1.     #include <time.h>  
  2.     #include <stdio.h>  
  3.     #include <string.h>  
  4.       
  5.     unsigned int LunarCalendarDay;  
  6.     unsigned int LunarCalendarTable[199] =  
  7.     {  
  8.         0x04AE53,0x0A5748,0x5526BD,0x0D2650,0x0D9544,0x46AAB9,0x056A4D,0x09AD42,0x24AEB6,0x04AE4A,/*1901-1910*/  
  9.         0x6A4DBE,0x0A4D52,0x0D2546,0x5D52BA,0x0B544E,0x0D6A43,0x296D37,0x095B4B,0x749BC1,0x049754,/*1911-1920*/  
  10.         0x0A4B48,0x5B25BC,0x06A550,0x06D445,0x4ADAB8,0x02B64D,0x095742,0x2497B7,0x04974A,0x664B3E,/*1921-1930*/  
  11.         0x0D4A51,0x0EA546,0x56D4BA,0x05AD4E,0x02B644,0x393738,0x092E4B,0x7C96BF,0x0C9553,0x0D4A48,/*1931-1940*/  
  12.         0x6DA53B,0x0B554F,0x056A45,0x4AADB9,0x025D4D,0x092D42,0x2C95B6,0x0A954A,0x7B4ABD,0x06CA51,/*1941-1950*/  
  13.         0x0B5546,0x555ABB,0x04DA4E,0x0A5B43,0x352BB8,0x052B4C,0x8A953F,0x0E9552,0x06AA48,0x6AD53C,/*1951-1960*/  
  14.         0x0AB54F,0x04B645,0x4A5739,0x0A574D,0x052642,0x3E9335,0x0D9549,0x75AABE,0x056A51,0x096D46,/*1961-1970*/  
  15.         0x54AEBB,0x04AD4F,0x0A4D43,0x4D26B7,0x0D254B,0x8D52BF,0x0B5452,0x0B6A47,0x696D3C,0x095B50,/*1971-1980*/  
  16.         0x049B45,0x4A4BB9,0x0A4B4D,0xAB25C2,0x06A554,0x06D449,0x6ADA3D,0x0AB651,0x093746,0x5497BB,/*1981-1990*/  
  17.         0x04974F,0x064B44,0x36A537,0x0EA54A,0x86B2BF,0x05AC53,0x0AB647,0x5936BC,0x092E50,0x0C9645,/*1991-2000*/  
  18.         0x4D4AB8,0x0D4A4C,0x0DA541,0x25AAB6,0x056A49,0x7AADBD,0x025D52,0x092D47,0x5C95BA,0x0A954E,/*2001-2010*/  
  19.         0x0B4A43,0x4B5537,0x0AD54A,0x955ABF,0x04BA53,0x0A5B48,0x652BBC,0x052B50,0x0A9345,0x474AB9,/*2011-2020*/  
  20.         0x06AA4C,0x0AD541,0x24DAB6,0x04B64A,0x69573D,0x0A4E51,0x0D2646,0x5E933A,0x0D534D,0x05AA43,/*2021-2030*/  
  21.         0x36B537,0x096D4B,0xB4AEBF,0x04AD53,0x0A4D48,0x6D25BC,0x0D254F,0x0D5244,0x5DAA38,0x0B5A4C,/*2031-2040*/  
  22.         0x056D41,0x24ADB6,0x049B4A,0x7A4BBE,0x0A4B51,0x0AA546,0x5B52BA,0x06D24E,0x0ADA42,0x355B37,/*2041-2050*/  
  23.         0x09374B,0x8497C1,0x049753,0x064B48,0x66A53C,0x0EA54F,0x06B244,0x4AB638,0x0AAE4C,0x092E42,/*2051-2060*/  
  24.         0x3C9735,0x0C9649,0x7D4ABD,0x0D4A51,0x0DA545,0x55AABA,0x056A4E,0x0A6D43,0x452EB7,0x052D4B,/*2061-2070*/  
  25.         0x8A95BF,0x0A9553,0x0B4A47,0x6B553B,0x0AD54F,0x055A45,0x4A5D38,0x0A5B4C,0x052B42,0x3A93B6,/*2071-2080*/  
  26.         0x069349,0x7729BD,0x06AA51,0x0AD546,0x54DABA,0x04B64E,0x0A5743,0x452738,0x0D264A,0x8E933E,/*2081-2090*/  
  27.         0x0D5252,0x0DAA47,0x66B53B,0x056D4F,0x04AE45,0x4A4EB9,0x0A4D4C,0x0D1541,0x2D92B5          /*2091-2099*/  
  28.     };  
  29.     int MonthAdd[12] = {0,31,59,90,120,151,181,212,243,273,304,334};  
  30.     int LunarCalendar(int year,int month,int day)  
  31.     {  
  32.         int Spring_NY,Sun_NY,StaticDayCount;  
  33.         int index,flag;  
  34.         //Spring_NY 记录春节离当年元旦的天数。  
  35.         //Sun_NY 记录阳历日离当年元旦的天数。  
  36.         if ( ((LunarCalendarTable[year-1901] & 0x0060) >> 5) == 1)  
  37.             Spring_NY = (LunarCalendarTable[year-1901] & 0x001F) - 1;  
  38.         else  
  39.             Spring_NY = (LunarCalendarTable[year-1901] & 0x001F) - 1 + 31;  
  40.         Sun_NY = MonthAdd[month-1] + day - 1;  
  41.         if ( (!(year % 4)) && (month > 2))  
  42.             Sun_NY++;  
  43.         //StaticDayCount记录大小月的天数 29 或30  
  44.         //index 记录从哪个月开始来计算。  
  45.         //flag 是用来对闰月的特殊处理。  
  46.         //判断阳历日在春节前还是春节后  
  47.         if (Sun_NY >= Spring_NY)//阳历日在春节后(含春节那天)  
  48.         {  
  49.             Sun_NY -= Spring_NY;  
  50.             month = 1;  
  51.             index = 1;  
  52.             flag = 0;  
  53.             if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index-1)) ) ==0)  
  54.                 StaticDayCount = 29;  
  55.             else  
  56.                 StaticDayCount = 30;  
  57.             while (Sun_NY >= StaticDayCount)  
  58.             {  
  59.                 Sun_NY -= StaticDayCount;  
  60.                 index++;  
  61.                 if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20) )  
  62.                 {  
  63.                     flag = ~flag;  
  64.                     if (flag == 0)  
  65.                         month++;  
  66.                 }  
  67.                 else  
  68.                     month++;  
  69.                 if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index-1)) ) ==0)  
  70.                     StaticDayCount=29;  
  71.                 else  
  72.                     StaticDayCount=30;  
  73.             }  
  74.             day = Sun_NY + 1;  
  75.         }  
  76.         else //阳历日在春节前  
  77.         {  
  78.             Spring_NY -= Sun_NY;  
  79.             year--;  
  80.             month = 12;  
  81.             if ( ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20) == 0)  
  82.                 index = 12;  
  83.             else  
  84.                 index = 13;  
  85.             flag = 0;  
  86.             if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index-1)) ) ==0)  
  87.                 StaticDayCount = 29;  
  88.             else  
  89.                 StaticDayCount = 30;  
  90.             while (Spring_NY > StaticDayCount)  
  91.             {  
  92.                 Spring_NY -= StaticDayCount;  
  93.                 index--;  
  94.                 if (flag == 0)  
  95.                     month--;  
  96.                 if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20))  
  97.                     flag = ~flag;  
  98.                 if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index-1)) ) ==0)  
  99.                     StaticDayCount = 29;  
  100.                 else  
  101.                     StaticDayCount = 30;  
  102.             }  
  103.             day = StaticDayCount - Spring_NY + 1;  
  104.         }  
  105.         LunarCalendarDay |= day;  
  106.         LunarCalendarDay |= (month << 6);  
  107.         if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20))  
  108.             return 1;  
  109.         else  
  110.             return 0;  
  111.     }  
  112.     main()  
  113.     {  
  114.         const char *ChDay[] = {"*","初一","初二","初三","初四","初五",  
  115.                                "初六","初七","初八","初九","初十",  
  116.                                "十一","十二","十三","十四","十五",  
  117.                                "十六","十七","十八","十九","二十",  
  118.                                "廿一","廿二","廿三","廿四","廿五",  
  119.                                "廿六","廿七","廿八","廿九","三十"  
  120.                               };  
  121.         const char *ChMonth[] = {"*","正","二","三","四","五","六","七","八","九","十","十一","腊"};  
  122.         struct tm * Local;  
  123.         long t;  
  124.         int year,month,day;  
  125.         char str[13] = "";  
  126.     #if 0  
  127.         t = time(NULL);  
  128.         Local = localtime(&t);  
  129.         year = Local->tm_year + 1900;  
  130.         month = Local->tm_mon + 1;  
  131.         day = Local-> tm_mday;  
  132.     #else  
  133.         year = 2013;  
  134.         month = 2;  
  135.         day = 10;  
  136.         printf("请依次输入公历的年月日(例如2013年1月2日,输入:2013-1-2)");  
  137.         scanf("%d-%d-%d", &year, &month, &day);   
  138.     #endif  
  139.         printf("%d年%d月%d日\t",year,month,day);  
  140.         if (LunarCalendar(year,month,day))  
  141.         {  
  142.             strcat(str,"闰");  
  143.             strcat(str,ChMonth[(LunarCalendarDay & 0x3C0) >> 6]);  
  144.         }  
  145.         else  
  146.             strcat(str,ChMonth[(LunarCalendarDay & 0x3C0) >> 6]);  
  147.         strcat(str,"月");  
  148.         strcat(str,ChDay[LunarCalendarDay & 0x3F]);  
  149.         puts(str);  
  150.         getchar();  
  151.     }  
复制代码

http://blog.csdn.net/syrchina/article/details/8538516

天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|狗趴(GodPub) Arduino&Raspberry Pi开源硬件学习与实践[QQ群:20085629]  

GMT+8, 2024-3-29 13:17 , Processed in 0.058539 second(s), 38 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表