极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13189|回复: 3

求助:求Arduino的公历转换农历的程序

[复制链接]
发表于 2014-7-16 09:50:30 | 显示全部楼层 |阅读模式
最近在用DS3231和OLED显示模块做一个万年历,打算加入农历显示的功能.在网上找了很久都没有找到相关的Arduino程序.只好到论坛做一下伸手党了.
回复

使用道具 举报

发表于 2014-7-16 10:20:19 | 显示全部楼层
找一个网页代码的就好了嘛
JS的代码
原理都是一样的 找一个年份作为基点 然后计算NOW时间和基点时间的差值计算出农历。
这个很多网页设计里面都有。 由于是JS的 代码大同小异 改的部分不多。
还有个思路就是从网上读取时间。这样可以直接联系NTP 连DS3231都可以省了
好处就是准确而且自动对时(理论上只要NTP服务可用 千年都不会有超过1秒的误差),坏处就是断网就没法弄。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-17 02:10:04 | 显示全部楼层
darkorigin 发表于 2014-7-16 10:20
找一个网页代码的就好了嘛
JS的代码
原理都是一样的 找一个年份作为基点 然后计算NOW时间和基点时间的差值 ...

可是我的特长跟你一样啊……
特长->抄代码->COPY代码->改代码->
回复 支持 反对

使用道具 举报

发表于 2014-8-4 10:24:58 | 显示全部楼层
本帖最后由 hahle 于 2014-8-4 10:26 编辑

