diff --git a/README.md b/README.md index 7802e38..80c8325 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ lunar是一款无第三方依赖的公历(阳历)、农历(阴历、老黄历) cn.6tail lunar - 1.2.28 + 1.2.29 ``` diff --git a/README_EN.md b/README_EN.md index cd74f53..8e44a4b 100644 --- a/README_EN.md +++ b/README_EN.md @@ -12,7 +12,7 @@ lunar is a calendar library for Solar and Chinese Lunar. cn.6tail lunar - 1.2.28 + 1.2.29 ``` diff --git a/pom.xml b/pom.xml index 9e18491..c853312 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ cn.6tail lunar jar - 1.2.28 + 1.2.29 ${project.groupId}:${project.artifactId} https://github.com/6tail/lunar-java a calendar library for Solar and Chinese Lunar diff --git a/src/main/java/com/nlf/calendar/ExactDate.java b/src/main/java/com/nlf/calendar/ExactDate.java index a625132..70971ae 100644 --- a/src/main/java/com/nlf/calendar/ExactDate.java +++ b/src/main/java/com/nlf/calendar/ExactDate.java @@ -52,27 +52,7 @@ public class ExactDate { * @return 天数 */ public static int getDaysBetween(int ay, int am, int ad, int by, int bm, int bd) { - int n; - int days; - int i; - if (ay == by) { - n = SolarUtil.getDaysInYear(by, bm, bd) - SolarUtil.getDaysInYear(ay, am, ad); - } else if (ay > by) { - days = SolarUtil.getDaysOfYear(by) - SolarUtil.getDaysInYear(by, bm, bd); - for (i = by + 1; i < ay; i++) { - days += SolarUtil.getDaysOfYear(i); - } - days += SolarUtil.getDaysInYear(ay, am, ad); - n = -days; - } else { - days = SolarUtil.getDaysOfYear(ay) - SolarUtil.getDaysInYear(ay, am, ad); - for (i = ay + 1; i < by; i++) { - days += SolarUtil.getDaysOfYear(i); - } - days += SolarUtil.getDaysInYear(by, bm, bd); - n = days; - } - return n; + return SolarUtil.getDaysBetween(ay, am, ad, by, bm, bd); } /** @@ -83,6 +63,6 @@ public class ExactDate { * @return 天数 */ public static int getDaysBetween(Calendar calendar0, Calendar calendar1) { - return getDaysBetween(calendar0.get(Calendar.YEAR), calendar0.get(Calendar.MONTH) + 1, calendar0.get(Calendar.DATE), calendar1.get(Calendar.YEAR), calendar1.get(Calendar.MONTH) + 1, calendar1.get(Calendar.DATE)); + return SolarUtil.getDaysBetween(calendar0.get(Calendar.YEAR), calendar0.get(Calendar.MONTH) + 1, calendar0.get(Calendar.DATE), calendar1.get(Calendar.YEAR), calendar1.get(Calendar.MONTH) + 1, calendar1.get(Calendar.DATE)); } } diff --git a/src/main/java/com/nlf/calendar/Solar.java b/src/main/java/com/nlf/calendar/Solar.java index 6d50e48..079d116 100644 --- a/src/main/java/com/nlf/calendar/Solar.java +++ b/src/main/java/com/nlf/calendar/Solar.java @@ -277,64 +277,38 @@ public class Solar { public static List fromBaZi(String yearGanZhi, String monthGanZhi, String dayGanZhi, String timeGanZhi, int sect, int baseYear) { sect = (1 == sect) ? 1 : 2; List l = new ArrayList(); - Solar today = new Solar(); - Lunar lunar = today.getLunar(); - int offsetYear = LunarUtil.getJiaZiIndex(lunar.getYearInGanZhiExact()) - LunarUtil.getJiaZiIndex(yearGanZhi); - if (offsetYear < 0) { - offsetYear = offsetYear + 60; + List years = new ArrayList(); + Solar today = fromDate(new Date()); + int offsetYear = LunarUtil.getJiaZiIndex(today.getLunar().getYearInGanZhiExact())-LunarUtil.getJiaZiIndex(yearGanZhi); + if(offsetYear < 0){ + offsetYear += 60; + } + int startYear = today.getYear() - offsetYear - 1; + while (startYear >= baseYear) { + years.add(startYear); + startYear -= 60; } - int startYear = lunar.getYear() - offsetYear; int hour = 0; String timeZhi = timeGanZhi.substring(1); - for (int i = 0, j = LunarUtil.ZHI.length; i < j; i++) { - if (LunarUtil.ZHI[i].equals(timeZhi)) { + for(int i = 0, j = LunarUtil.ZHI.length; i < j; i++){ + if(LunarUtil.ZHI[i].equals(timeZhi)){ hour = (i - 1) * 2; } } - while (startYear >= baseYear) { - int year = startYear - 1; - int counter = 0; - int month = 12; - int day; - boolean found = false; - while (counter < 15) { - if (year >= baseYear) { - day = 1; - Solar solar = new Solar(year, month, day, hour, 0, 0); - lunar = solar.getLunar(); - if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi)) { - found = true; - break; - } - } - month++; - if (month > 12) { - month = 1; - year++; - } - counter++; - } - if (found) { - counter = 0; - month--; - if (month < 1) { - month = 12; - year--; - } - day = 1; - Solar solar = new Solar(year, month, day, hour, 0, 0); - while (counter < 61) { - lunar = solar.getLunar(); + for (Integer integer : years) { + inner: for (int x = 0; x < 3; x++) { + int year = integer + x; + Solar solar = fromYmdHms(year, 1, 1, hour, 0, 0); + while (solar.getYear() == year) { + Lunar lunar = solar.getLunar(); String dgz = (2 == sect) ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact(); if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi) && dgz.equals(dayGanZhi) && lunar.getTimeInGanZhi().equals(timeGanZhi)) { l.add(solar); - break; + break inner; } solar = solar.next(1); - counter++; } } - startYear -= 60; } return l; } diff --git a/src/main/java/com/nlf/calendar/util/SolarUtil.java b/src/main/java/com/nlf/calendar/util/SolarUtil.java index 3f70559..2d47a13 100644 --- a/src/main/java/com/nlf/calendar/util/SolarUtil.java +++ b/src/main/java/com/nlf/calendar/util/SolarUtil.java @@ -157,6 +157,9 @@ public class SolarUtil { * @return 天数 */ public static int getDaysOfYear(int year) { + if (1582 == year) { + return 355; + } return isLeapYear(year) ? 366 : 365; } @@ -193,10 +196,15 @@ public class SolarUtil { for (int i = 1; i < month; i++) { days += getDaysOfMonth(year, i); } - days += day; - if (1582 == year && 10 == month && day >= 15) { - days -= 10; + int d = day; + if (1582 == year && 10 == month) { + if (day >= 15) { + d -= 10; + } else if (day > 4) { + throw new IllegalArgumentException(String.format("wrong solar year %d month %d day %d", year, month, day)); + } } + days += d; return days; } @@ -213,4 +221,64 @@ public class SolarUtil { int week = ExactDate.fromYmd(year, month, 1).get(Calendar.DAY_OF_WEEK) - 1; return (int) Math.ceil((days + week - start) * 1D / WEEK.length); } + + /** + * 获取两个日期之间相差的天数(如果日期a比日期b小,天数为正,如果日期a比日期b大,天数为负) + * + * @param ay 年a + * @param am 月a + * @param ad 日a + * @param by 年b + * @param bm 月b + * @param bd 日b + * @return 天数 + */ + public static int getDaysBetween(int ay, int am, int ad, int by, int bm, int bd) { + int n; + int days; + int i; + if (ay == by) { + n = getDaysInYear(by, bm, bd) - getDaysInYear(ay, am, ad); + } else if (ay > by) { + days = getDaysOfYear(by) - getDaysInYear(by, bm, bd); + for (i = by + 1; i < ay; i++) { + days += getDaysOfYear(i); + } + days += getDaysInYear(ay, am, ad); + n = -days; + } else { + days = getDaysOfYear(ay) - getDaysInYear(ay, am, ad); + for (i = ay + 1; i < by; i++) { + days += getDaysOfYear(i); + } + days += getDaysInYear(by, bm, bd); + n = days; + } + return n; + } + + public static int getWeek(int y, int m, int d) { + if (1582 == y && 10 == m) { + if (d > 4 && d < 15) { + throw new IllegalArgumentException(String.format("wrong solar year %d month %d day %d", y, m, d)); + } + } + Calendar start = ExactDate.fromYmd(1582, 10, 15); + Calendar current = ExactDate.fromYmd(y, m, d); + // 蔡勒公式 + if (m < 3) { + m += 12; + y--; + } + int c = y/100; + y = y - c * 100; + int w; + int x = y + y / 4 + c / 4 - 2 * c; + if (current.before(start)) { + w = (x + (13*(m+1))/5 + d + 2) % 7; + } else { + w = (x + (26*(m+1))/10 + d - 1) % 7; + } + return (w + 7) % 7; + } } diff --git a/src/test/java/test/BaZiTest.java b/src/test/java/test/BaZiTest.java index abd80a0..9f89c9f 100644 --- a/src/test/java/test/BaZiTest.java +++ b/src/test/java/test/BaZiTest.java @@ -6,6 +6,7 @@ import com.nlf.calendar.Solar; import org.junit.Assert; import org.junit.Test; +import java.util.ArrayList; import java.util.List; /** @@ -250,20 +251,71 @@ public class BaZiTest { @Test public void testBaZi2Solar() { - Solar solar = Solar.fromYmdHms(2027,1,27,12,0,0); - System.out.println(solar.getLunar().getEightChar().toString()); - List l = Solar.fromBaZi("丙午","辛丑","丙午","甲午"); - for(Solar s:l){ - System.out.println(s.toFullString()); + List l = Solar.fromBaZi("丙辰","丁酉","丙子","甲午"); + List actual = new ArrayList(); + for (Solar solar : l) { + actual.add(solar.toYmdHms()); } + + List expected = new ArrayList(); + expected.add("1976-09-21 12:00:00"); + expected.add("1916-10-06 12:00:00"); + Assert.assertEquals(expected, actual); } @Test public void testBaZi2Solar1() { List l = Solar.fromBaZi("壬寅","庚戌","己未","乙亥"); - for(Solar s:l){ - System.out.println(s.toFullString()); + List actual = new ArrayList(); + for (Solar solar : l) { + actual.add(solar.toYmdHms()); } + + List expected = new ArrayList(); + expected.add("2022-11-02 22:00:00"); + Assert.assertEquals(expected, actual); + } + + @Test + public void testBaZi2Solar2() { + List l = Solar.fromBaZi("己卯","辛未","甲戌","壬申"); + List actual = new ArrayList(); + for (Solar solar : l) { + actual.add(solar.toYmdHms()); + } + + List expected = new ArrayList(); + expected.add("1999-07-21 16:00:00"); + expected.add("1939-08-05 16:00:00"); + Assert.assertEquals(expected, actual); + } + + @Test + public void testBaZi2Solar3() { + List l = Solar.fromBaZi("庚子","戊子","己卯","庚午"); + List actual = new ArrayList(); + for (Solar solar : l) { + actual.add(solar.toYmdHms()); + } + + List expected = new ArrayList(); + expected.add("1960-12-17 12:00:00"); + expected.add("1901-01-01 12:00:00"); + Assert.assertEquals(expected, actual); + } + + @Test + public void testBaZi2Solar4() { + List l = Solar.fromBaZi("庚子","癸未","乙丑","丁亥"); + List actual = new ArrayList(); + for (Solar solar : l) { + actual.add(solar.toYmdHms()); + } + + List expected = new ArrayList(); + expected.add("2020-07-21 22:00:00"); + expected.add("1960-08-05 22:00:00"); + Assert.assertEquals(expected, actual); } @Test diff --git a/src/test/java/test/LunarTest.java b/src/test/java/test/LunarTest.java index 641dfcd..08d952f 100644 --- a/src/test/java/test/LunarTest.java +++ b/src/test/java/test/LunarTest.java @@ -447,4 +447,16 @@ public class LunarTest { Assert.assertEquals("秋社", lunar.getOtherFestivals().get(0)); } + @Test + public void test62() { + Lunar lunar = Lunar.fromYmd(1582, 9, 18); + Assert.assertEquals("1582-10-04", lunar.getSolar().toString()); + } + + @Test + public void test63() { + Lunar lunar = Lunar.fromYmd(1582, 9, 19); + Assert.assertEquals("1582-10-15", lunar.getSolar().toString()); + } + } diff --git a/src/test/java/test/SolarTest.java b/src/test/java/test/SolarTest.java index 3a3adc6..c352107 100644 --- a/src/test/java/test/SolarTest.java +++ b/src/test/java/test/SolarTest.java @@ -79,4 +79,70 @@ public class SolarTest { Assert.assertEquals("全国中小学生安全教育日",solar.getFestivals().get(0)); } + @Test + public void test12(){ + Solar solar = new Solar(2022, 1, 1); + Assert.assertEquals("2022-01-02", solar.next(1).toYmd()); + } + + @Test + public void test13(){ + Solar solar = new Solar(2022, 1, 31); + Assert.assertEquals("2022-02-01", solar.next(1).toYmd()); + } + + @Test + public void test14(){ + Solar solar = new Solar(2022, 1, 1); + Assert.assertEquals("2023-01-01", solar.next(365).toYmd()); + } + + @Test + public void test15(){ + Solar solar = new Solar(2023, 1, 1); + Assert.assertEquals("2022-01-01", solar.next(-365).toYmd()); + } + + @Test + public void test16(){ + Solar solar = new Solar(1582, 10, 4); + Assert.assertEquals("1582-10-15", solar.next(1).toYmd()); + } + + @Test + public void test17(){ + Solar solar = new Solar(1582, 10, 4); + Assert.assertEquals("1582-11-01", solar.next(18).toYmd()); + } + + @Test + public void test18(){ + Solar solar = new Solar(1582, 11, 1); + Assert.assertEquals("1582-10-04", solar.next(-18).toYmd()); + } + + @Test + public void test19(){ + Solar solar = new Solar(1582, 11, 1); + Assert.assertEquals("1582-10-15", solar.next(-17).toYmd()); + } + + @Test + public void test20(){ + int days = SolarUtil.getDaysBetween(1582, 10, 4, 1582, 10, 15); + Assert.assertEquals(1, days); + } + + @Test + public void test21(){ + int days = SolarUtil.getDaysBetween(1582, 10, 4, 1582, 11, 1); + Assert.assertEquals(18, days); + } + + @Test + public void test22(){ + int days = SolarUtil.getDaysBetween(1582, 1, 1, 1583, 1, 1); + Assert.assertEquals(355, days); + } + } diff --git a/src/test/java/test/WeekTest.java b/src/test/java/test/WeekTest.java index fd79e4b..091f11a 100644 --- a/src/test/java/test/WeekTest.java +++ b/src/test/java/test/WeekTest.java @@ -1,5 +1,6 @@ package test; +import com.nlf.calendar.Solar; import com.nlf.calendar.SolarWeek; import com.nlf.calendar.util.SolarUtil; import org.junit.Assert; @@ -41,4 +42,16 @@ public class WeekTest { //当周第一天(本月) Assert.assertEquals("2019-05-01",week.getFirstDayInMonth().toString()); } + + @Test + public void test1(){ + Solar solar = Solar.fromYmd(1582, 10, 1); + Assert.assertEquals(1, solar.getWeek()); + } + + @Test + public void test2(){ + Solar solar = Solar.fromYmd(1582, 10, 15); + Assert.assertEquals(5, solar.getWeek()); + } }