数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 3117|回复: 39

[C51] 1901年~2099年公历转农历程序

[复制链接]
发表于 2024-10-22 12:50:37 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
本帖最后由 mmxx2015 于 2024-10-22 18:10 编辑

搜索公历转农历方法时,多数结果使用的是查表法,即预置N年的农历特征数据,然后根据这些特征数据把N年内其中任意一天的公历转换为农历。

其中,找到的这篇文章的程序比较容易看懂:
公农历转换和获取二十四节气算法

https://blog.csdn.net/qq_46041930/article/details/108653836
文章中还有转换农历二十四节气和星期日,以下程序没有包含这两段,需要的可以查看原文。


实际测试也发现一些问题:
(1)农历特征表格有6年的数据错误。
  1. 1960年 闰六月
  2. 错误数据:{0x7A, 0xD5, 0x3C},    /* 060-1960 */
  3. 正确数据:{0x6A, 0xD5, 0x3C},    /* 060-1960 */

  4. 1989年 六月大,七月小
  5. 错误数据:{0x09, 0x37, 0x46},    /* 089-1989 */
  6. 正确数据:{0x09, 0x57, 0x46},    /* 089-1989 */
  7. 0x937=1001,0011,0111
  8. 0x957=1001,0101,0111

  9. 2025年 闰六月 三月大,四月小
  10. 错误数据:{0x69, 0x57, 0x3D},    /* 125-2025 */
  11. 正确数据:{0x6A, 0x57, 0x3D},    /* 125-2025 */
  12. 0x957=1001,0101,0111
  13. 0x95A=1010,0101,0111

  14. 2057年 八月小,九月大
  15. 错误数据:{0x06, 0xB2, 0x44},    /* 157-2057 */
  16. 正确数据:{0x06, 0xAA, 0x44},    /* 157-2057 */
  17. 0x6B2=0110,1011,0010
  18. 0x6AA=0110,1010,1010

  19. 2089年 七月小,八月大
  20. 错误数据:{0x0D, 0x26, 0x4A},    /* 189-2089 */
  21. 正确数据:{0x0D, 0x16, 0x4A},    /* 189-2089 */
  22. 0xD26=1101,0010,0110
  23. 0xD16=1101,0001,0110

  24. 2097年  六月小,七月大
  25. 错误数据:{0x0A, 0x4D, 0x4C},    /* 197-2097 */
  26. 正确数据:{0x0A, 0x2D, 0x4C},    /* 197-2097 */
  27. 0xA4D=1010,0100,1101
  28. 0xA2D=1010,0010,1101
复制代码
(2)表格少1900年,无法转换1901年春节前的农历(需要上一年的农历数据)。
(3)有农历闰月的年份,常规月和闰月均记为闰月,比如2025年六月和闰六月均记为闰月。

一下程序修正了上述问题,添加更详细的注释,部分数据使用结构体使之更容易理解。
经过把公历1901.1.1~2099.12.31转成农历串口输出与从农历查询网http://cn.nongli.info/提取的数据对比,数据一致(顺便说一下,我从网上下载的一份“公历农历对照表 ExcelHome”表格中1960年闰七月是错误的,1960年是闰六月,这份文件可能来着 ExcelHome,可能新版已修正,但因为要注册才能下载,所以未验证)。


程序组成(可按需放在一个或多个文件中):

  1. //******************************************************************
  2. //        结构体/联合体声明
  3. //******************************************************************

  4. //农历特征数据结构体
  5. typedef struct
  6. {
  7.         union
  8.         {
  9.                 unsigned char        V8;

  10.                 struct
  11.                 {
  12.                         unsigned char        Month_1_4_Long_Short:4;                //字节0 bit[3:0],农历第1-4月的大小
  13.                         unsigned char        Leap_Month:4;                        //字节0 bit[7:4],闰月月份,0表示无闰月
  14.                 }Bits;
  15.         }Byte_0;

  16.         unsigned char        Month_5_12_Long_Short;                                //字节1,农历第5-12月大小

  17.         union
  18.         {
  19.                 unsigned char        V8;

  20.                 struct
  21.                 {
  22.                         unsigned char        Spring_Festival_Date:5;                //字节2 bit[4:0],春节的公历日期
  23.                         unsigned char        Spring_Festival_Month:2;        //字节2 bit[6:5],春节的公历月份
  24.                         unsigned char        Month_13_Long_Short:1;                //字节2 bit7,农历第13个月大小
  25.                 }Bits;
  26.         }Byte_2;
  27. }Lunar_Year_Code_Typedef;


  28. //公历转农历返回数据结构体
  29. typedef struct
  30. {
  31.         unsigned char        Month:5;                //月
  32.         unsigned char        IS_Leap_Month:1;        //闰月标志
  33.         unsigned char        Reserved_Bits:2;
  34.         unsigned char        Date:8;                        //日
  35. }Solar2Lunar_Typedef;