直接上源码了;
unsigned char  YearDataBase[99][3]=
{
    {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
    {0x35,0x5B,0x37},  //2050
    {0x09,0x37,0x4B},  //2051
    {0x84,0x97,0xC1},  //2052
    {0x04,0x97,0x53},  //2053
    {0x06,0x4B,0x48},  //2054
    {0x66,0xA5,0x3C},  //2055
    {0x0e,0xA5,0x4f},  //2056
    {0x06,0xB2,0x44},  //2057
    {0x4A,0xB6,0x38},  //2058
    {0x0A,0xAe,0x4C},  //2059
    {0x09,0x2e,0x42},  //2060
    {0x3C,0x97,0x35},  //2061
    {0x0C,0x96,0x49},  //2062
    {0x7d,0x4A,0xBd},  //2063
    {0x0d,0x4A,0x51},  //2064
    {0x0d,0xA5,0x45},  //2065
    {0x55,0xAA,0xBA},  //2066
    {0x05,0x6A,0x4e},  //2067
    {0x0A,0x6d,0x43},  //2068
    {0x45,0x2e,0xB7},  //2069
    {0x05,0x2d,0x4B},  //2070
    {0x8A,0x95,0xBf},  //2071
    {0x0A,0x95,0x53},  //2072
    {0x0B,0x4A,0x47},  //2073
    {0x6B,0x55,0x3B},  //2074
    {0x0A,0xd5,0x4f},  //2075
    {0x05,0x5A,0x45},  //2076
    {0x4A,0x5d,0x38},  //2077
    {0x0A,0x5B,0x4C},  //2078
    {0x05,0x2B,0x42},  //2079
    {0x3A,0x93,0xB6},  //2080
    {0x06,0x93,0x49},  //2081
    {0x77,0x29,0xBd},  //2082
    {0x06,0xAA,0x51},  //2083
    {0x0A,0xd5,0x46},  //2084
    {0x54,0xdA,0xBA},  //2085
    {0x04,0xB6,0x4e},  //2086
    {0x0A,0x57,0x43},  //2087
    {0x45,0x27,0x38},  //2088
    {0x0d,0x26,0x4A},  //2089
    {0x8e,0x93,0x3e},  //2090
    {0x0d,0x52,0x52},  //2091
    {0x0d,0xAA,0x47},  //2092
    {0x66,0xB5,0x3B},  //2093
    {0x05,0x6d,0x4f},  //2094
    {0x04,0xAe,0x45},  //2095
    {0x4A,0x4e,0xB9},  //2096
    {0x0A,0x4d,0x4C},  //2097
    {0x0d,0x15,0x41},  //2098
    {0x2d,0x92,0xB5},  //2099
};


uint16_t LunarYearNum=0,LunarMonNum=0,LunarDayNum=0;//转化回来的阴历数值就存在相应的变量中(全局的)

uint8_t  DayDataBase[12]={0,32,59,90,120,151,181,212,243,273,304,334};

/**********************************************************************************
  函 数 名:获取农历的大小月份
  入口参数:Mon: 当年的月份数(农历的0~13) YearOffsetAdd: 年份数据表里的偏移地址
  返 回 值:0:大月份(30天) 1:小月份(29天)
  说    明:大小月的获取主要是从年份数据表里三个字节的高13位当中获取 如果对应为是1则
            是大月30天,小月29天
************************************************************************************/

UINT8 Solar2Luner(UINT8 SolarYearNum,UINT8 SolarMonNum,UINT8 SolarDayNum)
{
        UINT8  LeapMonVal=0; //农历闰月天数值变量
    UINT8  NewYearToYuanDan_Mon=0,NewYearToYuanDan_Day=0; //定义春节所在的月份数(不是1月就是2月)
        UINT8  YearFlag=0,MonPointer=0; //农历年的缓存标志和月份的偏移量
    UINT8  temp=0; //春节距离元旦的天数
    UINT16 TarGetDayT0YuanDan=0,YearOffsetAdd=0; //目标日期到元旦天数和年数据表的偏移地址
   
    YearOffsetAdd=(SolarYearNum-1); //获取数据表地址  

    NewYearToYuanDan_Mon=(YearDataBase[YearOffsetAdd][2]&0x60)>>5; //计算春节所在的月份(不是1月就是2月)
    NewYearToYuanDan_Day=(YearDataBase[YearOffsetAdd][2]&0x1f);    //从年数据表里获取最后一个字节的第五位只要是计算春节到元旦的日期(Day的天数值)
       
        (NewYearToYuanDan_Mon==1)?(temp=NewYearToYuanDan_Day-1)temp=NewYearToYuanDan_Day+31-1); //temp这才是通过上面得到的春节所在的月份之后最终计算出来春节距离元旦的总天数

    TarGetDayT0YuanDan=DayDataBase[SolarMonNum-1]+SolarDayNum-1;//得到目标日期到元旦天数

    if ((SolarMonNum>2) && !(SolarYearNum%4))//如果是闰年则加目标天数1
      TarGetDayT0YuanDan+=1;

//==============================转化分两块(以春节作为转换中心) 目标日期距离春节前或者春节后=========================//

    if(TarGetDayT0YuanDan>=temp) //目标日期在春节之后
    {
        TarGetDayT0YuanDan-=temp;  //求2个天数的差值
        SolarMonNum=1;
        MonPointer=1; //这时目标值一定是在一月

        (GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30)LeapMonVal=29); //判断闰月的月份是大月还是小月
                       
                 while(TarGetDayT0YuanDan>=LeapMonVal) //目标日期大于等于闰月(大小月)天数
                 {  
                        TarGetDayT0YuanDan-=LeapMonVal;  
                        MonPointer+=1;
                       
                        (GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30)LeapMonVal=29);
                       
                        if(SolarMonNum==YearDataBase[YearOffsetAdd][0]>>4) //获取第一字节的高四位 (闰月月份的获取)
                        {
                                YearFlag=~YearFlag;
                                if(!YearFlag)
                                  SolarMonNum+=1;
                        }
                        else
                          SolarMonNum+=1;
                 }
      SolarDayNum=TarGetDayT0YuanDan+1; //最后农历日期天数的获取
        }
    else //目标日期在春节前
    {
       temp-=TarGetDayT0YuanDan;
       SolarYearNum-=1;
       YearOffsetAdd-=3;
       SolarMonNum=12;

       (YearDataBase[YearOffsetAdd][0]>>4)?(MonPointer=13)MonPointer=12);
          
           (GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30)LeapMonVal=29);

       while(temp>LeapMonVal)
       {
          temp-=LeapMonVal;
          MonPointer-=1;
          if(!YearFlag)
                         SolarMonNum-=1;
          if(SolarMonNum==NewYearToYuanDan_Day)
                         YearFlag=~YearFlag;

             (GetLunBig_LitMon(MonPointer,YearOffsetAdd))?(LeapMonVal=30)LeapMonVal=29);

       }
       SolarDayNum=LeapMonVal-temp+1; //最后农历日期天数的获取
     }   
    LunarYearNum=SolarYearNum;
    LunarMonNum =SolarMonNum;
    LunarDayNum =SolarDayNum;
   
    tft.setCursor(80,20);    此处开始调用显示
   // tft.print( LunarYearNum );
    // tft.print("-" );  
    tft.print( LunarMonNum );  
     tft.print("-" );  
    tft.print( LunarDayNum  );

  return (0);
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-14 20:56 , Processed in 0.038468 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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