diff --git a/README.md b/README.md index 80c8325..861d7b8 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ lunar是一款无第三方依赖的公历(阳历)、农历(阴历、老黄历) cn.6tail lunar - 1.2.29 + 1.3.0 ``` diff --git a/README_EN.md b/README_EN.md index 8e44a4b..933a44c 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.29 + 1.3.0 ``` diff --git a/pom.xml b/pom.xml index c853312..f646396 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ cn.6tail lunar jar - 1.2.29 + 1.3.0 ${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 deleted file mode 100644 index 70971ae..0000000 --- a/src/main/java/com/nlf/calendar/ExactDate.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.nlf.calendar; - -import com.nlf.calendar.util.SolarUtil; - -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - -/** - * 精确日期 - * - * @author 6tail - */ -public class ExactDate { - - /** - * 时区 - */ - private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT+8"); - - @SuppressWarnings("MagicConstant") - public static Calendar fromYmdHms(int year, int month, int day, int hour, int minute, int second) { - Calendar c = Calendar.getInstance(TIME_ZONE); - c.set(year, month - 1, day, hour, minute, second); - c.set(Calendar.MILLISECOND, 0); - if (0 == year) { - c.add(Calendar.YEAR, 1); - } - return c; - } - - public static Calendar fromYmd(int year, int month, int day) { - return fromYmdHms(year, month, day, 0, 0, 0); - } - - public static Calendar fromDate(Date date) { - Calendar c = Calendar.getInstance(TIME_ZONE); - c.setTime(date); - c.set(Calendar.MILLISECOND, 0); - return c; - } - - /** - * 获取两个日期之间相差的天数(如果日期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) { - return SolarUtil.getDaysBetween(ay, am, ad, by, bm, bd); - } - - /** - * 获取两个日期之间相差的天数(如果日期a比日期b小,天数为正,如果日期a比日期b大,天数为负) - * - * @param calendar0 日期a - * @param calendar1 日期b - * @return 天数 - */ - public static int getDaysBetween(Calendar calendar0, Calendar calendar1) { - 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/Lunar.java b/src/main/java/com/nlf/calendar/Lunar.java index c81fc4b..37a81d9 100644 --- a/src/main/java/com/nlf/calendar/Lunar.java +++ b/src/main/java/com/nlf/calendar/Lunar.java @@ -190,20 +190,16 @@ public Lunar(int lunarYear, int lunarMonth, int lunarDay, int hour, int minute, } /** - * 通过阳历日期初始化 + * 通过阳历初始化 * - * @param date 阳历日期 + * @param solar 阳历 */ - public Lunar(Date date) { - solar = new Solar(date); - int currentYear = solar.getYear(); - int currentMonth = solar.getMonth(); - int currentDay = solar.getDay(); - LunarYear ly = LunarYear.fromYear(currentYear); + public Lunar(Solar solar) { + LunarYear ly = LunarYear.fromYear(solar.getYear()); for (LunarMonth m : ly.getMonths()) { // 初一 Solar firstDay = Solar.fromJulianDay(m.getFirstJulianDay()); - int days = ExactDate.getDaysBetween(firstDay.getYear(), firstDay.getMonth(), firstDay.getDay(), currentYear, currentMonth, currentDay); + int days = solar.subtract(firstDay); if (days < m.getDayCount()) { year = m.getYear(); month = m.getMonth(); @@ -214,9 +210,19 @@ public Lunar(Date date) { hour = solar.getHour(); minute = solar.getMinute(); second = solar.getSecond(); + this.solar = solar; compute(ly); } + /** + * 通过阳历日期初始化 + * + * @param date 阳历日期 + */ + public Lunar(Date date) { + this(Solar.fromDate(date)); + } + /** * 计算节气表 */ @@ -2175,13 +2181,13 @@ public NineStar getDayNineStar() { String solarNiZiYmd = solarNiZi.toYmd(); int offset = 0; if (solarYmd.compareTo(solarShunBaiYmd) >= 0 && solarYmd.compareTo(solarNiZiYmd) < 0) { - offset = ExactDate.getDaysBetween(solarShunBai.getCalendar(), this.getSolar().getCalendar()) % 9; + offset = solar.subtract(solarShunBai) % 9; } else if (solarYmd.compareTo(solarNiZiYmd) >= 0 && solarYmd.compareTo(solarShunBaiYmd2) < 0) { - offset = 8 - (ExactDate.getDaysBetween(solarNiZi.getCalendar(), this.getSolar().getCalendar()) % 9); + offset = 8 - (solar.subtract(solarNiZi) % 9); } else if (solarYmd.compareTo(solarShunBaiYmd2) >= 0) { - offset = ExactDate.getDaysBetween(solarShunBai2.getCalendar(), this.getSolar().getCalendar()) % 9; + offset = solar.subtract(solarShunBai2) % 9; } else if (solarYmd.compareTo(solarShunBaiYmd) < 0) { - offset = (8 + ExactDate.getDaysBetween(this.getSolar().getCalendar(), solarShunBai.getCalendar())) % 9; + offset = (8 + solarShunBai.subtract(solar)) % 9; } return NineStar.fromIndex(offset); } @@ -2884,23 +2890,23 @@ public String getTimeXunKong() { * @return 数九,如果不是数九天,返回null */ public ShuJiu getShuJiu() { - Calendar currentCalendar = ExactDate.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay()); + Solar current = Solar.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay()); Solar start = jieQi.get("DONG_ZHI"); - Calendar startCalendar = ExactDate.fromYmd(start.getYear(), start.getMonth(), start.getDay()); + start = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay()); - if (currentCalendar.compareTo(startCalendar) < 0) { + if (current.isBefore(start)) { start = jieQi.get("冬至"); - startCalendar = ExactDate.fromYmd(start.getYear(), start.getMonth(), start.getDay()); + start = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay()); } - Calendar endCalendar = ExactDate.fromYmd(start.getYear(), start.getMonth(), start.getDay()); - endCalendar.add(Calendar.DATE, 81); + Solar end = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay()); + end = end.next(81); - if (currentCalendar.compareTo(startCalendar) < 0 || currentCalendar.compareTo(endCalendar) >= 0) { + if (current.isBefore(start) || !current.isBefore(end)) { return null; } - int days = ExactDate.getDaysBetween(startCalendar, currentCalendar); + int days = current.subtract(start); return new ShuJiu(LunarUtil.NUMBER[days / 9 + 1] + "九", days % 9 + 1); } @@ -2910,10 +2916,10 @@ public ShuJiu getShuJiu() { * @return 三伏,如果不是伏天,返回null */ public Fu getFu() { - Calendar currentCalendar = ExactDate.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay()); + Solar current = Solar.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay()); Solar xiaZhi = jieQi.get("夏至"); Solar liQiu = jieQi.get("立秋"); - Calendar startCalendar = ExactDate.fromYmd(xiaZhi.getYear(), xiaZhi.getMonth(), xiaZhi.getDay()); + Solar start = Solar.fromYmd(xiaZhi.getYear(), xiaZhi.getMonth(), xiaZhi.getDay()); // 第1个庚日 int add = 6 - xiaZhi.getLunar().getDayGanIndex(); if (add < 0) { @@ -2921,34 +2927,31 @@ public Fu getFu() { } // 第3个庚日,即初伏第1天 add += 20; - startCalendar.add(Calendar.DATE, add); + start = start.next(add); // 初伏以前 - if (currentCalendar.compareTo(startCalendar) < 0) { + if (current.isBefore(start)) { return null; } - int days = ExactDate.getDaysBetween(startCalendar, currentCalendar); + int days = current.subtract(start); if (days < 10) { return new Fu("初伏", days + 1); } // 第4个庚日,中伏第1天 - startCalendar.add(Calendar.DATE, 10); - - days = ExactDate.getDaysBetween(startCalendar, currentCalendar); + start = start.next(10); + days = current.subtract(start); if (days < 10) { return new Fu("中伏", days + 1); } // 第5个庚日,中伏第11天或末伏第1天 - startCalendar.add(Calendar.DATE, 10); - - Calendar liQiuCalendar = ExactDate.fromYmd(liQiu.getYear(), liQiu.getMonth(), liQiu.getDay()); - - days = ExactDate.getDaysBetween(startCalendar, currentCalendar); + start = start.next(10); + days = current.subtract(start); + Solar liQiuSolar = Solar.fromYmd(liQiu.getYear(), liQiu.getMonth(), liQiu.getDay()); // 末伏 - if (liQiuCalendar.compareTo(startCalendar) <= 0) { + if (!liQiuSolar.isAfter(start)) { if (days < 10) { return new Fu("末伏", days + 1); } @@ -2958,8 +2961,8 @@ public Fu getFu() { return new Fu("中伏", days + 11); } // 末伏第1天 - startCalendar.add(Calendar.DATE, 10); - days = ExactDate.getDaysBetween(startCalendar, currentCalendar); + start = start.next(10); + days = current.subtract(start); if (days < 10) { return new Fu("末伏", days + 1); } @@ -2983,17 +2986,14 @@ public String getLiuYao() { */ public String getWuHou() { JieQi jieQi = getPrevJieQi(true); - String name = jieQi.getName(); int offset = 0; for (int i = 0, j = JIE_QI.length; i < j; i++) { - if (name.equals(JIE_QI[i])) { + if (jieQi.getName().equals(JIE_QI[i])) { offset = i; break; } } - Solar startSolar = jieQi.getSolar(); - int days = ExactDate.getDaysBetween(startSolar.getYear(), startSolar.getMonth(), startSolar.getDay(), solar.getYear(), solar.getMonth(), solar.getDay()); - int index = days / 5; + int index = solar.subtract(jieQi.getSolar()) / 5; if (index > 2) { index = 2; } @@ -3007,10 +3007,8 @@ public String getWuHou() { */ public String getHou() { JieQi jieQi = getPrevJieQi(true); - Solar startSolar = jieQi.getSolar(); - int days = ExactDate.getDaysBetween(startSolar.getYear(), startSolar.getMonth(), startSolar.getDay(), solar.getYear(), solar.getMonth(), solar.getDay()); int max = LunarUtil.HOU.length - 1; - int offset = days / 5; + int offset = solar.subtract(jieQi.getSolar()) / 5; if (offset > max) { offset = max; } diff --git a/src/main/java/com/nlf/calendar/Solar.java b/src/main/java/com/nlf/calendar/Solar.java index 079d116..a973507 100644 --- a/src/main/java/com/nlf/calendar/Solar.java +++ b/src/main/java/com/nlf/calendar/Solar.java @@ -1,9 +1,6 @@ package com.nlf.calendar; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; +import java.util.*; import com.nlf.calendar.util.HolidayUtil; import com.nlf.calendar.util.LunarUtil; @@ -15,6 +12,11 @@ * @author 6tail */ public class Solar { + /** + * 时区 + */ + public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT+8"); + /** * 2000年儒略日数(2000-1-1 12:00:00 UTC) */ @@ -50,11 +52,6 @@ public class Solar { */ private final int second; - /** - * 日历 - */ - private final Calendar calendar; - /** * 默认使用当前日期初始化 */ @@ -84,7 +81,20 @@ public Solar(int year, int month, int day) { * @param second 秒钟,0到59 */ public Solar(int year, int month, int day, int hour, int minute, int second) { - calendar = ExactDate.fromYmdHms(year, month, day, hour, minute, second); + if (1582 == year && 10 == month) { + if (day > 4 && day < 15) { + throw new IllegalArgumentException(String.format("wrong solar year %d month %d day %d", year, month, day)); + } + } + if (hour < 0 || hour > 23) { + throw new IllegalArgumentException(String.format("wrong hour %d", hour)); + } + if (minute < 0 || minute > 59) { + throw new IllegalArgumentException(String.format("wrong minute %d", minute)); + } + if (second < 0 || second > 59) { + throw new IllegalArgumentException(String.format("wrong second %d", second)); + } this.year = year; this.month = month; this.day = day; @@ -99,13 +109,15 @@ public Solar(int year, int month, int day, int hour, int minute, int second) { * @param date 日期 */ public Solar(Date date) { - calendar = ExactDate.fromDate(date); - year = calendar.get(Calendar.YEAR); - month = calendar.get(Calendar.MONTH) + 1; - day = calendar.get(Calendar.DATE); - hour = calendar.get(Calendar.HOUR_OF_DAY); - minute = calendar.get(Calendar.MINUTE); - second = calendar.get(Calendar.SECOND); + Calendar c = Calendar.getInstance(TIME_ZONE); + c.setTime(date); + c.set(Calendar.MILLISECOND, 0); + year = c.get(Calendar.YEAR); + month = c.get(Calendar.MONTH) + 1; + day = c.get(Calendar.DATE); + hour = c.get(Calendar.HOUR_OF_DAY); + minute = c.get(Calendar.MINUTE); + second = c.get(Calendar.SECOND); } /** @@ -115,7 +127,6 @@ public Solar(Date date) { */ public Solar(Calendar calendar) { calendar.set(Calendar.MILLISECOND, 0); - this.calendar = calendar; year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; day = calendar.get(Calendar.DATE); @@ -169,8 +180,6 @@ public Solar(double julianDay) { minute -= 60; hour++; } - - calendar = ExactDate.fromYmdHms(year, month, day, hour, minute, second); this.year = year; this.month = month; this.day = day; @@ -295,9 +304,9 @@ public static List fromBaZi(String yearGanZhi, String monthGanZhi, String hour = (i - 1) * 2; } } - for (Integer integer : years) { + for (Integer y : years) { inner: for (int x = 0; x < 3; x++) { - int year = integer + x; + int year = y + x; Solar solar = fromYmdHms(year, 1, 1, hour, 0, 0); while (solar.getYear() == year) { Lunar lunar = solar.getLunar(); @@ -328,7 +337,26 @@ public boolean isLeapYear() { * @return 0123456 */ public int getWeek() { - return calendar.get(Calendar.DAY_OF_WEEK) - 1; + Solar start = fromYmd(1582, 10, 15); + int y = year; + int m = month; + int d = day; + Solar current = fromYmd(y, m, d); + // 蔡勒公式 + if (m < 3) { + m += 12; + y--; + } + int c = y / 100; + y = y - c * 100; + int x = y + y / 4 + c / 4 - 2 * c; + int w; + if (current.isBefore(start)) { + w = (x + 13 * (m + 1) / 5 + d + 2) % 7; + } else { + w = (x + 26 * (m + 1) / 10 + d - 1) % 7; + } + return (w + 7) % 7; } /** @@ -487,7 +515,7 @@ public int getSecond() { * @return 农历 */ public Lunar getLunar() { - return new Lunar(calendar.getTime()); + return new Lunar(this); } /** @@ -512,15 +540,6 @@ public double getJulianDay() { return (int) (365.25 * (y + 4716)) + (int) (30.6001 * (m + 1)) + d + n - 1524.5; } - /** - * 获取日历 - * - * @return 日历 - */ - public Calendar getCalendar() { - return calendar; - } - @Override public String toString() { return toYmd(); @@ -560,6 +579,155 @@ public String toFullString() { return s.toString(); } + /** + * 阳历日期相减,获得相差天数 + * @param solar 阳历 + * @return 天数 + */ + public int subtract(Solar solar) { + return SolarUtil.getDaysBetween(solar.getYear(), solar.getMonth(), solar.getDay(), year, month, day); + } + + /** + * 阳历日期相减,获得相差分钟数 + * @param solar 阳历 + * @return 分钟数 + */ + public int subtractMinute(Solar solar) { + int days = subtract(solar); + int cm = hour * 60 + minute; + int sm = solar.getHour() * 60 + solar.getMinute(); + int m = cm - sm; + if (m < 0) { + m += 1440; + days--; + } + m += days * 1440; + return m; + } + + /** + * 是否在指定日期之后 + * @param solar 阳历 + * @return true/false + */ + public boolean isAfter(Solar solar) { + if (year > solar.getYear()) { + return true; + } else if (year < solar.getYear()) { + return false; + } + if (month > solar.getMonth()) { + return true; + } else if (month < solar.getMonth()) { + return false; + } + if (day > solar.getDay()) { + return true; + } else if (day < solar.getDay()) { + return false; + } + if (hour > solar.getHour()) { + return true; + } else if (hour < solar.getHour()) { + return false; + } + if (minute > solar.getMinute()) { + return true; + } else if (minute < solar.getMinute()) { + return false; + } + return second > solar.second; + } + + /** + * 是否在指定日期之前 + * @param solar 阳历 + * @return true/false + */ + public boolean isBefore(Solar solar) { + if (year > solar.getYear()) { + return false; + } else if (year < solar.getYear()) { + return true; + } + if (month > solar.getMonth()) { + return false; + } else if (month < solar.getMonth()) { + return true; + } + if (day > solar.getDay()) { + return false; + } else if (day < solar.getDay()) { + return true; + } + if (hour > solar.getHour()) { + return false; + } else if (hour < solar.getHour()) { + return true; + } + if (minute > solar.getMinute()) { + return false; + } else if (minute < solar.getMinute()) { + return true; + } + return second < solar.second; + } + + /** + * 年推移 + * @param years 年数 + * @return 阳历 + */ + public Solar nextYear(int years) { + int y = year + years; + int m = month; + int d = day; + // 2月处理 + if (2 == m) { + if (d > 28) { + if (!SolarUtil.isLeapYear(y)) { + d -= 28; + m++; + } + } + } + if (1582 == y && 10 == m) { + if (d > 4 && d < 15) { + d += 10; + } + } + return fromYmdHms(y, m, d, hour, minute, second); + } + + /** + * 月推移 + * @param months 月数 + * @return 阳历 + */ + public Solar nextMonth(int months) { + SolarMonth month = SolarMonth.fromYm(year, this.month); + month = month.next(months); + int y = month.getYear(); + int m = month.getMonth(); + int d = day; + // 2月处理 + if (2 == m) { + if (d > 28) { + if (!SolarUtil.isLeapYear(y)) { + d -= 28; + m++; + } + } + } + if (1582 == y && 10 == m) { + if (d > 4 && d < 15) { + d += 10; + } + } + return fromYmdHms(y, m, d, hour, minute, second); + } + /** * 获取往后推几天的阳历日期,如果要往前推,则天数用负数 * @@ -567,7 +735,40 @@ public String toFullString() { * @return 阳历日期 */ public Solar next(int days) { - return next(days, false); + int y = year; + int m = month; + int d = day; + if (days > 0) { + d = day + days; + int daysInMonth = SolarUtil.getDaysOfMonth(y, m); + while (d > daysInMonth) { + d -= daysInMonth; + m++; + if (m > 12) { + m -= 12; + y++; + } + daysInMonth = SolarUtil.getDaysOfMonth(y, m); + } + } else if (days < 0) { + int rest = -days; + while (d <= rest) { + rest -= d; + m--; + if (m < 1) { + m = 12; + y--; + } + d = SolarUtil.getDaysOfMonth(y, m); + } + d -= rest; + } + if (1582 == y && 10 == m) { + if (d > 4 && d < 15) { + d += 10; + } + } + return fromYmdHms(y, m, d, hour, minute, second); } /** @@ -578,32 +779,50 @@ public Solar next(int days) { * @return 阳历日期 */ public Solar next(int days, boolean onlyWorkday) { - Calendar c = ExactDate.fromYmdHms(year, month, day, hour, minute, second); - if (0 != days) { - if (!onlyWorkday) { - c.add(Calendar.DATE, days); - } else { - int rest = Math.abs(days); - int add = days < 1 ? -1 : 1; - while (rest > 0) { - c.add(Calendar.DATE, add); - boolean work = true; - Holiday holiday = HolidayUtil.getHoliday(c.get(Calendar.YEAR), c.get(Calendar.MONTH) + 1, c.get(Calendar.DAY_OF_MONTH)); - if (null == holiday) { - int week = c.get(Calendar.DAY_OF_WEEK); - if (1 == week || 7 == week) { - work = false; - } - } else { - work = holiday.isWork(); - } - if (work) { - rest--; + if(!onlyWorkday) { + return next(days); + } + Solar solar = fromYmdHms(year, month, day, hour, minute, second); + if (days != 0) { + int rest = Math.abs(days); + int add = days < 1 ? -1 : 1; + while (rest > 0) { + solar = solar.next(add); + boolean work = true; + Holiday holiday = HolidayUtil.getHoliday(solar.getYear(), solar.getMonth(), solar.getDay()); + if (null == holiday) { + int week = solar.getWeek(); + if (0 == week || 6 == week) { + work = false; } + } else { + work = holiday.isWork(); + } + if (work) { + rest -= 1; } } } - return new Solar(c); + return solar; + } + + /** + * 小时推移 + * @param hours 小时数 + * @return 阳历 + */ + public Solar nextHour(int hours) { + int h = hour + hours; + int n = h < 0 ? -1 : 1; + int hour = Math.abs(h); + int days = hour / 24 * n; + hour = (hour % 24) * n; + if (hour < 0) { + hour += 24; + days--; + } + Solar solar = next(days); + return fromYmdHms(solar.getYear(), solar.getMonth(), solar.getDay(), hour, solar.getMinute(), solar.getSecond()); } } diff --git a/src/main/java/com/nlf/calendar/SolarHalfYear.java b/src/main/java/com/nlf/calendar/SolarHalfYear.java index 8153160..0f3c5a7 100644 --- a/src/main/java/com/nlf/calendar/SolarHalfYear.java +++ b/src/main/java/com/nlf/calendar/SolarHalfYear.java @@ -36,14 +36,15 @@ public SolarHalfYear() { * 通过日期初始化 */ public SolarHalfYear(Date date) { - Calendar c = ExactDate.fromDate(date); - year = c.get(Calendar.YEAR); - month = c.get(Calendar.MONTH) + 1; + Solar solar = Solar.fromDate(date); + year = solar.getYear(); + month = solar.getMonth(); } /** * 通过日历初始化 */ + @Deprecated public SolarHalfYear(Calendar calendar) { year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; @@ -76,6 +77,7 @@ public static SolarHalfYear fromDate(Date date) { * @param calendar 日历 * @return 阳历半年 */ + @Deprecated public static SolarHalfYear fromCalendar(Calendar calendar) { return new SolarHalfYear(calendar); } @@ -125,12 +127,8 @@ public int getIndex() { * @return 推移后的半年 */ public SolarHalfYear next(int halfYears) { - if (0 == halfYears) { - return new SolarHalfYear(year, month); - } - Calendar c = ExactDate.fromYmd(year, month, 1); - c.add(Calendar.MONTH, MONTH_COUNT * halfYears); - return new SolarHalfYear(c); + SolarMonth m = SolarMonth.fromYm(year, month).next(MONTH_COUNT * halfYears); + return new SolarHalfYear(m.getYear(), m.getMonth()); } /** diff --git a/src/main/java/com/nlf/calendar/SolarMonth.java b/src/main/java/com/nlf/calendar/SolarMonth.java index 27410f0..890e2cf 100644 --- a/src/main/java/com/nlf/calendar/SolarMonth.java +++ b/src/main/java/com/nlf/calendar/SolarMonth.java @@ -33,14 +33,15 @@ public SolarMonth() { * 通过日期初始化 */ public SolarMonth(Date date) { - Calendar c = ExactDate.fromDate(date); - year = c.get(Calendar.YEAR); - month = c.get(Calendar.MONTH) + 1; + Solar solar = Solar.fromDate(date); + year = solar.getYear(); + month = solar.getMonth(); } /** * 通过日历初始化 */ + @Deprecated public SolarMonth(Calendar calendar) { year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; @@ -73,6 +74,7 @@ public static SolarMonth fromDate(Date date) { * @param calendar 日历 * @return 阳历月 */ + @Deprecated public static SolarMonth fromCalendar(Calendar calendar) { return new SolarMonth(calendar); } @@ -148,9 +150,18 @@ public List getWeeks(int start) { * @return 阳历月 */ public SolarMonth next(int months) { - Calendar c = ExactDate.fromYmd(year, month, 1); - c.add(Calendar.MONTH, months); - return new SolarMonth(c); + int n = months < 0 ? -1 : 1; + int m = Math.abs(months); + int y = year + m / 12 * n; + m = month + m % 12 * n; + if (m > 12) { + m -= 12; + y++; + } else if (m < 1) { + m += 12; + y--; + } + return new SolarMonth(y, m); } @Override diff --git a/src/main/java/com/nlf/calendar/SolarSeason.java b/src/main/java/com/nlf/calendar/SolarSeason.java index 6bc57f0..b551ae1 100644 --- a/src/main/java/com/nlf/calendar/SolarSeason.java +++ b/src/main/java/com/nlf/calendar/SolarSeason.java @@ -37,14 +37,15 @@ public SolarSeason() { * 通过日期初始化 */ public SolarSeason(Date date) { - Calendar c = ExactDate.fromDate(date); - year = c.get(Calendar.YEAR); - month = c.get(Calendar.MONTH) + 1; + Solar solar = Solar.fromDate(date); + year = solar.getYear(); + month = solar.getMonth(); } /** * 通过日历初始化 */ + @Deprecated public SolarSeason(Calendar calendar) { year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; @@ -77,6 +78,7 @@ public static SolarSeason fromDate(Date date) { * @param calendar 日历 * @return 阳历季度 */ + @Deprecated public static SolarSeason fromCalendar(Calendar calendar) { return new SolarSeason(calendar); } @@ -126,12 +128,8 @@ public int getIndex() { * @return 推移后的季度 */ public SolarSeason next(int seasons) { - if (0 == seasons) { - return new SolarSeason(year, month); - } - Calendar c = ExactDate.fromYmd(year, month, 1); - c.add(Calendar.MONTH, MONTH_COUNT * seasons); - return new SolarSeason(c); + SolarMonth m = SolarMonth.fromYm(year, month).next(MONTH_COUNT * seasons); + return new SolarSeason(m.getYear(), m.getMonth()); } /** diff --git a/src/main/java/com/nlf/calendar/SolarWeek.java b/src/main/java/com/nlf/calendar/SolarWeek.java index 9adecfb..639e364 100644 --- a/src/main/java/com/nlf/calendar/SolarWeek.java +++ b/src/main/java/com/nlf/calendar/SolarWeek.java @@ -48,10 +48,10 @@ public SolarWeek(int start) { * @param start 星期几作为一周的开始,1234560分别代表星期一至星期天 */ public SolarWeek(Date date, int start) { - Calendar c = ExactDate.fromDate(date); - year = c.get(Calendar.YEAR); - month = c.get(Calendar.MONTH) + 1; - day = c.get(Calendar.DATE); + Solar solar = Solar.fromDate(date); + year = solar.getYear(); + month = solar.getMonth(); + day = solar.getDay(); this.start = start; } @@ -60,6 +60,7 @@ public SolarWeek(Date date, int start) { * * @param start 星期几作为一周的开始,1234560分别代表星期一至星期天 */ + @Deprecated public SolarWeek(Calendar calendar, int start) { year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH) + 1; @@ -100,6 +101,7 @@ public static SolarWeek fromDate(Date date, int start) { * @param start 星期几作为一周的开始,1234560分别代表星期一至星期天 * @return 阳历周 */ + @Deprecated public static SolarWeek fromCalendar(Calendar calendar, int start) { return new SolarWeek(calendar, start); } @@ -159,9 +161,7 @@ public int getStart() { * @return 周序号,从1开始 */ public int getIndex() { - Calendar c = ExactDate.fromYmd(year, month, 1); - int firstDayWeek = c.get(Calendar.DAY_OF_WEEK) - 1; - int offset = firstDayWeek - start; + int offset = Solar.fromYmd(year, month, 1).getWeek() - start; if(offset < 0) { offset += 7; } @@ -174,9 +174,7 @@ public int getIndex() { * @return 周序号,从1开始 */ public int getIndexInYear() { - Calendar c = ExactDate.fromYmd(year, 1, 1); - int firstDayWeek = c.get(Calendar.DAY_OF_WEEK) - 1; - int offset = firstDayWeek - start; + int offset = Solar.fromYmd(year, 1, 1).getWeek() - start; if(offset < 0) { offset += 7; } @@ -194,15 +192,15 @@ public SolarWeek next(int weeks, boolean separateMonth) { if (0 == weeks) { return new SolarWeek(year, month, day, start); } + Solar solar = Solar.fromYmd(year, month, day); if (separateMonth) { int n = weeks; - Calendar c = ExactDate.fromYmd(year, month, day); - SolarWeek week = new SolarWeek(c, start); + SolarWeek week = new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start); int month = this.month; boolean plus = n > 0; while (0 != n) { - c.add(Calendar.DATE, plus ? 7 : -7); - week = new SolarWeek(c, start); + solar = solar.next(plus ? 7 : -7); + week = new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start); int weekMonth = week.getMonth(); if (month != weekMonth) { int index = week.getIndex(); @@ -212,8 +210,8 @@ public SolarWeek next(int weeks, boolean separateMonth) { week = new SolarWeek(firstDay.getYear(), firstDay.getMonth(), firstDay.getDay(), start); weekMonth = week.getMonth(); } else { - c = ExactDate.fromYmd(week.getYear(), week.getMonth(), 1); - week = new SolarWeek(c, start); + solar = Solar.fromYmd(week.getYear(), week.getMonth(), 1); + week = new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start); } } else { int size = SolarUtil.getWeeksOfMonth(week.getYear(), week.getMonth(), start); @@ -223,8 +221,8 @@ public SolarWeek next(int weeks, boolean separateMonth) { week = new SolarWeek(lastDay.getYear(), lastDay.getMonth(), lastDay.getDay(), start); weekMonth = week.getMonth(); } else { - c = ExactDate.fromYmd(week.getYear(), week.getMonth(), SolarUtil.getDaysOfMonth(week.getYear(), week.getMonth())); - week = new SolarWeek(c, start); + solar = Solar.fromYmd(week.getYear(), week.getMonth(), SolarUtil.getDaysOfMonth(week.getYear(), week.getMonth())); + week = new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start); } } month = weekMonth; @@ -233,9 +231,8 @@ public SolarWeek next(int weeks, boolean separateMonth) { } return week; } else { - Calendar c = ExactDate.fromYmd(year, month, day); - c.add(Calendar.DATE, weeks * 7); - return new SolarWeek(c, start); + solar = solar.next(weeks * 7); + return new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start); } } @@ -245,14 +242,12 @@ public SolarWeek next(int weeks, boolean separateMonth) { * @return 本周第一天的阳历日期 */ public Solar getFirstDay() { - Calendar c = ExactDate.fromYmd(year, month, day); - int week = c.get(Calendar.DAY_OF_WEEK) - 1; - int prev = week - start; + Solar solar = Solar.fromYmd(year, month, day); + int prev = solar.getWeek() - start; if (prev < 0) { prev += 7; } - c.add(Calendar.DATE, -prev); - return new Solar(c); + return solar.next(-prev); } /** diff --git a/src/main/java/com/nlf/calendar/SolarYear.java b/src/main/java/com/nlf/calendar/SolarYear.java index f5924b0..de0bd65 100644 --- a/src/main/java/com/nlf/calendar/SolarYear.java +++ b/src/main/java/com/nlf/calendar/SolarYear.java @@ -32,13 +32,13 @@ public SolarYear() { * 通过日期初始化 */ public SolarYear(Date date) { - Calendar c = ExactDate.fromDate(date); - year = c.get(Calendar.YEAR); + year = Solar.fromDate(date).getYear(); } /** * 通过日历初始化 */ + @Deprecated public SolarYear(Calendar calendar) { year = calendar.get(Calendar.YEAR); } @@ -68,6 +68,7 @@ public static SolarYear fromDate(Date date) { * @param calendar 日历 * @return 阳历年 */ + @Deprecated public static SolarYear fromCalendar(Calendar calendar) { return new SolarYear(calendar); } @@ -113,9 +114,7 @@ public List getMonths() { * @return 阳历年 */ public SolarYear next(int years) { - Calendar c = ExactDate.fromYmd(year, 1, 1); - c.add(Calendar.YEAR, years); - return new SolarYear(c); + return new SolarYear(year + years); } @Override diff --git a/src/main/java/com/nlf/calendar/eightchar/Yun.java b/src/main/java/com/nlf/calendar/eightchar/Yun.java index a8abbf2..ada093e 100644 --- a/src/main/java/com/nlf/calendar/eightchar/Yun.java +++ b/src/main/java/com/nlf/calendar/eightchar/Yun.java @@ -1,10 +1,11 @@ package com.nlf.calendar.eightchar; -import com.nlf.calendar.*; +import com.nlf.calendar.EightChar; +import com.nlf.calendar.JieQi; +import com.nlf.calendar.Lunar; +import com.nlf.calendar.Solar; import com.nlf.calendar.util.LunarUtil; -import java.util.Calendar; - /** * 运 * @@ -89,7 +90,7 @@ private void computeStart(int sect) { int hour = 0; if (2 == sect) { - long minutes = (end.getCalendar().getTimeInMillis() - start.getCalendar().getTimeInMillis()) / 60000; + long minutes = end.subtractMinute(start); long y = minutes / 4320; minutes -= y * 4320; long m = minutes / 360; @@ -107,7 +108,7 @@ private void computeStart(int sect) { // 时辰差 int hourDiff = endTimeZhiIndex - startTimeZhiIndex; // 天数差 - int dayDiff = ExactDate.getDaysBetween(start.getYear(), start.getMonth(), start.getDay(), end.getYear(), end.getMonth(), end.getDay()); + int dayDiff = end.subtract(start); if (hourDiff < 0) { hourDiff += 12; dayDiff--; @@ -188,13 +189,11 @@ public Lunar getLunar() { * @return 阳历日期 */ public Solar getStartSolar() { - Solar birth = lunar.getSolar(); - Calendar c = ExactDate.fromYmdHms(birth.getYear(), birth.getMonth(), birth.getDay(), birth.getHour(), birth.getMinute(), birth.getSecond()); - c.add(Calendar.YEAR, startYear); - c.add(Calendar.MONTH, startMonth); - c.add(Calendar.DATE, startDay); - c.add(Calendar.HOUR, startHour); - return Solar.fromCalendar(c); + Solar solar = lunar.getSolar(); + solar = solar.nextYear(startYear); + solar = solar.nextMonth(startMonth); + solar = solar.next(startDay); + return solar.nextHour(startHour); } /** diff --git a/src/main/java/com/nlf/calendar/util/SolarUtil.java b/src/main/java/com/nlf/calendar/util/SolarUtil.java index 2d47a13..fdebcf0 100644 --- a/src/main/java/com/nlf/calendar/util/SolarUtil.java +++ b/src/main/java/com/nlf/calendar/util/SolarUtil.java @@ -1,6 +1,6 @@ package com.nlf.calendar.util; -import com.nlf.calendar.ExactDate; +import com.nlf.calendar.Solar; import java.util.*; @@ -217,9 +217,7 @@ public static int getDaysInYear(int year, int month, int day) { * @return 周数 */ public static int getWeeksOfMonth(int year, int month, int start) { - int days = getDaysOfMonth(year, month); - int week = ExactDate.fromYmd(year, month, 1).get(Calendar.DAY_OF_WEEK) - 1; - return (int) Math.ceil((days + week - start) * 1D / WEEK.length); + return (int) Math.ceil((getDaysOfMonth(year, month) + Solar.fromYmd(year, month, 1).getWeek() - start) * 1D / WEEK.length); } /** @@ -257,28 +255,4 @@ public static int getDaysBetween(int ay, int am, int ad, int by, int bm, int bd) 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/TimeTest.java b/src/test/java/test/TimeTest.java index 66a0992..e0ff984 100644 --- a/src/test/java/test/TimeTest.java +++ b/src/test/java/test/TimeTest.java @@ -136,7 +136,7 @@ public class TimeTest { put("2020-4,5,","丙"); put("2020-4,5,23:01:01","戊"); put("2020-4,5,其他","丙"); - put("2020-4,5,80:90","丙"); + put("2020-4,5,0:90","丙"); put("2020-4,5,21:01:01","丁"); @@ -204,7 +204,7 @@ public class TimeTest { put("2020-4,5,","丙子"); put("2020-4,5,23:01:01","戊子"); put("2020-4,5,其他","丙子"); - put("2020-4,5,80:90","丙子"); + put("2020-4,5,0:90","丙子"); put("2020-4,5,20:21:01","丙戌"); put("2020-4,5,21:01:01","丁亥");