复制代码
  1. //位值
  2. #define        BIT0        0x01
  3. #define        BIT1        0x02
  4. #define        BIT2        0x04
  5. #define        BIT3        0x08
  6. #define        BIT4        0x10
  7. #define        BIT5        0x20
  8. #define        BIT6        0x40
  9. #define        BIT7        0x80

  10. #define        BIT8        0x0100
  11. #define        BIT9        0x0200
  12. #define        BIT10        0x0400
  13. #define        BIT11        0x0800
  14. #define        BIT12        0x1000
  15. #define        BIT13        0x2000
  16. #define        BIT14        0x4000
  17. #define        BIT15        0x8000
复制代码
  1. //******************************************************************
  2. //* 公历与农历转换年份数据存储数组
  3. //* 公历年对应的农历数据,每年三字节,
  4. //* 格式第一字节BIT7-4 位表示闰月月份,值为0为无闰月,BIT3-0对应农历第1-4月的大小
  5. //* 第二字节BIT7-0对应农历第5-12月大小,第三字节BIT7表示农历第13个月大小
  6. //* 月份对应的位为1表示本农历月大(30天),为0表示小(29天).
  7. //* 第三字节BIT6-5表示春节的公历月份,BIT4-0表示春节的公历日期
  8. //******************************************************************
  9. //农历特征数据表格(1900年~2099年)
  10. Lunar_Year_Code_Typedef code Lunar_Year_Code[200] =
  11. {
  12.         {0x84, 0xB6, 0xBF},        /* 000-1900 */
  13.         {0x04, 0xAE, 0x53},        /* 001-1901 */
  14.         {0x0A, 0x57, 0x48},        /* 002-1902 */
  15.         {0x55, 0x26, 0xBD},        /* 003-1903 */
  16.         {0x0D, 0x26, 0x50},        /* 004-1904 */
  17.         {0x0D, 0x95, 0x44},        /* 005-1905 */
  18.         {0x46, 0xAA, 0xB9},        /* 006-1906 */
  19.         {0x05, 0x6A, 0x4D},        /* 007-1907 */
  20.         {0x09, 0xAD, 0x42},        /* 008-1908 */
  21.         {0x24, 0xAE, 0xB6},        /* 009-1909 */
  22.         {0x04, 0xAE, 0x4A},        /* 010-1910 */
  23.         {0x6A, 0x4D, 0xBE},        /* 011-1911 */
  24.         {0x0A, 0x4D, 0x52},        /* 012-1912 */
  25.         {0x0D, 0x25, 0x46},        /* 013-1913 */
  26.         {0x5D, 0x52, 0xBA},        /* 014-1914 */
  27.         {0x0B, 0x54, 0x4E},        /* 015-1915 */
  28.         {0x0D, 0x6A, 0x43},        /* 016-1916 */
  29.         {0x29, 0x6D, 0x37},        /* 017-1917 */
  30.         {0x09, 0x5B, 0x4B},        /* 018-1918 */
  31.         {0x74, 0x9B, 0xC1},        /* 019-1919 */
  32.         {0x04, 0x97, 0x54},        /* 020-1920 */
  33.         {0x0A, 0x4B, 0x48},        /* 021-1921 */
  34.         {0x5B, 0x25, 0xBC},        /* 022-1922 */
  35.         {0x06, 0xA5, 0x50},        /* 023-1923 */
  36.         {0x06, 0xD4, 0x45},        /* 024-1924 */
  37.         {0x4A, 0xDA, 0xB8},        /* 025-1925 */
  38.         {0x02, 0xB6, 0x4D},        /* 026-1926 */
  39.         {0x09, 0x57, 0x42},        /* 027-1927 */
  40.         {0x24, 0x97, 0xB7},        /* 028-1928 */
  41.         {0x04, 0x97, 0x4A},        /* 029-1929 */
  42.         {0x66, 0x4B, 0x3E},        /* 030-1930 */
  43.         {0x0D, 0x4A, 0x51},        /* 031-1931 */
  44.         {0x0E, 0xA5, 0x46},        /* 032-1932 */
  45.         {0x56, 0xD4, 0xBA},        /* 033-1933 */
  46.         {0x05, 0xAD, 0x4E},        /* 034-1934 */
  47.         {0x02, 0xB6, 0x44},        /* 035-1935 */
  48.         {0x39, 0x37, 0x38},        /* 036-1936 */
  49.         {0x09, 0x2E, 0x4B},        /* 037-1937 */
  50.         {0x7C, 0x96, 0xBF},        /* 038-1938 */
  51.         {0x0C, 0x95, 0x53},        /* 039-1939 */
  52.         {0x0D, 0x4A, 0x48},        /* 040-1940 */
  53.         {0x6D, 0xA5, 0x3B},        /* 041-1941 */
  54.         {0x0B, 0x55, 0x4F},        /* 042-1942 */
  55.         {0x05, 0x6A, 0x45},        /* 043-1943 */
  56.         {0x4A, 0xAD, 0xB9},        /* 044-1944 */
  57.         {0x02, 0x5D, 0x4D},        /* 045-1945 */
  58.         {0x09, 0x2D, 0x42},        /* 046-1946 */
  59.         {0x2C, 0x95, 0xB6},        /* 047-1947 */
  60.         {0x0A, 0x95, 0x4A},        /* 048-1948 */
  61.         {0x7B, 0x4A, 0xBD},        /* 049-1949 */
  62.         {0x06, 0xCA, 0x51},        /* 050-1950 */
  63.         {0x0B, 0x55, 0x46},        /* 051-1951 */
  64.         {0x55, 0x5A, 0xBB},        /* 052-1952 */
  65.         {0x04, 0xDA, 0x4E},        /* 053-1953 */
  66.         {0x0A, 0x5B, 0x43},        /* 054-1954 */
  67.         {0x35, 0x2B, 0xB8},        /* 055-1955 */
  68.         {0x05, 0x2B, 0x4C},        /* 056-1956 */
  69.         {0x8A, 0x95, 0x3F},        /* 057-1957 */
  70.         {0x0E, 0x95, 0x52},        /* 058-1958 */
  71.         {0x06, 0xAA, 0x48},        /* 059-1959 */
  72.         {0x6A, 0xD5, 0x3C},        /* 060-1960 */
  73.         {0x0A, 0xB5, 0x4F},        /* 061-1961 */
  74.         {0x04, 0xB6, 0x45},        /* 062-1962 */
  75.         {0x4A, 0x57, 0x39},        /* 063-1963 */
  76.         {0x0A, 0x57, 0x4D},        /* 064-1964 */
  77.         {0x05, 0x26, 0x42},        /* 065-1965 */
  78.         {0x3E, 0x93, 0x35},        /* 066-1966 */
  79.         {0x0D, 0x95, 0x49},        /* 067-1967 */
  80.         {0x75, 0xAA, 0xBE},        /* 068-1968 */
  81.         {0x05, 0x6A, 0x51},        /* 069-1969 */
  82.         {0x09, 0x6D, 0x46},        /* 070-1970 */
  83.         {0x54, 0xAE, 0xBB},        /* 071-1971 */
  84.         {0x04, 0xAD, 0x4F},        /* 072-1972 */
  85.         {0x0A, 0x4D, 0x43},        /* 073-1973 */
  86.         {0x4D, 0x26, 0xB7},        /* 074-1974 */
  87.         {0x0D, 0x25, 0x4B},        /* 075-1975 */
  88.         {0x8D, 0x52, 0xBF},        /* 076-1976 */
  89.         {0x0B, 0x54, 0x52},        /* 077-1977 */
  90.         {0x0B, 0x6A, 0x47},        /* 078-1978 */
  91.         {0x69, 0x6D, 0x3C},        /* 079-1979 */
  92.         {0x09, 0x5B, 0x50},        /* 080-1980 */
  93.         {0x04, 0x9B, 0x45},        /* 081-1981 */
  94.         {0x4A, 0x4B, 0xB9},        /* 082-1982 */
  95.         {0x0A, 0x4B, 0x4D},        /* 083-1983 */
  96.         {0xAB, 0x25, 0xC2},        /* 084-1984 */
  97.         {0x06, 0xA5, 0x54},        /* 085-1985 */
  98.         {0x06, 0xD4, 0x49},        /* 086-1986 */
  99.         {0x6A, 0xDA, 0x3D},        /* 087-1987 */
  100.         {0x0A, 0xB6, 0x51},        /* 088-1988 */
  101.         {0x09, 0x57, 0x46},        /* 089-1989 */
  102.         {0x54, 0x97, 0xBB},        /* 090-1990 */
  103.         {0x04, 0x97, 0x4F},        /* 091-1991 */
  104.         {0x06, 0x4B, 0x44},        /* 092-1992 */
  105.         {0x36, 0xA5, 0x37},        /* 093-1993 */
  106.         {0x0E, 0xA5, 0x4A},        /* 094-1994 */
  107.         {0x86, 0xB2, 0xBF},        /* 095-1995 */
  108.         {0x05, 0xAC, 0x53},        /* 096-1996 */
  109.         {0x0A, 0xB6, 0x47},        /* 097-1997 */
  110.         {0x59, 0x36, 0xBC},        /* 098-1998 */
  111.         {0x09, 0x2E, 0x50},        /* 099-1999 */
  112.         {0x0C, 0x96, 0x45},        /* 100-2000 */
  113.         {0x4D, 0x4A, 0xB8},        /* 101-2001 */
  114.         {0x0D, 0x4A, 0x4C},        /* 102-2002 */
  115.         {0x0D, 0xA5, 0x41},        /* 103-2003 */
  116.         {0x25, 0xAA, 0xB6},        /* 104-2004 */
  117.         {0x05, 0x6A, 0x49},        /* 105-2005 */
  118.         {0x7A, 0xAD, 0xBD},        /* 106-2006 */
  119.         {0x02, 0x5D, 0x52},        /* 107-2007 */
  120.         {0x09, 0x2D, 0x47},        /* 108-2008 */
  121.         {0x5C, 0x95, 0xBA},        /* 109-2009 */
  122.         {0x0A, 0x95, 0x4E},        /* 110-2010 */
  123.         {0x0B, 0x4A, 0x43},        /* 111-2011 */
  124.         {0x4B, 0x55, 0x37},        /* 112-2012 */
  125.         {0x0A, 0xD5, 0x4A},        /* 113-2013 */
  126.         {0x95, 0x5A, 0xBF},        /* 114-2014 */
  127.         {0x04, 0xBA, 0x53},        /* 115-2015 */
  128.         {0x0A, 0x5B, 0x48},        /* 116-2016 */
  129.         {0x65, 0x2B, 0xBC},        /* 117-2017 */
  130.         {0x05, 0x2B, 0x50},        /* 118-2018 */
  131.         {0x0A, 0x93, 0x45},        /* 119-2019 */
  132.         {0x47, 0x4A, 0xB9},        /* 120-2020 */
  133.         {0x06, 0xAA, 0x4C},        /* 121-2021 */
  134.         {0x0A, 0xD5, 0x41},        /* 122-2022 */
  135.         {0x24, 0xDA, 0xB6},        /* 123-2023 */
  136.         {0x04, 0xB6, 0x4A},        /* 124-2024 */
  137.         {0x6A, 0x57, 0x3D},        /* 125-2025 */
  138.         {0x0A, 0x4E, 0x51},        /* 126-2026 */
  139.         {0x0D, 0x26, 0x46},        /* 127-2027 */
  140.         {0x5E, 0x93, 0x3A},        /* 128-2028 */
  141.         {0x0D, 0x53, 0x4D},        /* 129-2029 */
  142.         {0x05, 0xAA, 0x43},        /* 130-2030 */
  143.         {0x36, 0xB5, 0x37},        /* 131-2031 */
  144.         {0x09, 0x6D, 0x4B},        /* 132-2032 */
  145.         {0xB4, 0xAE, 0xBF},        /* 133-2033 */
  146.         {0x04, 0xAD, 0x53},        /* 134-2034 */
  147.         {0x0A, 0x4D, 0x48},        /* 135-2035 */
  148.         {0x6D, 0x25, 0xBC},        /* 136-2036 */
  149.         {0x0D, 0x25, 0x4F},        /* 137-2037 */
  150.         {0x0D, 0x52, 0x44},        /* 138-2038 */
  151.         {0x5D, 0xAA, 0x38},        /* 139-2039 */
  152.         {0x0B, 0x5A, 0x4C},        /* 140-2040 */
  153.         {0x05, 0x6D, 0x41},        /* 141-2041 */
  154.         {0x24, 0xAD, 0xB6},        /* 142-2042 */
  155.         {0x04, 0x9B, 0x4A},        /* 143-2043 */
  156.         {0x7A, 0x4B, 0xBE},        /* 144-2044 */
  157.         {0x0A, 0x4B, 0x51},        /* 145-2045 */
  158.         {0x0A, 0xA5, 0x46},        /* 146-2046 */
  159.         {0x5B, 0x52, 0xBA},        /* 147-2047 */
  160.         {0x06, 0xD2, 0x4E},        /* 148-2048 */
  161.         {0x0A, 0xDA, 0x42},        /* 149-2049 */
  162.         {0x35, 0x5B, 0x37},        /* 150-2050 */
  163.         {0x09, 0x37, 0x4B},        /* 151-2051 */
  164.         {0x84, 0x97, 0xC1},        /* 152-2052 */
  165.         {0x04, 0x97, 0x53},        /* 153-2053 */
  166.         {0x06, 0x4B, 0x48},        /* 154-2054 */
  167.         {0x66, 0xA5, 0x3C},        /* 155-2055 */
  168.         {0x0E, 0xA5, 0x4F},        /* 156-2056 */
  169.         {0x06, 0xAA, 0x44},        /* 157-2057 */
  170.         {0x4A, 0xB6, 0x38},        /* 158-2058 */
  171.         {0x0A, 0xAE, 0x4C},        /* 159-2059 */
  172.         {0x09, 0x2E, 0x42},        /* 160-2060 */
  173.         {0x3C, 0x97, 0x35},        /* 161-2061 */
  174.         {0x0C, 0x96, 0x49},        /* 162-2062 */
  175.         {0x7D, 0x4A, 0xBD},        /* 163-2063 */
  176.         {0x0D, 0x4A, 0x51},        /* 164-2064 */
  177.         {0x0D, 0xA5, 0x45},        /* 165-2065 */
  178.         {0x55, 0xAA, 0xBA},        /* 166-2066 */
  179.         {0x05, 0x6A, 0x4E},        /* 167-2067 */
  180.         {0x0A, 0x6D, 0x43},        /* 168-2068 */
  181.         {0x45, 0x2E, 0xB7},        /* 169-2069 */
  182.         {0x05, 0x2D, 0x4B},        /* 170-2070 */
  183.         {0x8A, 0x95, 0xBF},        /* 171-2071 */
  184.         {0x0A, 0x95, 0x53},        /* 172-2072 */
  185.         {0x0B, 0x4A, 0x47},        /* 173-2073 */
  186.         {0x6B, 0x55, 0x3B},        /* 174-2074 */
  187.         {0x0A, 0xD5, 0x4F},        /* 175-2075 */
  188.         {0x05, 0x5A, 0x45},        /* 176-2076 */
  189.         {0x4A, 0x5D, 0x38},        /* 177-2077 */
  190.         {0x0A, 0x5B, 0x4C},        /* 178-2078 */
  191.         {0x05, 0x2B, 0x42},        /* 179-2079 */
  192.         {0x3A, 0x93, 0xB6},        /* 180-2080 */
  193.         {0x06, 0x93, 0x49},        /* 181-2081 */
  194.         {0x77, 0x29, 0xBD},        /* 182-2082 */
  195.         {0x06, 0xAA, 0x51},        /* 183-2083 */
  196.         {0x0A, 0xD5, 0x46},        /* 184-2084 */
  197.         {0x54, 0xDA, 0xBA},        /* 185-2085 */
  198.         {0x04, 0xB6, 0x4E},        /* 186-2086 */
  199.         {0x0A, 0x57, 0x43},        /* 187-2087 */
  200.         {0x45, 0x27, 0x38},        /* 188-2088 */
  201.         {0x0D, 0x16, 0x4A},        /* 189-2089 */
  202.         {0x8E, 0x93, 0x3E},        /* 190-2090 */
  203.         {0x0D, 0x52, 0x52},        /* 191-2091 */
  204.         {0x0D, 0xAA, 0x47},        /* 192-2092 */
  205.         {0x66, 0xB5, 0x3B},        /* 193-2093 */
  206.         {0x05, 0x6D, 0x4F},        /* 194-2094 */
  207.         {0x04, 0xAE, 0x45},        /* 195-2095 */
  208.         {0x4A, 0x4E, 0xB9},        /* 196-2096 */
  209.         {0x0A, 0x2D, 0x4C},        /* 197-2097 */
  210.         {0x0D, 0x15, 0x41},        /* 198-2098 */
  211.         {0x2D, 0x92, 0xB5},        /* 199-2099 */
  212. };


  213. //公历前n月总天数
  214. unsigned int code Days_Code[13] =
  215. {
  216.         0,        //0
  217.         0,        //1,1月:当月
  218.         31,        //2,1月:31
  219.         59,        //3,1~2月:31+28=59
  220.         90,        //4,1~3月:31+28+31=90
  221.         120,        //5,1~4月:31+28+31+30=120
  222.         151,        //6,1~5月:31+28+31+30+31=151
  223.         181,        //7,1~6月:31+28+31+30+31+30=181
  224.         212,        //8,1~7月:31+28+31+30+31+30+31=212
  225.         243,        //9,1~8月:31+28+31+30+31+30+31+31=243
  226.         273,        //10,1~9月:31+28+31+30+31+30+31+31+30=273
  227.         304,        //11,1~10月:31+28+31+30+31+30+31+31+30+31=304
  228.         334,        //12,1~11月:31+28+31+30+31+30+31+31+30+31+30=334
  229. };


  230. //农历大小月特征位编码
  231. unsigned char code Month_Long_Short_Bit_Table[14] =
  232. {
  233.         0x00,                //0
  234.         BIT3,                //1,1月
  235.         BIT2,                //2,2月
  236.         BIT1,                //3,3月
  237.         BIT0,                //4,4月
  238.         BIT7,                //5,5月
  239.         BIT6,                //6,6月
  240.         BIT5,                //7,7月
  241.         BIT4,                //8,8月
  242.         BIT3,                //9,9月
  243.         BIT2,                //10,10月
  244.         BIT1,                //11,11月
  245.         BIT0,                //12,12月
  246.         BIT7,                //13,13月
  247. };
