当前位置:   article > 正文

《农历算法》_农历程序算法

农历程序算法

先献上我靠这个日历算法最终完成的一款简易日历App(相信找这个算法的人应该也在为实现一个日历而头疼吧哈哈)

下面为项目源码,支持开源精神,欢迎star、fork:(内附项目效果图) 

https://github.com/Yuziquan/WCCalendar2

 (希望可以帮到有需要的人~~)

 

 

结合网上的农历算法,完善了关于节假日的部分

(其中

public String getLunarDate(int year_log, int month_log, int day_log, boolean isday)

是核心函数)

 

 

注意:lunarHoliday 和 solarHoliday 里面的每一个节假日中一定要有一个空格来分隔日期和节假日名称!

 

 

  1. package com.wuchang.wccalendar;
  2. /**
  3. * Created by WuchangI on 2017/8/10.
  4. */
  5. import java.text.ParseException;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import java.util.Locale;
  9. /**
  10. * 农历算法
  11. *
  12. */
  13. public class LunarCalendar
  14. {
  15. private int year; // 农历的年份
  16. private int month;
  17. private int day;
  18. private String lunarMonth; // 农历的月份
  19. public int leapMonth = 0; // 闰的是哪个月
  20. final static String chineseNumber[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
  21. static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);
  22. final static long[] lunarInfo = new long[]{ //
  23. 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, //
  24. 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, //
  25. 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, //
  26. 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, //
  27. 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, //
  28. 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, //
  29. 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, //
  30. 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, //
  31. 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, //
  32. 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //
  33. 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, //
  34. 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, //
  35. 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, //
  36. 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, //
  37. 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, //
  38. 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, //
  39. 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0};
  40. // 农历部分假日
  41. final static String[] lunarHoliday = new String[]{"0101 春节", "0105 五末日", "0115 元宵(上元节)", "0202 龙抬头", "0303 鸡蛋节", "0505 端午节",
  42. "0513 雨节", "0601 过半年", "0606 晒衣节", "0707 七夕(乞巧)", "0715 中元节(鬼节)", "0801 天医节", "0815 中秋节", "0909 重阳节", "1015 下元节",
  43. "1208 腊八", "1224 小年", "0100 除夕"};
  44. // 公历部分节假日
  45. final static String[] solarHoliday = new String[]{
  46. "0101 元旦", "0131 国际麻风节","0202 世界湿地日", "0203 立春", "0210 国际气象节", "0214 情人节", "0301 国际海豹日", "0303 全国爱耳日", "0305 学雷锋纪念日",
  47. "0308 妇女节", "0312 植树节", "0315 消费权益保护", "0401 愚人节", "0402 国际儿童图书日", "0403 寒食节", "0404 清明节", "0407 世界卫生日", "0501 劳动节",
  48. "0503 世界哮喘日", "0504 中国青年节", "0508 世界红十字日", "0512 国际护士节", "0514 母亲节", "0601 国际儿童节", "0605 芒种", "0606 世界爱眼日", "0611 中国文化遗产日",
  49. "0618 父亲节", "0701 建党节", "0707 小暑", "0711 世界人口日", "0801 建军节", "0807 立秋", "0823 处暑", "0903 抗战纪念日", "0907 白露", "0908 国际扫盲日", "0910 教师节",
  50. "0928 孔子诞辰", "1001 国庆", "1004 世界动物日", "1008 寒露", "1101 万圣节", "1107 立冬", "1108 世界记者日", "1109 消防宣传日", "1111 光棍节", "1112 孙中山诞辰",
  51. "1201 世界艾滋病日", "1203 国际残疾人日", "1207 大雪", "1209 世界足球日", "1213 南京大屠杀纪念日", "1220 澳门回归纪念日", "1225 圣诞节"};
  52. /**
  53. * 传回农历 y年的总天数
  54. *
  55. * @param y 年份
  56. * @return 该年的总天数
  57. */
  58. private static int yearDays(int y)
  59. {
  60. int i, sum = 348;
  61. for (i = 0x8000; i > 0x8; i >>= 1)
  62. {
  63. if ((lunarInfo[y - 1900] & i) != 0)
  64. sum += 1;
  65. }
  66. return (sum + leapDays(y));
  67. }
  68. /**
  69. * 传回农历 y年闰月的天数
  70. *
  71. * @param y 年份
  72. * @return 改年闰月天数
  73. */
  74. private static int leapDays(int y)
  75. {
  76. if (leapMonth(y) != 0)
  77. {
  78. if ((lunarInfo[y - 1900] & 0x10000) != 0)
  79. return 30;
  80. else
  81. return 29;
  82. } else
  83. return 0;
  84. }
  85. /**
  86. * 传回农历 y年闰哪个月 1-12 , 没闰传回 0
  87. *
  88. * @param y 年份
  89. * @return 改年闰月的月数
  90. */
  91. private static int leapMonth(int y)
  92. {
  93. return (int) (lunarInfo[y - 1900] & 0b1111);
  94. }
  95. /**
  96. * 传回农历 y年m月的总天数
  97. *
  98. * @param y 年份
  99. * @param m 月份
  100. * @return 该月份的总天数
  101. */
  102. private static int monthDays(int y, int m)
  103. {
  104. if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
  105. return 29;
  106. else
  107. return 30;
  108. }
  109. /**
  110. * 传回农历 y年的生肖
  111. *
  112. * @param year 年份
  113. * @return 生肖
  114. */
  115. public String animalsYear(int year)
  116. {
  117. final String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
  118. return Animals[(year - 4) % 12];
  119. }
  120. /**
  121. * 传入 月日的offset 传回干支, 0=甲子
  122. */
  123. private static String cyclicalm(int num)
  124. {
  125. final String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
  126. final String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
  127. return (Gan[num % 10] + Zhi[num % 12]);
  128. }
  129. /**
  130. * 传入 offset 传回干支, 0=甲子
  131. */
  132. public String cyclical(int year)
  133. {
  134. int num = year - 1900 + 36;
  135. return (cyclicalm(num));
  136. }
  137. public static String getChinaDayString(int day)
  138. {
  139. String chineseTen[] = {"初", "十", "廿", "卅"};
  140. int n = day % 10 == 0 ? 9 : day % 10 - 1;
  141. if (day > 30)
  142. return "";
  143. if (day == 10)
  144. return "初十";
  145. else
  146. return chineseTen[day / 10] + chineseNumber[n];
  147. }
  148. /**
  149. * 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数
  150. * dayCyl5:与1900年1月31日相差的天数,再加40 ?
  151. * <p/>
  152. * isday: 这个参数为false---日期为节假日时,阴历日期就返回节假日 ,true---不管日期是否为节假日依然返回这天对应的阴历日期
  153. *
  154. * @return
  155. */
  156. public String getLunarDate(int year_log, int month_log, int day_log,
  157. boolean isday)
  158. {
  159. // @SuppressWarnings("unused")
  160. int yearCyl, monCyl, dayCyl;
  161. // int leapMonth = 0;
  162. String nowadays;
  163. Date baseDate = null;
  164. Date nowaday = null;
  165. try
  166. {
  167. baseDate = chineseDateFormat.parse("1900年1月31日");
  168. } catch (ParseException e)
  169. {
  170. e.printStackTrace(); // To change body of catch statement use
  171. // Options | File Templates.
  172. }
  173. nowadays = year_log + "年" + month_log + "月" + day_log + "日";
  174. try
  175. {
  176. nowaday = chineseDateFormat.parse(nowadays);
  177. } catch (ParseException e)
  178. {
  179. e.printStackTrace(); // To change body of catch statement use
  180. // Options | File Templates.
  181. }
  182. // 求出和1900年1月31日相差的天数
  183. int offset = (int) ((nowaday.getTime() - baseDate.getTime()) / 86400000L);
  184. dayCyl = offset + 40;
  185. monCyl = 14;
  186. // 用offset减去每农历年的天数
  187. // 计算当天是农历第几天
  188. // i最终结果是农历的年份
  189. // offset是当年的第几天
  190. int iYear, daysOfYear = 0;
  191. for (iYear = 1900; iYear < 10000 && offset > 0; iYear++)
  192. {
  193. daysOfYear = yearDays(iYear);
  194. offset -= daysOfYear;
  195. monCyl += 12;
  196. }
  197. if (offset < 0)
  198. {
  199. offset += daysOfYear;
  200. iYear--;
  201. monCyl -= 12;
  202. }
  203. // 农历年份
  204. year = iYear;
  205. setYear(year); // 设置公历对应的农历年份
  206. yearCyl = iYear - 1864;
  207. leapMonth = leapMonth(iYear); // 闰哪个月,1-12
  208. boolean leap = false;
  209. // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
  210. int iMonth, daysOfMonth = 0;
  211. for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++)
  212. {
  213. // 闰月
  214. if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap)
  215. {
  216. --iMonth;
  217. leap = true;
  218. daysOfMonth = leapDays(year);
  219. } else
  220. daysOfMonth = monthDays(year, iMonth);
  221. offset -= daysOfMonth;
  222. // 解除闰月
  223. if (leap && iMonth == (leapMonth + 1))
  224. leap = false;
  225. if (!leap)
  226. monCyl++;
  227. }
  228. // offset为0时,并且刚才计算的月份是闰月,要校正
  229. if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1)
  230. {
  231. if (leap)
  232. {
  233. leap = false;
  234. } else
  235. {
  236. leap = true;
  237. --iMonth;
  238. --monCyl;
  239. }
  240. }
  241. // offset小于0时,也要校正
  242. if (offset < 0)
  243. {
  244. offset += daysOfMonth;
  245. --iMonth;
  246. --monCyl;
  247. }
  248. month = iMonth;
  249. setLunarMonth(chineseNumber[month - 1] + "月"); // 设置对应的阴历月份
  250. day = offset + 1;
  251. if (!isday)
  252. {
  253. // 如果日期为节假日则阴历日期则返回节假日
  254. // setLeapMonth(leapMonth);
  255. for (int i = 0; i < solarHoliday.length; i++)
  256. {
  257. // 返回公历节假日名称
  258. String sd = solarHoliday[i].split(" ")[0]; // 节假日的日期
  259. String sdv = solarHoliday[i].split(" ")[1]; // 节假日的名称
  260. String smonth_v = month_log + "";
  261. String sday_v = day_log + "";
  262. String smd = "";
  263. if (month_log < 10)
  264. {
  265. smonth_v = "0" + month_log;
  266. }
  267. if (day_log < 10)
  268. {
  269. sday_v = "0" + day_log;
  270. }
  271. smd = smonth_v + sday_v;
  272. if (sd.trim().equals(smd.trim()))
  273. {
  274. return sdv;
  275. }
  276. }
  277. for (int i = 0; i < lunarHoliday.length; i++)
  278. {
  279. // 返回农历节假日名称
  280. String ld = lunarHoliday[i].split(" ")[0]; // 节假日的日期
  281. String ldv = lunarHoliday[i].split(" ")[1]; // 节假日的名称
  282. String lmonth_v = month + "";
  283. String lday_v = day + "";
  284. String lmd = "";
  285. if (month < 10)
  286. {
  287. lmonth_v = "0" + month;
  288. }
  289. if (day < 10)
  290. {
  291. lday_v = "0" + day;
  292. }
  293. lmd = lmonth_v + lday_v;
  294. if (ld.trim().equals(lmd.trim()))
  295. {
  296. return ldv;
  297. }
  298. }
  299. }
  300. if (day == 1)
  301. return chineseNumber[month - 1] + "月";
  302. else
  303. return getChinaDayString(day);
  304. }
  305. public String toString()
  306. {
  307. if (chineseNumber[month - 1] == "一" && getChinaDayString(day) == "初一")
  308. return "农历" + year + "年";
  309. else if (getChinaDayString(day) == "初一")
  310. return chineseNumber[month - 1] + "月";
  311. else
  312. return getChinaDayString(day);
  313. // return year + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] +
  314. // "月" + getChinaDayString(day);
  315. }
  316. //
  317. // public static void main(String[] args) {
  318. // System.out.println(new
  319. // LunarCalendar().getLunarDate(2012, 1, 23));
  320. // }
  321. public int getLeapMonth()
  322. {
  323. return leapMonth;
  324. }
  325. public void setLeapMonth(int leapMonth)
  326. {
  327. this.leapMonth = leapMonth;
  328. }
  329. /**
  330. * 得到当前日期对应的阴历月份
  331. *
  332. * @return
  333. */
  334. public String getLunarMonth()
  335. {
  336. return lunarMonth;
  337. }
  338. public void setLunarMonth(String lunarMonth)
  339. {
  340. this.lunarMonth = lunarMonth;
  341. }
  342. /**
  343. * 得到当前年对应的农历年份
  344. *
  345. * @return
  346. */
  347. public int getYear()
  348. {
  349. return year;
  350. }
  351. public void setYear(int year)
  352. {
  353. this.year = year;
  354. }
  355. }

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/1017246
推荐阅读
相关标签
  

闽ICP备14008679号