24节气算法

旧城等待, 2022-09-24 16:18 292阅读 0赞
  1. import java.util.Calendar;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. /** *describe:24节气 * * 注:程序中使用到的计算节气公式、节气世纪常量等相关信息参照 * * 程序的运行得出的节气结果绝大多数是正确的,有少数部份是有误差的 */
  5. public class SolarTerms {
  6. private static final double D = 0.2422;
  7. private final static Map<String, Integer[]> INCREASE_OFFSETMAP = new HashMap<String, Integer[]>();// +1偏移
  8. private final static Map<String, Integer[]> DECREASE_OFFSETMAP = new HashMap<String, Integer[]>();// -1偏移
  9. /** 24节气 **/
  10. private static enum SolarTermsEnum {
  11. LICHUN, // --立春
  12. YUSHUI, // --雨水
  13. JINGZHE, // --惊蛰
  14. CHUNFEN, // 春分
  15. QINGMING, // 清明
  16. GUYU, // 谷雨
  17. LIXIA, // 立夏
  18. XIAOMAN, // 小满
  19. MANGZHONG, // 芒种
  20. XIAZHI, // 夏至
  21. XIAOSHU, // 小暑
  22. DASHU, // 大暑
  23. LIQIU, // 立秋
  24. CHUSHU, // 处暑
  25. BAILU, // 白露
  26. QIUFEN, // 秋分
  27. HANLU, // 寒露
  28. SHUANGJIANG, // 霜降
  29. LIDONG, // 立冬
  30. XIAOXUE, // 小雪
  31. DAXUE, // 大雪
  32. DONGZHI, // 冬至
  33. XIAOHAN, // 小寒
  34. DAHAN;// 大寒
  35. }
  36. static {
  37. DECREASE_OFFSETMAP.put(SolarTermsEnum.YUSHUI.name(), new Integer[] { 2026 });// 雨水
  38. INCREASE_OFFSETMAP.put(SolarTermsEnum.CHUNFEN.name(), new Integer[] { 2084 });// 春分
  39. INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOMAN.name(), new Integer[] { 2008 });// 小满
  40. INCREASE_OFFSETMAP.put(SolarTermsEnum.MANGZHONG.name(), new Integer[] { 1902 });// 芒种
  41. INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAZHI.name(), new Integer[] { 1928 });// 夏至
  42. INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOSHU.name(), new Integer[] { 1925, 2016 });// 小暑
  43. INCREASE_OFFSETMAP.put(SolarTermsEnum.DASHU.name(), new Integer[] { 1922 });// 大暑
  44. INCREASE_OFFSETMAP.put(SolarTermsEnum.LIQIU.name(), new Integer[] { 2002 });// 立秋
  45. INCREASE_OFFSETMAP.put(SolarTermsEnum.BAILU.name(), new Integer[] { 1927 });// 白露
  46. INCREASE_OFFSETMAP.put(SolarTermsEnum.QIUFEN.name(), new Integer[] { 1942 });// 秋分
  47. INCREASE_OFFSETMAP.put(SolarTermsEnum.SHUANGJIANG.name(), new Integer[] { 2089 });// 霜降
  48. INCREASE_OFFSETMAP.put(SolarTermsEnum.LIDONG.name(), new Integer[] { 2089 });// 立冬
  49. INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOXUE.name(), new Integer[] { 1978 });// 小雪
  50. INCREASE_OFFSETMAP.put(SolarTermsEnum.DAXUE.name(), new Integer[] { 1954 });// 大雪
  51. DECREASE_OFFSETMAP.put(SolarTermsEnum.DONGZHI.name(), new Integer[] { 1918, 2021 });// 冬至
  52. INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(), new Integer[] { 1982 });// 小寒
  53. DECREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(), new Integer[] { 2019 });// 小寒
  54. INCREASE_OFFSETMAP.put(SolarTermsEnum.DAHAN.name(), new Integer[] { 2082 });// 大寒
  55. }
  56. // 定义一个二维数组,第一维数组存储的是20世纪的节气C值,第二维数组存储的是21世纪的节气C值,0到23个,依次代表立春、雨水...大寒节气的C值
  57. private static final double[][] CENTURY_ARRAY = {
  58. { 4.6295, 19.4599, 6.3826, 21.4155, 5.59, 20.888, 6.318, 21.86, 6.5, 22.2, 7.928, 23.65, 8.35, 23.95, 8.44,
  59. 23.822, 9.098, 24.218, 8.218, 23.08, 7.9, 22.6, 6.11, 20.84 },
  60. { 3.87, 18.73, 5.63, 20.646, 4.81, 20.1, 5.52, 21.04, 5.678, 21.37, 7.108, 22.83, 7.5, 23.13, 7.646,
  61. 23.042, 8.318, 23.438, 7.438, 22.36, 7.18, 21.94, 5.4055, 20.12 } };
  62. /** * * @param year * 年份 * @param name * 节气的名称 * @return 返回节气是相应月份的第几天 */
  63. public static int getSolarTermNum(int year, String name) {
  64. double centuryValue = 0;// 节气的世纪值,每个节气的每个世纪值都不同
  65. name = name.trim().toUpperCase();
  66. int ordinal = SolarTermsEnum.valueOf(name).ordinal();
  67. int centuryIndex = -1;
  68. if (year >= 1901 && year <= 2000) {// 20世纪
  69. centuryIndex = 0;
  70. } else if (year >= 2001 && year <= 2100) {// 21世纪
  71. centuryIndex = 1;
  72. } else {
  73. throw new RuntimeException("不支持此年份:" + year + ",目前只支持1901年到2100年的时间范围");
  74. }
  75. centuryValue = CENTURY_ARRAY[centuryIndex][ordinal];
  76. int dateNum = 0;
  77. /** * 计算 num =[Y*D+C]-L这是传说中的寿星通用公式 公式解读:年数的后2位乘0.2422加C(即:centuryValue)取整数后,减闰年数 */
  78. int y = year % 100;// 步骤1:取年分的后两位数
  79. if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {// 闰年
  80. if (ordinal == SolarTermsEnum.XIAOHAN.ordinal() || ordinal == SolarTermsEnum.DAHAN.ordinal()
  81. || ordinal == SolarTermsEnum.LICHUN.ordinal() || ordinal == SolarTermsEnum.YUSHUI.ordinal()) {
  82. // 注意:凡闰年3月1日前闰年数要减一,即:L=[(Y-1)/4],因为小寒、大寒、立春、雨水这两个节气都小于3月1日,所以 y = y-1
  83. y = y - 1;// 步骤2
  84. }
  85. }
  86. dateNum = (int) (y * D + centuryValue) - (int) (y / 4);// 步骤3,使用公式[Y*D+C]-L计算
  87. dateNum += specialYearOffset(year, name);// 步骤4,加上特殊的年分的节气偏移量
  88. return dateNum;
  89. }
  90. /** * 特例,特殊的年分的节气偏移量,由于公式并不完善,所以算出的个别节气的第几天数并不准确,在此返回其偏移量 * * @param year * 年份 * @param name * 节气名称 * @return 返回其偏移量 */
  91. public static int specialYearOffset(int year, String name) {
  92. int offset = 0;
  93. offset += getOffset(DECREASE_OFFSETMAP, year, name, -1);
  94. offset += getOffset(INCREASE_OFFSETMAP, year, name, 1);
  95. return offset;
  96. }
  97. public static int getOffset(Map<String, Integer[]> map, int year, String name, int offset) {
  98. int off = 0;
  99. Integer[] years = map.get(name);
  100. if (null != years) {
  101. for (int i : years) {
  102. if (i == year) {
  103. off = offset;
  104. break;
  105. }
  106. }
  107. }
  108. return off;
  109. }
  110. public static String solarTermToString(int year) {
  111. StringBuffer sb = new StringBuffer();
  112. // sb.append("---").append(year);
  113. // if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {// 闰年
  114. // sb.append(" 闰年");
  115. // } else {
  116. // sb.append(" 平年");
  117. // }
  118. // sb.append("\n").append("立春:2月").append(getSolarTermNum(year, SolarTermsEnum.LICHUN.name())).append("日,雨水:2月")
  119. // .append(getSolarTermNum(year, SolarTermsEnum.YUSHUI.name())).append("日,惊蛰:3月").append(
  120. // getSolarTermNum(year, SolarTermsEnum.JINGZHE.name())).append("日,春分:3月").append(
  121. // getSolarTermNum(year, SolarTermsEnum.CHUNFEN.name())).append("日,清明:4月").append(
  122. // getSolarTermNum(year, SolarTermsEnum.QINGMING.name())).append("日,谷雨:4月").append(
  123. // getSolarTermNum(year, SolarTermsEnum.GUYU.name())).append("日,立夏:5月").append(
  124. // getSolarTermNum(year, SolarTermsEnum.LIXIA.name())).append("日,小满:5月").append(
  125. // getSolarTermNum(year, SolarTermsEnum.XIAOMAN.name())).append("日,芒种:6月").append(
  126. // getSolarTermNum(year, SolarTermsEnum.MANGZHONG.name())).append("日,夏至:6月").append(
  127. // getSolarTermNum(year, SolarTermsEnum.XIAZHI.name())).append("日,小暑:7月").append(
  128. // getSolarTermNum(year, SolarTermsEnum.XIAOSHU.name())).append("日,大暑:7月").append(
  129. // getSolarTermNum(year, SolarTermsEnum.DASHU.name())).append("日,\n立秋:8月").append(
  130. // getSolarTermNum(year, SolarTermsEnum.LIQIU.name())).append("日,处暑:8月").append(
  131. // getSolarTermNum(year, SolarTermsEnum.CHUSHU.name())).append("日,白露:9月").append(
  132. // getSolarTermNum(year, SolarTermsEnum.BAILU.name())).append("日,秋分:9月").append(
  133. // getSolarTermNum(year, SolarTermsEnum.QIUFEN.name())).append("日,寒露:10月").append(
  134. // getSolarTermNum(year, SolarTermsEnum.HANLU.name())).append("日,霜降:10月").append(
  135. // getSolarTermNum(year, SolarTermsEnum.SHUANGJIANG.name())).append("日,立冬:11月").append(
  136. // getSolarTermNum(year, SolarTermsEnum.LIDONG.name())).append("日,小雪:11月").append(
  137. // getSolarTermNum(year, SolarTermsEnum.XIAOXUE.name())).append("日,大雪:12月").append(
  138. // getSolarTermNum(year, SolarTermsEnum.DAXUE.name())).append("日,冬至:12月").append(
  139. // getSolarTermNum(year, SolarTermsEnum.DONGZHI.name())).append("日,小寒:1月").append(
  140. // getSolarTermNum(year, SolarTermsEnum.XIAOHAN.name())).append("日,大寒:1月").append(
  141. // getSolarTermNum(year, SolarTermsEnum.DAHAN.name()));
  142. sb.append("2:").append(getSolarTermNum(year, SolarTermsEnum.LICHUN.name())).append(",2:").append(
  143. getSolarTermNum(year, SolarTermsEnum.YUSHUI.name())).append(",3:").append(
  144. getSolarTermNum(year, SolarTermsEnum.JINGZHE.name())).append(",3:").append(
  145. getSolarTermNum(year, SolarTermsEnum.CHUNFEN.name())).append(",4:").append(
  146. getSolarTermNum(year, SolarTermsEnum.QINGMING.name())).append(",4:").append(
  147. getSolarTermNum(year, SolarTermsEnum.GUYU.name())).append(",5:").append(
  148. getSolarTermNum(year, SolarTermsEnum.LIXIA.name())).append(",5:").append(
  149. getSolarTermNum(year, SolarTermsEnum.XIAOMAN.name())).append(",6:").append(
  150. getSolarTermNum(year, SolarTermsEnum.MANGZHONG.name())).append(",6:").append(
  151. getSolarTermNum(year, SolarTermsEnum.XIAZHI.name())).append(",7:").append(
  152. getSolarTermNum(year, SolarTermsEnum.XIAOSHU.name())).append(",7:").append(
  153. getSolarTermNum(year, SolarTermsEnum.DASHU.name())).append(",8:").append(
  154. getSolarTermNum(year, SolarTermsEnum.LIQIU.name())).append(",8:").append(
  155. getSolarTermNum(year, SolarTermsEnum.CHUSHU.name())).append(",9:").append(
  156. getSolarTermNum(year, SolarTermsEnum.BAILU.name())).append(",9:").append(
  157. getSolarTermNum(year, SolarTermsEnum.QIUFEN.name())).append(",10:").append(
  158. getSolarTermNum(year, SolarTermsEnum.HANLU.name())).append(",10:").append(
  159. getSolarTermNum(year, SolarTermsEnum.SHUANGJIANG.name())).append(",11:").append(
  160. getSolarTermNum(year, SolarTermsEnum.LIDONG.name())).append(",11:").append(
  161. getSolarTermNum(year, SolarTermsEnum.XIAOXUE.name())).append(",12:").append(
  162. getSolarTermNum(year, SolarTermsEnum.DAXUE.name())).append(",12:").append(
  163. getSolarTermNum(year, SolarTermsEnum.DONGZHI.name())).append(",1:").append(
  164. getSolarTermNum(year, SolarTermsEnum.XIAOHAN.name())).append(",1:").append(
  165. getSolarTermNum(year, SolarTermsEnum.DAHAN.name()));
  166. return sb.toString();
  167. }
  168. public static int[][] genSolarTermsDays() {
  169. Calendar cal = Calendar.getInstance();
  170. int year = cal.get(Calendar.YEAR);
  171. return linear2TwoDimensional(solarTermToString(year).split(","));
  172. }
  173. /** * 一位数组转换为二维数组 * * @param arr * @return */
  174. public static int[][] linear2TwoDimensional(String[] arr) {
  175. int s[][] = new int[arr.length][];// 声明一个二维数组
  176. for (int i = 0; i < arr.length; i++) {
  177. String[] sdate = arr[i].split(":");
  178. int[] idate = new int[sdate.length];
  179. for (int j = 0; j < sdate.length; j++) {
  180. idate[j] = Integer.valueOf(sdate[j].trim());
  181. }
  182. s[i] = idate;
  183. }
  184. return s;
  185. }
  186. }

发表评论

表情:
评论列表 (有 0 条评论,292人围观)

还没有评论,来说两句吧...

相关阅读

    相关 24点游戏及其算法

    24点游戏及其算法 1.问题描述 24点是棋牌类益智游戏,要求结果等于二十四,一起来玩玩吧!这个游戏用扑克牌更容易来开展。拿一副牌,抽去大小王后(初练也可以把J/Q

    相关 java 24算法实现

      最近闲来无事,突然怀念起小时候和堂兄表姐们经常玩24点游戏,于是就琢磨着是不是开发一个安卓手机版本。然后上网上一搜,发现已经被别人给开发烂了啊。不过这只能说明这个小游戏要想