复制代码
  1. //******************************************************************
  2. //函数名称:unsigned char Get_Lunar_Month_Days(unsigned char Lunar_Month, unsigned int Offset)
  3. //函数功能:用于读取数据表中农历月的大月或小月
  4. //输入参数:Lunar_Month,Offset
  5. //返回值:  0/1(1:大月;0:小月)
  6. //******************************************************************
  7. unsigned char Get_Lunar_Month_Days(unsigned char Lunar_Month, unsigned int Offset)
  8. {
  9.         unsigned char        Month_Long_Short;        //大小月


  10.         Month_Long_Short = 0;        //无效数据返回小月

  11.         if(Lunar_Month <= Ubound(Month_Long_Short_Bit_Table))
  12.         {
  13.                 if(Lunar_Month <= 4)        //农历参数表格第0字节bit[3:0]表示农历第1-4月的大小
  14.                 {
  15.                         Month_Long_Short = (Lunar_Year_Code[Offset].Byte_0.Bits.Month_1_4_Long_Short & Month_Long_Short_Bit_Table[Lunar_Month]);
  16.                 }
  17.                 else if(Lunar_Month <= 12)        //农历参数表格第1字节bit[7:0]表示农历第5-12月的大小
  18.                 {
  19.                         Month_Long_Short = (Lunar_Year_Code[Offset].Month_5_12_Long_Short & Month_Long_Short_Bit_Table[Lunar_Month]);
  20.                 }
  21.                 else        //农历第13个月大小
  22.                 {
  23.                         Month_Long_Short = Lunar_Year_Code[Offset].Byte_2.Bits.Month_13_Long_Short;
  24.                 }
  25.         }

  26.         if(Month_Long_Short)
  27.         {
  28.                 Month_Long_Short = 1;
  29.         }

  30.         return Month_Long_Short;
  31. }
