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

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
12
返回列表 发新帖
楼主: 卓泰科技
打印 上一主题 下一主题

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

[复制链接]

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
11#
 楼主| 发表于 2015-2-20 23:28:51 | 只看该作者
农历算法简介以及公式

一、节气的计算

  先给节气进行编号,从近日点开始的第一个节气编为0,编号如下及其相应的月份如下:
            
0 小寒 腊月
            
            
6  清明 三月
            
            
12 小暑 六月
            
            
18 寒露 九月
            
            
1 大寒 腊月
            
            
7  谷雨 三月
            
            
13 大暑 六月
            
            
19 霜降 九月
            
            
2 立春  正月
            
            
8  立夏 四月
            
            
14 立秋 七月
            
            
20 立冬 十月
            
            
3 雨水 正月
            
            
9  小满 四月
            
            
15 处暑 七月
            
            
21 小雪 十月
            
            
4 惊蛰 二月
            
            
10 芒种 五月
            
            
16 白露 八月
            
            
22 大雪 冬月
            
            
5 春分 二月
            
            
11 夏至 五月
            
            
17 秋分 八月
            
            
23 冬至 冬月
            


把当天和1900年1月0日(星期日)的差称为积日,那么第y年(1900年算第0年)第x 个节气的积日是
        F = 365.242 * y + 6.2 + 15.22 * x - 1.9 * sin(0.262 * x)
这个公式的误差在0.05天左右。

二、朔日的计算

  从1900年开始的第m个朔日的公式是
        M = 1.6 + 29.5306 * m + 0.4 * sin(1 - 0.45058 * m)
这个公式的误差在0.2天左右。


三、年份的确定

  1864年1月0日是农历癸亥年,所以用当年减去1864,用10除得的余数作为年份天干的,用12除得的余数作为年份的地支,数字对应的天干和地支如下。
            
数字
            
            
0
            
            
1
            
            
2
            
            
3
            
            
4
            
            
5
            
            
6
            
            
7
            
            
8
            
            
9
            
            
10
            
            
11
            
            
天干
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
地支
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            


当年的1月0日换算为积日,可以用年份减去1900得到的年数被4整除,所得商数作为 y(D4),余数作为y(M4),y(M4)为零的年份是公历闰年,积日是
        D(1) = 1461 * y(D4) - 1
y(M4)不为零的年份是公历平年,积日是
        D(1) = 1461 * y(D4) + 365 * y(M4)

四、月份的确定
  计算前一年冬至的积日F(0),并用F(0)计算冬至所在的朔月m及其朔日M(0),就可以推算冬至的农历日期,冬至所在的农历月份总是十一月。计算下一个中气F(1)和下一个朔日M(1),如果F(1)<M(1),那么该月就是上一个月的闰月,并把这个中气作为F(2),以后的中气、朔日和农历月份也这样确定。


有关农历的东西有以下几篇文章:

计算某天是星期几【C代码】
农历算法简介以及公式
农历中天干地支的计算【C代码】
农历一百年算法(1921~2021)【C语言代码】
农历两百年算法(1901~2100)【C语言代码】
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
12#
 楼主| 发表于 2015-2-20 23:32:22 | 只看该作者
好复杂的农历
先不深入研究了,否则估计这里就卡死了。
这个毛病要改。
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
13#
 楼主| 发表于 2015-2-20 23:40:26 | 只看该作者
发一个移植于C51的公历转农历的程序
http://www.geek-workshop.com/thread-12245-1-1.html

万年历制作练习, 开发记录中 ,已基本完成开发,上传了源代码
http://www.geek-workshop.com/thread-12768-1-1.html

