diff --git a/CHANGELOG.md b/CHANGELOG.md index a5b15c6de..bf710f0a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -## 5.3.9 (2020-07-07) +## 5.3.9 (2020-07-12) ### 新特性 * 【core 】 DateUtil增加formatChineseDate(pr#932@Github) @@ -11,6 +11,7 @@ * 【core 】 增强StrUtil中空判断后返回数据性能(pr#949@Github) * 【core 】 deprecate掉millsecond,改为millisecond(issue#I1M9P8@Gitee) * 【core 】 增加LocalDateTimeUtil(issue#I1KUVC@Gitee) +* 【core 】 Month增加getLastDay方法 ### Bug修复 * 【core 】 修复NumberUtil.partValue有余数问题(issue#I1KX66@Gitee) @@ -22,6 +23,7 @@ * 【extra 】 修复Ftp中ArrayList长度为负问题(pr#136@Github) * 【core 】 修复Dict中putAll大小写问题(issue#I1MU5B@Gitee) * 【core 】 修复POI中sax读取数字判断错误问题(issue#931@Github) +* 【core 】 修复DateUtil.endOfQuarter错误问题(issue#I1NGZ7@Gitee) ------------------------------------------------------------------------------------------------------------- ## 5.3.8 (2020-06-16) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index ee8ec9e51..705b51670 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -237,11 +237,15 @@ public class CalendarUtil { * @return {@link Calendar} * @since 4.1.0 */ + @SuppressWarnings({"MagicConstant", "ConstantConditions"}) public static Calendar endOfQuarter(Calendar calendar) { - //noinspection MagicConstant - calendar.set(Calendar.MONTH, calendar.get(DateField.MONTH.getValue()) / 3 * 3 + 2); - calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); - return endOfDay(calendar); + final int year = calendar.get(Calendar.YEAR); + final int month = calendar.get(DateField.MONTH.getValue()) / 3 * 3 + 2; + + final Calendar resultCal = Calendar.getInstance(calendar.getTimeZone()); + resultCal.set(year, month, Month.of(month).getLastDay(DateUtil.isLeapYear(year))); + + return endOfDay(resultCal); } /** 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 09622ddd3..0b23ee484 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 @@ -16,7 +16,11 @@ import java.util.List; */ public class ChineseDate { - private static final Date baseDate = DateUtil.parseDate("1900-01-31"); +// private static final Date baseDate = DateUtil.parseDate("1900-01-31"); + /** + * 1900-01-31 + */ + private static final long baseDate = -2206425943000L; //农历年 private final int year; @@ -28,6 +32,12 @@ public class ChineseDate { private boolean leap; private final String[] chineseNumber = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"}; private final String[] chineseNumberName = {"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"}; + /** + *农历表示: + * 1. 表示当年有无闰年,有的话,为闰月的月份,没有的话,为0。 + * 2-4.为除了闰月外的正常月份是大月还是小月,1为30天,0为29天。 + * 5. 表示闰月是大月还是小月,仅当存在闰月的情况下有意义。 + */ private final long[] lunarInfo = new long[]{0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, @@ -66,33 +76,30 @@ public class ChineseDate { * @param date 日期 */ public ChineseDate(Date date) { - // -------------------- private -------------------- int yearCyl; int monCyl; int dayCyl; - int leapMonth; // 求出和1900年1月31日相差的天数 - int offset = (int) ((date.getTime() - baseDate.getTime()) / 86400000L); + int offset = (int) ((date.getTime() - baseDate) / DateUnit.DAY.getMillis()); monCyl = 14; // 用offset减去每农历年的天数 // 计算当天是农历第几天 // i最终结果是农历的年份 // offset是当年的第几天 int iYear; - int daysOfYear = 0; - for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) { + int daysOfYear; + for (iYear = 1900; iYear < 2050; iYear++) { daysOfYear = yearDays(iYear); + if (offset < daysOfYear) { + break; + } offset -= daysOfYear; monCyl += 12; } - if (offset < 0) { - offset += daysOfYear; - iYear--; - monCyl -= 12; - } + // 农历年份 year = iYear; - leapMonth = leapMonth(iYear); // 闰哪个月,1-12 + int leapMonth = leapMonth(iYear); // 闰哪个月,1-12 leap = false; // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 int iMonth, daysOfMonth = 0; @@ -270,7 +277,7 @@ public class ChineseDate { * @return 标准的日期格式 * @since 5.2.4 */ - public String toStringNormal(){ + public String toStringNormal() { return String.format("%04d-%02d-%02d", this.year, this.month, this.day); } @@ -314,8 +321,9 @@ public class ChineseDate { private int leapDays(int y) { if (leapMonth(y) != 0) { return (lunarInfo[y - 1900] & 0x10000) != 0 ? 30 : 29; - } else - return 0; + } + + return 0; } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/Month.java b/hutool-core/src/main/java/cn/hutool/core/date/Month.java index 3c35608d0..8eeda8c46 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/Month.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/Month.java @@ -5,7 +5,8 @@ import java.util.Calendar; /** * 月份枚举
* 与Calendar中的月份int值对应 - * + * + * @author Looly * @see Calendar#JANUARY * @see Calendar#FEBRUARY * @see Calendar#MARCH @@ -19,53 +20,106 @@ import java.util.Calendar; * @see Calendar#NOVEMBER * @see Calendar#DECEMBER * @see Calendar#UNDECIMBER - * - * @author Looly - * */ public enum Month { - - /** 一月 */ + /** + * 一月 + */ JANUARY(Calendar.JANUARY), - /** 二月 */ + /** + * 二月 + */ FEBRUARY(Calendar.FEBRUARY), - /** 三月 */ + /** + * 三月 + */ MARCH(Calendar.MARCH), - /** 四月 */ + /** + * 四月 + */ APRIL(Calendar.APRIL), - /** 五月 */ + /** + * 五月 + */ MAY(Calendar.MAY), - /** 六月 */ + /** + * 六月 + */ JUNE(Calendar.JUNE), - /** 七月 */ + /** + * 七月 + */ JULY(Calendar.JULY), - /** 八月 */ + /** + * 八月 + */ AUGUST(Calendar.AUGUST), - /** 九月 */ + /** + * 九月 + */ SEPTEMBER(Calendar.SEPTEMBER), - /** 十月 */ + /** + * 十月 + */ OCTOBER(Calendar.OCTOBER), - /** 十一月 */ + /** + * 十一月 + */ NOVEMBER(Calendar.NOVEMBER), - /** 十二月 */ + /** + * 十二月 + */ DECEMBER(Calendar.DECEMBER), - /** 十三月,仅用于农历 */ + /** + * 十三月,仅用于农历 + */ UNDECIMBER(Calendar.UNDECIMBER); // --------------------------------------------------------------- + private static final int[] DAYS_OF_MONTH = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1}; + + /** + * 对应值,见{@link Calendar} + */ private final int value; + /** + * 构造 + * + * @param value 对应值,见{@link Calendar} + */ Month(int value) { this.value = value; } + /** + * 获取{@link Calendar}中的对应值 + * + * @return {@link Calendar}中的对应值 + */ public int getValue() { return this.value; } + /** + * 获取此月份最后一天的值,不支持的月份(例如UNDECIMBER)返回-1 + * + * @param isLeapYear 是否闰年 + * @return 此月份最后一天的值 + */ + public int getLastDay(boolean isLeapYear) { + int lastDay = DAYS_OF_MONTH[value]; + if (isLeapYear && Calendar.FEBRUARY == value){ + lastDay += 1; + } + return lastDay; + } + /** * 将 {@link Calendar}月份相关值转换为Month枚举对象
- * + * + * @param calendarMonthIntValue Calendar中关于Month的int值 + * @return {@link Month} * @see Calendar#JANUARY * @see Calendar#FEBRUARY * @see Calendar#MARCH @@ -79,9 +133,6 @@ public enum Month { * @see Calendar#NOVEMBER * @see Calendar#DECEMBER * @see Calendar#UNDECIMBER - * - * @param calendarMonthIntValue Calendar中关于Month的int值 - * @return {@link Month} */ public static Month of(int calendarMonthIntValue) { switch (calendarMonthIntValue) { diff --git a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java index 90ca8bb4b..f78d2259a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java @@ -36,4 +36,13 @@ public class ChineseDateTest { ChineseDate date = new ChineseDate(DateUtil.parseDate("2020-03-1")); Assert.assertEquals("2020-02-08", date.toStringNormal()); } + + @Test + public void parseTest(){ + ChineseDate date = new ChineseDate(DateUtil.parseDate("1996-07-14")); + Assert.assertEquals("丙子鼠年 五月廿九", date.toString()); + + date = new ChineseDate(DateUtil.parseDate("1996-07-15")); + Assert.assertEquals("丙子鼠年 五月三十", date.toString()); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index a7f888c6c..b3d144159 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -73,7 +73,7 @@ public class DateUtilTest { @Test public void beginAndEndTest() { - String dateStr = "2017-03-01 22:33:23"; + String dateStr = "2017-03-01 00:33:23"; Date date = DateUtil.parse(dateStr); // 一天的开始 @@ -84,6 +84,12 @@ public class DateUtilTest { Assert.assertEquals("2017-03-01 23:59:59", endOfDay.toString()); } + @Test + public void endOfDayTest() { + final DateTime parse = DateUtil.parse("2020-05-31 00:00:00"); + Assert.assertEquals("2020-05-31 23:59:59", DateUtil.endOfDay(parse).toString()); + } + @Test public void truncateTest(){ String dateStr2 = "2020-02-29 12:59:34"; @@ -587,6 +593,14 @@ public class DateUtilTest { Assert.assertEquals("2019-12-31 23:59:59", endOfYear.toString()); } + @Test + public void endOfQuarterTest() { + Date date = DateUtil.endOfQuarter( + DateUtil.parse("2020-05-31 00:00:00")); + + Assert.assertEquals("2020-06-30 23:59:59", DateUtil.format(date,"yyyy-MM-dd HH:mm:ss")); + } + @Test public void endOfWeekTest() { // 周日 diff --git a/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java b/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java new file mode 100644 index 000000000..42e24117e --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java @@ -0,0 +1,40 @@ +package cn.hutool.core.date; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Calendar; + +public class MonthTest { + + @SuppressWarnings("ConstantConditions") + @Test + public void getLastDayTest(){ + int lastDay = Month.of(Calendar.JANUARY).getLastDay(false); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.FEBRUARY).getLastDay(false); + Assert.assertEquals(28, lastDay); + lastDay = Month.of(Calendar.FEBRUARY).getLastDay(true); + Assert.assertEquals(29, lastDay); + lastDay = Month.of(Calendar.MARCH).getLastDay(true); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.APRIL).getLastDay(true); + Assert.assertEquals(30, lastDay); + lastDay = Month.of(Calendar.MAY).getLastDay(true); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.JUNE).getLastDay(true); + Assert.assertEquals(30, lastDay); + lastDay = Month.of(Calendar.JULY).getLastDay(true); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.AUGUST).getLastDay(true); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.SEPTEMBER).getLastDay(true); + Assert.assertEquals(30, lastDay); + lastDay = Month.of(Calendar.OCTOBER).getLastDay(true); + Assert.assertEquals(31, lastDay); + lastDay = Month.of(Calendar.NOVEMBER).getLastDay(true); + Assert.assertEquals(30, lastDay); + lastDay = Month.of(Calendar.DECEMBER).getLastDay(true); + Assert.assertEquals(31, lastDay); + } +}