复制代码
  1. //******************************************************************
  2. //函数名称:Solar2Lunar_Typedef Get_China_Calendar(unsigned int Year,unsigned char Month,unsigned char Day)
  3. //函数功能:公农历转换
  4. //输入参数:Year:公历年(只允许1901-2099年)  Month:公历月  Day:公历日
  5. //返回值:  0/1 1对应转换成功,0对应转换失败
  6. //******************************************************************
  7. #define        C_SOLAR_YEAR_MIN        1901                        //公历年最小值
  8. #define        C_SOLAR_YEAR_MAX        2099                        //公历年最大值

  9. Solar2Lunar_Typedef Get_China_Calendar(unsigned int Year,unsigned char Month,unsigned char Day)
  10. {
  11.         unsigned char        Spring_Festival_Month;                //当年春节所在的公历月份
  12.         unsigned char        Spring_Festival_Date;                //当年春节所在的公历日
  13.         unsigned char        Leap_Month_Flag;                //闰月,农历月不+1
  14.         unsigned char        Lunar_Month;                        //农历月
  15.         unsigned char        Lunar_Month_Temp;                //农历月(尝试判断月份)
  16.         unsigned char        Lunar_Month_Save;                //农历月保存(用于判断是不是闰月)
  17.         unsigned char        Lunar_Date;                        //农历日
  18.         unsigned char        Lunar_Leap_Month;                //闰月
  19.         unsigned char        Lunar_Month_Days;                //农历月天数
  20.         unsigned char        Spring_Festival_Days;                //当年春年离当年元旦的天数
  21.         unsigned int        Days_After_New_Years_Day;        //公历日离当年元旦的天数
  22.         unsigned int        Days_Differ;                        //两个日期天数差
  23.         unsigned int        Table_Offset;                        //农历特征数据表格查表偏移量
  24.         Solar2Lunar_Typedef Return_Value;        //返回值


  25.         Return_Value.Month = 0;                //月
  26.         Return_Value.IS_Leap_Month = 0;        //闰月标志
  27.         Return_Value.Reserved_Bits = 0;
  28.         Return_Value.Date = 0;                //日

  29.         if((Year >= C_SOLAR_YEAR_MIN) && (Year <= C_SOLAR_YEAR_MAX))        //1901~2099年之外不处理
  30.         {
  31.                 Lunar_Month_Save=0;                //农历月保存(用于判断是不是闰月)
  32.         
  33.                 /* 定位数据表地址 */
  34.                 Table_Offset = (Year - 1900);        //农历特征数据从1900年开始,但只能转换1901年之后的数据,转换春节前的数据需要前一年的数据
  35.         
  36.                 /* 取当年春节所在的公历月份 */
  37.                 Spring_Festival_Month = Lunar_Year_Code[Table_Offset].Byte_2.Bits.Spring_Festival_Month;
  38.         
  39.                 /* 取当年春节所在的公历日 */
  40.                 Spring_Festival_Date = Lunar_Year_Code[Table_Offset].Byte_2.Bits.Spring_Festival_Date;
  41.         
  42.                 /* 计算当年春年离当年元旦的天数,春节只会在公历1月或2月 */
  43.                 if ( Spring_Festival_Month == 1 )
  44.                 {
  45.                         Spring_Festival_Days = Spring_Festival_Date - 1;
  46.                 }
  47.                 else
  48.                 {
  49.                         Spring_Festival_Days = Spring_Festival_Date + 31 - 1;
  50.                 }
  51.         
  52.                 /* 计算公历日离当年元旦的天数 */
  53.                 Days_After_New_Years_Day = Days_Code[Month] + Day - 1;
  54.         
  55.                 /* 如果公历月大于2月并且该年的2月为闰月,天数加1 */
  56.                 if (Month > 2)
  57.                 {
  58.                         if((Year % 100) == 0)        //能被100整除
  59.                         {
  60.                                 if((Year % 400) == 0)        //能被400整除--闰年
  61.                                 {
  62.                                         Days_After_New_Years_Day ++;
  63.                                 }
  64.                         }
  65.                         else if (Year % 4 == 0)        //不能被100整除,能被4整除--闰年
  66.                         {
  67.                                 Days_After_New_Years_Day ++;
  68.                         }
  69.                 }
  70.         
  71.                 /* 判断公历日在春节前还是春节后 */
  72.                 if(Days_After_New_Years_Day >= Spring_Festival_Days)        //当前公历日在春节后
  73.                 {
  74.                         Days_Differ = (Days_After_New_Years_Day - Spring_Festival_Days);        //Days_Differ存放当前公历日距离当前春节公历日天数
  75.                         
  76.                         Lunar_Month = 1;                //农历月
  77.                         Lunar_Month_Temp = 1;                //农历月,从1月开始判断(第一个月不会是闰月,直接农历正月天数)
  78.                         Leap_Month_Flag = 0;                //闰月,农历月不+1
  79.         
  80.                         if(Get_Lunar_Month_Days(Lunar_Month_Temp, Table_Offset) == 0)        //农历月天数
  81.                         {
  82.                                 Lunar_Month_Days = 29;        /* 小月29天 */
  83.                         }
  84.                         else
  85.                         {
  86.                                 Lunar_Month_Days = 30;        /* 大月30天 */
  87.                         }
  88.         
  89.                         /* 从数据表中取该年的闰月月份,如为0则该年无闰月 */
  90.                         Lunar_Leap_Month = Lunar_Year_Code[Table_Offset].Byte_0.Bits.Leap_Month;
  91.         
  92.                         while(Days_Differ >= Lunar_Month_Days)        //天数差>=当前处理农历月天数
  93.                         {
  94.                                 Days_Differ -= Lunar_Month_Days;
  95.                                 
  96.                                 if(Lunar_Month == Lunar_Leap_Month)        //农历月=当年农历闰月
  97.                                 {
  98.                                         Leap_Month_Flag = (~Leap_Month_Flag);        //闰月标志
  99.                                        
  100.                                         if (Leap_Month_Flag == 0)
  101.                                         {
  102.                                                 Lunar_Month ++;        //闰月之后的下一个月
  103.                                         }
  104.                                         else
  105.                                         {
  106.                                                 Lunar_Month_Save = Lunar_Month;        //农历月保存(用于判断是不是闰月)
  107.                                         }
  108.                                 }
  109.                                 else
  110.                                 {
  111.                                         Lunar_Month ++;                //下一个月
  112.                                 }
  113.                                 
  114.                                 Lunar_Month_Temp ++;
  115.         
  116.                                 if(Get_Lunar_Month_Days(Lunar_Month_Temp, Table_Offset) == 0)
  117.                                 {
  118.                                         Lunar_Month_Days = 29;
  119.                                 }
  120.                                 else
  121.                                 {
  122.                                         Lunar_Month_Days = 30;
  123.                                 }
  124.                         }
  125.         
  126.                         Lunar_Date = (Days_Differ + 1);                //农历日
  127.                 }
  128.                 else        /* 公历日在春节前使用下面代码进行运算 */
  129.                 {
  130.                         Days_Differ = (Spring_Festival_Days - Days_After_New_Years_Day);
  131.                         
  132.                         Table_Offset -= 1;        //未到当年春节,取前一年的农历特征表格
  133.                         Lunar_Month = 12;        //从前一年农历十二月开始判断
  134.                         
  135.                         Lunar_Leap_Month = Lunar_Year_Code[Table_Offset].Byte_0.Bits.Leap_Month;        //闰月月份
  136.                         
  137.                         if (Lunar_Leap_Month == 0)        //当前年没有闰月
  138.                         {
  139.                                 Lunar_Month_Temp = 12;        //农历月,从12月开始判断
  140.                         }
  141.                         else
  142.                         {
  143.                                 Lunar_Month_Temp = 13;        //农历月,当前年有闰月,从13月开始判断
  144.                         }
  145.         
  146.                         Leap_Month_Flag = 0;        //闰月,农历月不-1
  147.         
  148.                         if(Get_Lunar_Month_Days(Lunar_Month_Temp, Table_Offset) == 0)        //农历月天数
  149.                         {
  150.                                 Lunar_Month_Days = 29;        /* 小月29天 */
  151.                         }
  152.                         else
  153.                         {
  154.                                 Lunar_Month_Days = 30;        /* 大月30天 */
  155.                         }
  156.         
  157.                         while(Days_Differ > Lunar_Month_Days)
  158.                         {
  159.                                 Days_Differ -= Lunar_Month_Days;
  160.                                 
  161.                                 Lunar_Month_Temp --;
  162.                                 
  163.                                 if(Leap_Month_Flag == 0)
  164.                                 {
  165.                                         Lunar_Month --;
  166.                                 }
  167.                                 
  168.                                 if(Lunar_Month == Lunar_Leap_Month)
  169.                                 {
  170.                                         Leap_Month_Flag = (~Leap_Month_Flag);
  171.                                        
  172.                                         if(Leap_Month_Flag)
  173.                                         {
  174.                                                 Lunar_Month_Save = Lunar_Month;        //农历月保存(用于判断是不是闰月)
  175.                                         }
  176.                                 }
  177.                                 
  178.                                 if(Get_Lunar_Month_Days(Lunar_Month_Temp, Table_Offset) == 0)
  179.                                 {
  180.                                         Lunar_Month_Days = 29;
  181.                                 }
  182.                                 else
  183.                                 {
  184.                                         Lunar_Month_Days = 30;
  185.                                 }
  186.                         }
  187.         
  188.                         Lunar_Date = (Lunar_Month_Days - Days_Differ + 1);        //农历日
  189.                 }
  190.         
  191.                 if(Lunar_Month == Lunar_Month_Save)        //当前月=闰月保存月份
  192.                 {
  193.                         Return_Value.IS_Leap_Month = 1;        //闰月标志=1
  194.                 }
  195.                
  196.                 Return_Value.Month = Lunar_Month;        //保存转换农历月、日
  197.                 Return_Value.Date = Lunar_Date;
  198.         }

  199.         return        Return_Value;        //返回值
  200. }