一个写得不错的公历转农历程序
http://www.jhmcu.com/yi-ge-xie-de-bu-cuo-di-gong-li-zhuan-nong-li-cheng-xu

  1. 公历转农历程序:



  2. //公历转农历和星期
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #include <intrins.h>
  6. /*
  7. 公历年对应的农历数据,每年三字节,
  8. 格式第一字节BIT7-4 位表示闰月月份,值为0 为无闰月,BIT3-0 对应农历第1-4 月的大小
  9. 第二字节BIT7-0 对应农历第5-12 月大小,第三字节BIT7 表示农历第13 个月大小
  10. 月份对应的位为1 表示本农历月大(30 天),为0 表示小(29 天)
  11. 第三字节BIT6-5 表示春节的公历月份,BIT4-0 表示春节的公历日期
  12. */
  13. code uchar year_code[597] = {
  14. 0x04,0xAe,0x53, //1901 0
  15. 0x0A,0x57,0x48, //1902 3
  16. 0x55,0x26,0xBd, //1903 6
  17. 0x0d,0x26,0x50, //1904 9
  18. 0x0d,0x95,0x44, //1905 12
  19. 0x46,0xAA,0xB9, //1906 15
  20. 0x05,0x6A,0x4d, //1907 18
  21. 0x09,0xAd,0x42, //1908 21
  22. 0x24,0xAe,0xB6, //1909
  23. 0x04,0xAe,0x4A, //1910
  24. 0x6A,0x4d,0xBe, //1911
  25. 0x0A,0x4d,0x52, //1912
  26. 0x0d,0x25,0x46, //1913
  27. 0x5d,0x52,0xBA, //1914
  28. 0x0B,0x54,0x4e, //1915
  29. 0x0d,0x6A,0x43, //1916
  30. 0x29,0x6d,0x37, //1917
  31. 0x09,0x5B,0x4B, //1918
  32. 0x74,0x9B,0xC1, //1919
  33. 0x04,0x97,0x54, //1920
  34. 0x0A,0x4B,0x48, //1921
  35. 0x5B,0x25,0xBC, //1922
  36. 0x06,0xA5,0x50, //1923
  37. 0x06,0xd4,0x45, //1924
  38. 0x4A,0xdA,0xB8, //1925
  39. 0x02,0xB6,0x4d, //1926
  40. 0x09,0x57,0x42, //1927
  41. 0x24,0x97,0xB7, //1928
  42. 0x04,0x97,0x4A, //1929
  43. 0x66,0x4B,0x3e, //1930
  44. 0x0d,0x4A,0x51, //1931
  45. 0x0e,0xA5,0x46, //1932
  46. 0x56,0xd4,0xBA, //1933
  47. 0x05,0xAd,0x4e, //1934
  48. 0x02,0xB6,0x44, //1935
  49. 0x39,0x37,0x38, //1936
  50. 0x09,0x2e,0x4B, //1937
  51. 0x7C,0x96,0xBf, //1938
  52. 0x0C,0x95,0x53, //1939
  53. 0x0d,0x4A,0x48, //1940
  54. 0x6d,0xA5,0x3B, //1941
  55. 0x0B,0x55,0x4f, //1942
  56. 0x05,0x6A,0x45, //1943
  57. 0x4A,0xAd,0xB9, //1944
  58. 0x02,0x5d,0x4d, //1945
  59. 0x09,0x2d,0x42, //1946
  60. 0x2C,0x95,0xB6, //1947
  61. 0x0A,0x95,0x4A, //1948
  62. 0x7B,0x4A,0xBd, //1949
  63. 0x06,0xCA,0x51, //1950
  64. 0x0B,0x55,0x46, //1951
  65. 0x55,0x5A,0xBB, //1952
  66. 0x04,0xdA,0x4e, //1953
  67. 0x0A,0x5B,0x43, //1954
  68. 0x35,0x2B,0xB8, //1955
  69. 0x05,0x2B,0x4C, //1956
  70. 0x8A,0x95,0x3f, //1957
  71. 0x0e,0x95,0x52, //1958
  72. 0x06,0xAA,0x48, //1959
  73. 0x7A,0xd5,0x3C, //1960
  74. 0x0A,0xB5,0x4f, //1961
  75. 0x04,0xB6,0x45, //1962
  76. 0x4A,0x57,0x39, //1963
  77. 0x0A,0x57,0x4d, //1964
  78. 0x05,0x26,0x42, //1965
  79. 0x3e,0x93,0x35, //1966
  80. 0x0d,0x95,0x49, //1967
  81. 0x75,0xAA,0xBe, //1968
  82. 0x05,0x6A,0x51, //1969
  83. 0x09,0x6d,0x46, //1970
  84. 0x54,0xAe,0xBB, //1971
  85. 0x04,0xAd,0x4f, //1972
  86. 0x0A,0x4d,0x43, //1973
  87. 0x4d,0x26,0xB7, //1974
  88. 0x0d,0x25,0x4B, //1975
  89. 0x8d,0x52,0xBf, //1976
  90. 0x0B,0x54,0x52, //1977
  91. 0x0B,0x6A,0x47, //1978
  92. 0x69,0x6d,0x3C, //1979
  93. 0x09,0x5B,0x50, //1980
  94. 0x04,0x9B,0x45, //1981
  95. 0x4A,0x4B,0xB9, //1982
  96. 0x0A,0x4B,0x4d, //1983
  97. 0xAB,0x25,0xC2, //1984
  98. 0x06,0xA5,0x54, //1985
  99. 0x06,0xd4,0x49, //1986
  100. 0x6A,0xdA,0x3d, //1987
  101. 0x0A,0xB6,0x51, //1988
  102. 0x09,0x37,0x46, //1989
  103. 0x54,0x97,0xBB, //1990
  104. 0x04,0x97,0x4f, //1991
  105. 0x06,0x4B,0x44, //1992
  106. 0x36,0xA5,0x37, //1993
  107. 0x0e,0xA5,0x4A, //1994
  108. 0x86,0xB2,0xBf, //1995
  109. 0x05,0xAC,0x53, //1996
  110. 0x0A,0xB6,0x47, //1997
  111. 0x59,0x36,0xBC, //1998
  112. 0x09,0x2e,0x50, //1999 294
  113. 0x0C,0x96,0x45, //2000 297
  114. 0x4d,0x4A,0xB8, //2001
  115. 0x0d,0x4A,0x4C, //2002
  116. 0x0d,0xA5,0x41, //2003
  117. 0x25,0xAA,0xB6, //2004
  118. 0x05,0x6A,0x49, //2005
  119. 0x7A,0xAd,0xBd, //2006
  120. 0x02,0x5d,0x52, //2007
  121. 0x09,0x2d,0x47, //2008
  122. 0x5C,0x95,0xBA, //2009
  123. 0x0A,0x95,0x4e, //2010
  124. 0x0B,0x4A,0x43, //2011
  125. 0x4B,0x55,0x37, //2012
  126. 0x0A,0xd5,0x4A, //2013
  127. 0x95,0x5A,0xBf, //2014
  128. 0x04,0xBA,0x53, //2015
  129. 0x0A,0x5B,0x48, //2016
  130. 0x65,0x2B,0xBC, //2017
  131. 0x05,0x2B,0x50, //2018
  132. 0x0A,0x93,0x45, //2019
  133. 0x47,0x4A,0xB9, //2020
  134. 0x06,0xAA,0x4C, //2021
  135. 0x0A,0xd5,0x41, //2022
  136. 0x24,0xdA,0xB6, //2023
  137. 0x04,0xB6,0x4A, //2024
  138. 0x69,0x57,0x3d, //2025
  139. 0x0A,0x4e,0x51, //2026
  140. 0x0d,0x26,0x46, //2027
  141. 0x5e,0x93,0x3A, //2028
  142. 0x0d,0x53,0x4d, //2029
  143. 0x05,0xAA,0x43, //2030
  144. 0x36,0xB5,0x37, //2031
  145. 0x09,0x6d,0x4B, //2032
  146. 0xB4,0xAe,0xBf, //2033
  147. 0x04,0xAd,0x53, //2034
  148. 0x0A,0x4d,0x48, //2035
  149. 0x6d,0x25,0xBC, //2036
  150. 0x0d,0x25,0x4f, //2037
  151. 0x0d,0x52,0x44, //2038
  152. 0x5d,0xAA,0x38, //2039
  153. 0x0B,0x5A,0x4C, //2040
  154. 0x05,0x6d,0x41, //2041
  155. 0x24,0xAd,0xB6, //2042
  156. 0x04,0x9B,0x4A, //2043
  157. 0x7A,0x4B,0xBe, //2044
  158. 0x0A,0x4B,0x51, //2045
  159. 0x0A,0xA5,0x46, //2046
  160. 0x5B,0x52,0xBA, //2047
  161. 0x06,0xd2,0x4e, //2048
  162. 0x0A,0xdA,0x42, //2049
  163. 0x35,0x5B,0x37, //2050
  164. 0x09,0x37,0x4B, //2051
  165. 0x84,0x97,0xC1, //2052
  166. 0x04,0x97,0x53, //2053
  167. 0x06,0x4B,0x48, //2054
  168. 0x66,0xA5,0x3C, //2055
  169. 0x0e,0xA5,0x4f, //2056
  170. 0x06,0xB2,0x44, //2057
  171. 0x4A,0xB6,0x38, //2058
  172. 0x0A,0xAe,0x4C, //2059
  173. 0x09,0x2e,0x42, //2060
  174. 0x3C,0x97,0x35, //2061
  175. 0x0C,0x96,0x49, //2062
  176. 0x7d,0x4A,0xBd, //2063
  177. 0x0d,0x4A,0x51, //2064
  178. 0x0d,0xA5,0x45, //2065
  179. 0x55,0xAA,0xBA, //2066
  180. 0x05,0x6A,0x4e, //2067
  181. 0x0A,0x6d,0x43, //2068
  182. 0x45,0x2e,0xB7, //2069
  183. 0x05,0x2d,0x4B, //2070
  184. 0x8A,0x95,0xBf, //2071
  185. 0x0A,0x95,0x53, //2072
  186. 0x0B,0x4A,0x47, //2073
  187. 0x6B,0x55,0x3B, //2074
  188. 0x0A,0xd5,0x4f, //2075
  189. 0x05,0x5A,0x45, //2076
  190. 0x4A,0x5d,0x38, //2077
  191. 0x0A,0x5B,0x4C, //2078
  192. 0x05,0x2B,0x42, //2079
  193. 0x3A,0x93,0xB6, //2080
  194. 0x06,0x93,0x49, //2081
  195. 0x77,0x29,0xBd, //2082
  196. 0x06,0xAA,0x51, //2083
  197. 0x0A,0xd5,0x46, //2084
  198. 0x54,0xdA,0xBA, //2085
  199. 0x04,0xB6,0x4e, //2086
  200. 0x0A,0x57,0x43, //2087
  201. 0x45,0x27,0x38, //2088
  202. 0x0d,0x26,0x4A, //2089
  203. 0x8e,0x93,0x3e, //2090
  204. 0x0d,0x52,0x52, //2091
  205. 0x0d,0xAA,0x47, //2092
  206. 0x66,0xB5,0x3B, //2093
  207. 0x05,0x6d,0x4f, //2094
  208. 0x04,0xAe,0x45, //2095
  209. 0x4A,0x4e,0xB9, //2096
  210. 0x0A,0x4d,0x4C, //2097
  211. 0x0d,0x15,0x41, //2098
  212. 0x2d,0x92,0xB5, //2099
  213. };
  214. ///月份数据表
  215. code uchar day_code1[9]={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
  216. code uint day_code2[3]={0x111,0x130,0x14e};
  217. /*
  218. 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
  219. 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
  220. 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
  221. c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
  222. 纪,c_sun=1为19世纪
  223. 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
  224. */
  225. bit c_moon;
  226. data uchar year_moon,month_moon,day_moon,week;
  227. /*子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0*/
  228. bit get_moon_day(uchar month_p,uint table_addr)
  229. {
  230.         uchar temp;
  231.         switch (month_p)
  232.         {
  233.                 case 1:{temp=year_code[table_addr]&0x08;
  234.                         if (temp==0)return(0);else return(1);}
  235.                 case 2:{temp=year_code[table_addr]&0x04;
  236.                         if (temp==0)return(0);else return(1);}
  237.                 case 3:{temp=year_code[table_addr]&0x02;
  238.                         if (temp==0)return(0);else return(1);}
  239.                 case 4:{temp=year_code[table_addr]&0x01;
  240.                         if (temp==0)return(0);else return(1);}
  241.                 case 5:{temp=year_code[table_addr+1]&0x80;
  242.                         if (temp==0) return(0);else return(1);}
  243.                 case 6:{temp=year_code[table_addr+1]&0x40;
  244.                         if (temp==0)return(0);else return(1);}
  245.                 case 7:{temp=year_code[table_addr+1]&0x20;
  246.                         if (temp==0)return(0);else return(1);}
  247.                 case 8:{temp=year_code[table_addr+1]&0x10;
  248.                         if (temp==0)return(0);else return(1);}
  249.                 case 9:{temp=year_code[table_addr+1]&0x08;
  250.                         if (temp==0)return(0);else return(1);}
  251.                 case 10:{temp=year_code[table_addr+1]&0x04;
  252.                         if (temp==0)return(0);else return(1);}
  253.                 case 11:{temp=year_code[table_addr+1]&0x02;
  254.                         if (temp==0)return(0);else return(1);}
  255.                 case 12:{temp=year_code[table_addr+1]&0x01;
  256.                         if (temp==0)return(0);else return(1);}
  257.                 case 13:{temp=year_code[table_addr+2]&0x80;
  258.                         if (temp==0)return(0);else return(1);}
  259.         }
  260. }
  261. /*
  262. 函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)
  263. 调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)
  264. 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
  265. c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
  266. 纪,c_sun=1为19世纪
  267. 调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据
  268. */
  269. void Conversion(bit c,uchar year,uchar month,uchar day)
  270. { //c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据
  271.         uchar temp1,temp2,temp3,month_p;
  272.         uint temp4,table_addr;
  273.         bit flag2,flag_y;
  274.         temp1=year/16; //BCD->hex 先把数据转换为十六进制
  275.         temp2=year%16;
  276.         year=temp1*10+temp2;
  277.         temp1=month/16;
  278.         temp2=month%16;
  279.         month=temp1*10+temp2;
  280.         temp1=day/16;
  281.         temp2=day%16;
  282.         day=temp1*10+temp2;
  283.         //定位数据表地址
  284.         if(c==0)
  285.         {
  286.                 table_addr=(year+0x64-1)*0x3;
  287.         }
  288.         else
  289.         {
  290.                 table_addr=(year-1)*0x3;
  291.         }
  292.         //定位数据表地址完成
  293.         //取当年春节所在的公历月份
  294.         temp1=year_code[table_addr+2]&0x60;
  295.         temp1=_cror_(temp1,5);
  296.         //取当年春节所在的公历月份完成
  297.         //取当年春节所在的公历日
  298.         temp2=year_code[table_addr+2]&0x1f;
  299.         //取当年春节所在的公历日完成
  300.         // 计算当年春年离当年元旦的天数,春节只会在公历1月或2月
  301.         if(temp1==0x1)
  302.         {
  303.                 temp3=temp2-1;
  304.         }
  305.         else
  306.         {
  307.                 temp3=temp2+0x1f-1;
  308.         }
  309.         // 计算当年春年离当年元旦的天数完成
  310.         //计算公历日离当年元旦的天数,为了减少运算,用了两个表
  311.         //day_code1[9],day_code2[3]
  312.         //如果公历月在九月或前,天数会少于0xff,用表day_code1[9],
  313.         //在九月后,天数大于0xff,用表day_code2[3]
  314.         //如输入公历日为8月10日,则公历日离元旦天数为day_code1[8-1]+10-1
  315.         //如输入公历日为11月10日,则公历日离元旦天数为day_code2[11-10]+10-1
  316.         if (month<10)
  317.         {
  318.                 temp4=day_code1[month-1]+day-1;
  319.         }
  320.         else
  321.         {
  322.                 temp4=day_code2[month-10]+day-1;
  323.         }
  324.         if ((month>0x2)&&(year%0x4==0))
  325.         { //如果公历月大于2月并且该年的2月为闰月,天数加1
  326.                 temp4+=1;
  327.         }
  328.         //计算公历日离当年元旦的天数完成
  329.         //判断公历日在春节前还是春节后
  330.         if (temp4>=temp3)
  331.         { //公历日在春节后或就是春节当日使用下面代码进行运算
  332.                 temp4-=temp3;
  333.                 month=0x1;
  334.                 month_p=0x1; //month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月
  335.                 flag2=get_moon_day(month_p,table_addr);
  336.                 //检查该农历月为大小还是小月,大月返回1,小月返回0
  337.                 flag_y=0;
  338.                 if(flag2==0)temp1=0x1d; //小月29天
  339.                 else temp1=0x1e; //大小30天
  340.                 temp2=year_code[table_addr]&0xf0;
  341.                 temp2=_cror_(temp2,4); //从数据表中取该年的闰月月份,如为0则该年无闰月
  342.                 while(temp4>=temp1)
  343.                 {
  344.                 temp4-=temp1;
  345.                 month_p+=1;
  346.                 if(month==temp2)
  347.                 {
  348.                 flag_y=~flag_y;
  349.                 if(flag_y==0)
  350.                 month+=1;
  351.                 }
  352.                 else month+=1;
  353.                 flag2=get_moon_day(month_p,table_addr);
  354.                 if(flag2==0)temp1=0x1d;
  355.                 else temp1=0x1e;
  356.                 }
  357.                 day=temp4+1;
  358.         }
  359.         else
  360.         { //公历日在春节前使用下面代码进行运算
  361.                 temp3-=temp4;
  362.                 if (year==0x0)
  363.                 {
  364.                         year=0x63;c=1;
  365.                 }
  366.                 else year-=1;
  367.                 table_addr-=0x3;
  368.                 month=0xc;
  369.                 temp2=year_code[table_addr]&0xf0;
  370.                 temp2=_cror_(temp2,4);
  371.                 if (temp2==0)
  372.                         month_p=0xc;
  373.                 else
  374.                         month_p=0xd; //
  375.                 /*month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12*/
  376.                 flag_y=0;
  377.                 flag2=get_moon_day(month_p,table_addr);
  378.                 if(flag2==0)temp1=0x1d;
  379.                 else temp1=0x1e;
  380.                 while(temp3>temp1)
  381.                 {
  382.                         temp3-=temp1;
  383.                         month_p-=1;
  384.                         if(flag_y==0)month-=1;
  385.                         if(month==temp2)flag_y=~flag_y;
  386.                                 flag2=get_moon_day(month_p,table_addr);
  387.                         if(flag2==0)temp1=0x1d;
  388.                         else temp1=0x1e;
  389.                 }
  390.                 day=temp1-temp3+1;
  391.         }
  392.         c_moon=c; //HEX->BCD ,运算结束后,把数据转换为BCD数据
  393.         temp1=year/10;
  394.         temp1=_crol_(temp1,4);
  395.         temp2=year%10;
  396.         year_moon=temp1|temp2;
  397.         temp1=month/10;
  398.         temp1=_crol_(temp1,4);
  399.         temp2=month%10;
  400.         month_moon=temp1|temp2;
  401.         temp1=day/10;
  402.         temp1=_crol_(temp1,4);
  403.         temp2=day%10;
  404.         day_moon=temp1|temp2;
  405. }
  406. /*函数功能:输入BCD阳历数据,输出BCD星期数据(只允许1901-2099年)
  407. 调用函数示例:Conver_week(c_sun,year_sun,month_sun,day_sun)
  408. 如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);
  409. c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世
  410. 纪,c_sun=1为19世纪
  411. 调用函数后,原有数据不变,读week得出阴历BCD数据
  412. */
  413. code uchar table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
  414. /*
  415. 算法:日期+年份+所过闰年数+月较正数之和除7 的余数就是星期但如果是在
  416. 闰年又不到3 月份上述之和要减一天再除7
  417. 星期数为0
  418. */
  419. void Conver_week(bit c,uchar year,uchar month,uchar day)
  420. {//c=0 为21世纪,c=1 为19世纪 输入输出数据均为BCD数据
  421.         uchar temp1,temp2;
  422.         temp1=year/16; //BCD->hex 先把数据转换为十六进制
  423.         temp2=year%16;
  424.         year=temp1*10+temp2;
  425.         temp1=month/16;
  426.         temp2=month%16;
  427.         month=temp1*10+temp2;
  428.         temp1=day/16;
  429.         temp2=day%16;
  430.         day=temp1*10+temp2;
  431.         if (c==0){year+=0x64;} //如果为21世纪,年份数加100
  432.         temp1=year/0x4; //所过闰年数只算1900年之后的
  433.         temp2=year+temp1;
  434.         temp2=temp2%0x7; //为节省资源,先进行一次取余,避免数大于0xff,避免使用整型数据
  435.         temp2=temp2+day+table_week[month-1];
  436.         if (year%0x4==0&&month<3)temp2-=1;
  437.         week=temp2%0x7;
  438. }

  439. //=========================================
  440. //TEST
  441. //=========================================
  442. uchar c_sun,year_sun,month_sun,day_sun;

  443. //主程序
  444. void main()
  445. {
  446.         c_sun=1;
  447.         year_sun=0x2;
  448.         month_sun=0x11;
  449.         day_sun=0x3;
  450.         Conver_week(c_sun,year_sun,month_sun,day_sun);
  451.         Conversion(c_sun,year_sun,month_sun,day_sun);
  452.         while(1);
  453. }



  454. 这个公历转农历算法,可以直接应用在单片机设计的数码钟上,只要调用Conversion(); 函数,传递公历的日期(BCD码),就可以输出农历的日期(BCD码)。很简单就可以应用到自己设计的单片机系统中。
复制代码


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

84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
14#
 楼主| 发表于 2015-2-20 23:42:42 | 只看该作者
被公历农历转换折腾办法,我发现这是病
得治
总想找到最优的方法
一劳永逸
其实这是不现实的
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-4-20 08:29 , Processed in 0.044340 second(s), 29 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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