From 6e6aa91a903e8b45ebb5bf0588db893c67e90e72 Mon Sep 17 00:00:00 2001 From: Zhu Kaixiao <3617246657@qq.com> Date: Fri, 2 Apr 2021 15:15:46 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E8=8E=B7=E5=8F=96=E8=8A=82=E6=B0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/date/ChineseDate.java | 16 +- .../hutool/core/date/chinese/SolarTerms.java | 198 +++++++++++++++++- .../core/date/chinese/SolarTermsTest.java | 80 +++++++ 3 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 hutool-core/src/test/java/cn/hutool/core/date/chinese/SolarTermsTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java index 454e6c197..017f4b473 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java @@ -1,10 +1,7 @@ package cn.hutool.core.date; import cn.hutool.core.convert.NumberChineseFormatter; -import cn.hutool.core.date.chinese.ChineseMonth; -import cn.hutool.core.date.chinese.GanZhi; -import cn.hutool.core.date.chinese.LunarFestival; -import cn.hutool.core.date.chinese.LunarInfo; +import cn.hutool.core.date.chinese.*; import cn.hutool.core.util.StrUtil; import java.util.Date; @@ -264,6 +261,15 @@ public class ChineseDate { return null; } + + /** + * 获得节气 + * @return 获得节气 + */ + public String getTerm() { + return SolarTerms.getTerm(gyear, gmonth, gday); + } + /** * 转换为标准的日期格式来表示农历日期,例如2020-01-13 * @@ -347,4 +353,4 @@ public class ChineseDate { // ------------------------------------------------------- private method end -} \ No newline at end of file +} diff --git a/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java b/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java index 597e60bc2..84d65671a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java @@ -1,15 +1,132 @@ package cn.hutool.core.date.chinese; +import cn.hutool.core.date.ChineseDate; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.NumberUtil; +import java.time.LocalDate; +import java.util.Date; + /** * 24节气相关信息 * - * @author looly + * @author looly, zak * @since 5.4.1 */ public class SolarTerms { + /** + * 24节气 + */ + public static final String[] TERMS = { + "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", + "清明", "谷雨", "立夏", "小满", "芒种", "夏至", + "小暑", "大暑", "立秋", "处暑", "白露", "秋分", + "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" + }; + + /** + * 小寒 + */ + public static final String XIAO_HAN = TERMS[0]; + /** + * 大寒 + */ + public static final String DA_HAN = TERMS[1]; + /** + * 立春 + */ + public static final String LI_CHUN = TERMS[2]; + /** + * 雨水 + */ + public static final String YU_SHUI = TERMS[3]; + /** + * 惊蛰 + */ + public static final String JING_ZHE = TERMS[4]; + /** + * 春分 + */ + public static final String CHUN_FEN = TERMS[5]; + /** + * 清明 + */ + public static final String QING_MING = TERMS[6]; + /** + * 谷雨 + */ + public static final String GU_YU = TERMS[7]; + /** + * 立夏 + */ + public static final String LI_XIA = TERMS[8]; + /** + * 小满 + */ + public static final String XIAO_MAN = TERMS[9]; + /** + * 芒种 + */ + public static final String MANG_ZHONG = TERMS[10]; + /** + * 夏至 + */ + public static final String XIA_ZHI = TERMS[11]; + /** + * 小暑 + */ + public static final String XIAO_SHU = TERMS[12]; + /** + * 大暑 + */ + public static final String DA_SHU = TERMS[13]; + /** + * 立秋 + */ + public static final String LI_QIU = TERMS[14]; + /** + * 处暑 + */ + public static final String CHU_SHU = TERMS[15]; + /** + * 白露 + */ + public static final String BAI_LU = TERMS[16]; + /** + * 秋分 + */ + public static final String QIU_FEN = TERMS[17]; + /** + * 寒露 + */ + public static final String HAN_LU = TERMS[18]; + /** + * 霜降 + */ + public static final String SHUANG_JIANG = TERMS[19]; + /** + * 立冬 + */ + public static final String LI_DONG = TERMS[20]; + /** + * 小雪 + */ + public static final String XIAO_XUE = TERMS[21]; + /** + * 大雪 + */ + public static final String DA_XUE = TERMS[22]; + /** + * 冬至 + */ + public static final String DONG_ZHI = TERMS[23]; + + + + + /** * 根据节气修正干支月 * @@ -40,6 +157,85 @@ public class SolarTerms { return NumberUtil.parseInt(_calday[n - 1]); } + + + /** + * 根据日期获取节气 + * @param date 日期 + * @return 返回指定日期所处的节气 + */ + public static String getTerm(Date date) { + final DateTime dt = DateUtil.date(date); + return getTerm(dt.year(), dt.month() + 1, dt.dayOfMonth()); + } + + + /** + * 根据农历日期获取节气 + * @param chineseDate 农历日期 + * @return 返回指定日期所处的节气 + */ + public static String getTerm(ChineseDate chineseDate) { + return chineseDate.getTerm(); + } + + /** + * 根据日期获取节气 + * @param date 日期 + * @return 返回指定日期所处的节气 + */ + public static String getTerm(LocalDate date) { + return getTerm0(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); + } + + /** + * 根据年月日获取节气 + * @param year 年 + * @param mouth 月 + * @param day 日 + * @return 返回指定年月日所处的节气 + */ + public static String getTerm(int year, int mouth, int day) { + return getTerm(LocalDate.of(year, mouth, day)); + } + + /** + * 根据年月日获取节气, 内部方法,不对月和日做有效校验 + * @param year 年 + * @param mouth 月 + * @param day 日 + * @return 返回指定年月日所处的节气 + */ + static String getTerm0(int year, int mouth, int day) { + if (year < 1900 || year > 2100) { + throw new IllegalArgumentException("只支持1900-2100之间的日期获取节气"); + } + + String termTable = S_TERM_INFO[year - 1900]; + + // 节气速查表中每5个字符含有4个节气,通过月份直接计算偏移 + int segment = (mouth + 1) / 2 - 1; + int termInfo = NumberUtil.parseInt("0x" + termTable.substring(segment * 5, (segment + 1) * 5)); + + String[] segmentTable = new String[24]; + segmentTable[0] = String.valueOf(termInfo).substring(0, 1); + segmentTable[1] = String.valueOf(termInfo).substring(1, 3); + segmentTable[2] = String.valueOf(termInfo).substring(3, 4); + segmentTable[3] = String.valueOf(termInfo).substring(4, 6); + + // 奇数月份的节气在前2个,偶数月份的节气在后两个 + int segmentOffset = (mouth & 1) == 1 ? 0 : 2; + if (day < NumberUtil.parseInt(segmentTable[segmentOffset])) { + int idx = segment * 4 + segmentOffset - 1; + return TERMS[idx < 0 ? 23 : idx]; + } + if(day >= NumberUtil.parseInt(segmentTable[segmentOffset + 1])) { + return TERMS[segment * 4 + segmentOffset + 1]; + } + return TERMS[segment * 4 + segmentOffset]; + } + + /** * 1900-2100各年的24节气日期速查表 * 此表来自:https://github.com/jjonline/calendar.js/blob/master/calendar.js diff --git a/hutool-core/src/test/java/cn/hutool/core/date/chinese/SolarTermsTest.java b/hutool-core/src/test/java/cn/hutool/core/date/chinese/SolarTermsTest.java new file mode 100644 index 000000000..be8b2b9c7 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/date/chinese/SolarTermsTest.java @@ -0,0 +1,80 @@ +package cn.hutool.core.date.chinese; + +import cn.hutool.core.date.ChineseDate; +import cn.hutool.core.date.DateUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Date; + +import static org.junit.Assert.*; + +public class SolarTermsTest { + + + @Test + public void getTermTest() { + Assert.assertEquals(SolarTerms.DONG_ZHI, SolarTerms.getTerm(2021, 1, 4)); + Assert.assertEquals(SolarTerms.XIAO_HAN, SolarTerms.getTerm(2021, 1, 5)); + Assert.assertEquals(SolarTerms.XIAO_HAN, SolarTerms.getTerm(2021, 1, 19)); + Assert.assertEquals(SolarTerms.DA_HAN, SolarTerms.getTerm(2021, 1, 20)); + Assert.assertEquals(SolarTerms.DA_HAN, SolarTerms.getTerm(2021, 2, 2)); + Assert.assertEquals(SolarTerms.LI_CHUN, SolarTerms.getTerm(2021, 2, 3)); + Assert.assertEquals(SolarTerms.LI_CHUN, SolarTerms.getTerm(2021, 2, 17)); + Assert.assertEquals(SolarTerms.YU_SHUI, SolarTerms.getTerm(2021, 2, 18)); + Assert.assertEquals(SolarTerms.YU_SHUI, SolarTerms.getTerm(2021, 3, 4)); + Assert.assertEquals(SolarTerms.JING_ZHE, SolarTerms.getTerm(2021, 3, 5)); + Assert.assertEquals(SolarTerms.JING_ZHE, SolarTerms.getTerm(2021, 3, 19)); + Assert.assertEquals(SolarTerms.CHUN_FEN, SolarTerms.getTerm(2021, 3, 20)); + Assert.assertEquals(SolarTerms.CHUN_FEN, SolarTerms.getTerm(2021, 4, 3)); + Assert.assertEquals(SolarTerms.QING_MING, SolarTerms.getTerm(2021, 4, 4)); + Assert.assertEquals(SolarTerms.QING_MING, SolarTerms.getTerm(2021, 4, 10)); + Assert.assertEquals(SolarTerms.QING_MING, SolarTerms.getTerm(2021, 4, 19)); + Assert.assertEquals(SolarTerms.GU_YU, SolarTerms.getTerm(2021, 4, 20)); + Assert.assertEquals(SolarTerms.GU_YU, SolarTerms.getTerm(2021, 4, 29)); + Assert.assertEquals(SolarTerms.GU_YU, SolarTerms.getTerm(2021, 5, 4)); + Assert.assertEquals(SolarTerms.LI_XIA, SolarTerms.getTerm(2021, 5, 5)); + Assert.assertEquals(SolarTerms.LI_XIA, SolarTerms.getTerm(2021, 5, 9)); + Assert.assertEquals(SolarTerms.LI_XIA, SolarTerms.getTerm(2021, 5, 20)); + Assert.assertEquals(SolarTerms.XIAO_MAN, SolarTerms.getTerm(2021, 5, 21)); + Assert.assertEquals(SolarTerms.XIAO_MAN, SolarTerms.getTerm(2021, 6, 4)); + Assert.assertEquals(SolarTerms.MANG_ZHONG, SolarTerms.getTerm(2021, 6, 5)); + Assert.assertEquals(SolarTerms.MANG_ZHONG, SolarTerms.getTerm(2021, 6, 20)); + Assert.assertEquals(SolarTerms.XIA_ZHI, SolarTerms.getTerm(2021, 6, 21)); + Assert.assertEquals(SolarTerms.XIA_ZHI, SolarTerms.getTerm(2021, 7, 6)); + Assert.assertEquals(SolarTerms.XIAO_SHU, SolarTerms.getTerm(2021, 7, 7)); + Assert.assertEquals(SolarTerms.XIAO_SHU, SolarTerms.getTerm(2021, 7, 21)); + Assert.assertEquals(SolarTerms.DA_SHU, SolarTerms.getTerm(2021, 7, 22)); + Assert.assertEquals(SolarTerms.DA_SHU, SolarTerms.getTerm(2021, 8, 6)); + Assert.assertEquals(SolarTerms.LI_QIU, SolarTerms.getTerm(2021, 8, 7)); + Assert.assertEquals(SolarTerms.CHU_SHU, SolarTerms.getTerm(2021, 8, 23)); + Assert.assertEquals(SolarTerms.CHU_SHU, SolarTerms.getTerm(2021, 9, 6)); + Assert.assertEquals(SolarTerms.BAI_LU, SolarTerms.getTerm(2021, 9, 7)); + Assert.assertEquals(SolarTerms.BAI_LU, SolarTerms.getTerm(2021, 9, 22)); + Assert.assertEquals(SolarTerms.QIU_FEN, SolarTerms.getTerm(2021, 9, 23)); + Assert.assertEquals(SolarTerms.QIU_FEN, SolarTerms.getTerm(2021, 10, 7)); + Assert.assertEquals(SolarTerms.HAN_LU, SolarTerms.getTerm(2021, 10, 8)); + Assert.assertEquals(SolarTerms.HAN_LU, SolarTerms.getTerm(2021, 10, 22)); + Assert.assertEquals(SolarTerms.SHUANG_JIANG, SolarTerms.getTerm(2021, 10, 23)); + Assert.assertEquals(SolarTerms.SHUANG_JIANG, SolarTerms.getTerm(2021, 11, 6)); + Assert.assertEquals(SolarTerms.LI_DONG, SolarTerms.getTerm(2021, 11, 7)); + Assert.assertEquals(SolarTerms.LI_DONG, SolarTerms.getTerm(2021, 11, 21)); + Assert.assertEquals(SolarTerms.XIAO_XUE, SolarTerms.getTerm(2021, 11, 22)); + Assert.assertEquals(SolarTerms.XIAO_XUE, SolarTerms.getTerm(2021, 12, 6)); + Assert.assertEquals(SolarTerms.DA_XUE, SolarTerms.getTerm(2021, 12, 7)); + Assert.assertEquals(SolarTerms.DA_XUE, SolarTerms.getTerm(2021, 12, 20)); + Assert.assertEquals(SolarTerms.DONG_ZHI, SolarTerms.getTerm(2021, 12, 21)); + } + + + @Test + public void getTermByDateTest() { + Assert.assertEquals(SolarTerms.CHUN_FEN, SolarTerms.getTerm(DateUtil.parseDate("2021-04-02"))); + } + + + @Test + public void getTermByChineseDateTest() { + Assert.assertEquals(SolarTerms.QING_MING, SolarTerms.getTerm(new ChineseDate(2021, 2, 25))); + } +} From d244650ebc09c24ce60f3f93a8ef35a68de95205 Mon Sep 17 00:00:00 2001 From: Zhu Kaixiao <3617246657@qq.com> Date: Fri, 2 Apr 2021 15:27:13 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/date/chinese/SolarTerms.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java b/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java index 84d65671a..28754c08c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/chinese/SolarTerms.java @@ -166,7 +166,7 @@ public class SolarTerms { */ public static String getTerm(Date date) { final DateTime dt = DateUtil.date(date); - return getTerm(dt.year(), dt.month() + 1, dt.dayOfMonth()); + return getTerm0(dt.year(), dt.month() + 1, dt.dayOfMonth()); }