复制代码

转换实例:
(1)定义一个结构体变量保存转换返回值
  1. Solar2Lunar_Typedef Lunar_Data;        //公历转农历返回值
复制代码
(2)简单判断数据是否有效(待转换日期在预设范围内都会返回有效结果)。
  1.         Lunar_Data=Get_China_Calendar(Year,Month,Date);        //公历转农历
  2.         
  3.         if(Lunar_Data.Month != 0)        //数据有效
  4.         {
  5.                 Lunar_Calendar.Month = Lunar_Data.Month;        //保存转换农历月、日
  6.                 Lunar_Calendar.Date= Lunar_Data.Date;
  7.                
  8.                 Lunar_Calendar.IS_Leap_Month = Lunar_Data.IS_Leap_Month;        //闰月标志
  9.         }
复制代码



打赏

参与人数 3家元 +90 收起 理由
hefanghua + 30 这是最详尽的了!果断收藏。
水表君 + 30 優秀文章
兔包公 + 30 以資鼓勵

查看全部打赏

发表于 2024-10-22 15:31:36 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-22 15:45:13 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-22 16:21:00 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-22 18:13:53 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-23 17:27:57 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-23 21:50:56 来自手机浏览器 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-24 10:37:39 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-24 12:09:15 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-25 13:55:18 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-25 22:13:20 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-25 22:58:05 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-29 01:33:17 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-29 22:26:54 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2024-10-30 15:57:37 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-1 21:31:01 | 显示全部楼层
游客请登录后查看回复内容

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

发表于 2024-11-2 20:22:34 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-2 22:36:29 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 2025-1-12 21:33:15 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-12 22:53:15 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-12-11 08:29 , Processed in 0.234000 second(s), 11 queries , Gzip On, Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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