diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b067a1d2..b2f02a86e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,14 @@ ------------------------------------------------------------------------------------------------------------- -## 5.3.10 (2020-07-17) +## 5.3.10 (2020-07-22) ### 新特性 * 【db 】 增加DbUtil.setReturnGeneratedKeyGlobal(issue#I1NM0K@Gitee) * 【core 】 增加DataSize和DataSizeUtil(issue#967@Github) * 【core 】 ImgUtil增加异常,避免空指针(issue#I1NKXG@Gitee) * 【core 】 增加CRC16算法若干(pr#963@Github) +* 【core 】 LocalDateTimeUtil增加format等方法(pr#140@Gitee) ### Bug修复 * 【core 】 修复ZipUtil中finish位于循环内的问题(issue#961@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index c1575382a..91cdae363 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -14,18 +14,13 @@ import cn.hutool.core.util.StrUtil; import java.text.DateFormat; import java.text.SimpleDateFormat; + import java.time.Instant; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; import java.time.Year; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAccessor; + import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -498,11 +493,7 @@ public class DateUtil extends CalendarUtil { * @return 格式化后的字符串 */ public static String format(LocalDateTime localDateTime, String format) { - if (null == localDateTime || StrUtil.isBlank(format)) { - return null; - } - DateTimeFormatter df = DateTimeFormatter.ofPattern(format); - return localDateTime.format(df); + return LocalDateTimeUtil.format(localDateTime, format); } /** @@ -670,14 +661,7 @@ public class DateUtil extends CalendarUtil { * @return LocalDateTime对象 */ public static LocalDateTime parseLocalDateTime(CharSequence dateStr, String format) { - dateStr = normalize(dateStr); - DateTimeFormatter df = DateTimeFormatter.ofPattern(format); - try { - return LocalDateTime.parse(dateStr, df); - } catch (DateTimeParseException e) { - // 在给定日期字符串没有时间部分时,LocalDateTime会报错,此时使用LocalDate中转转换 - return LocalDate.parse(dateStr, df).atStartOfDay(); - } + return LocalDateTimeUtil.parse(dateStr, format); } /** @@ -835,7 +819,7 @@ public class DateUtil extends CalendarUtil { } else if (length == DatePattern.UTC_MS_WITH_ZONE_OFFSET_PATTERN.length() + 2 || length == DatePattern.UTC_MS_WITH_ZONE_OFFSET_PATTERN.length() + 3) { // 格式类似:2018-09-13T05:34:31.999+0800 或 2018-09-13T05:34:31.999+08:00 return parse(utcString, DatePattern.UTC_MS_WITH_ZONE_OFFSET_FORMAT); - } else if(length == DatePattern.UTC_SIMPLE_PATTERN.length()-2){ + } else if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 2) { // 格式类似:2018-09-13T05:34:31 return parse(utcString, DatePattern.UTC_SIMPLE_FORMAT); } @@ -937,7 +921,7 @@ public class DateUtil extends CalendarUtil { // yyyy-MM-dd HH:mm return parse(dateStr, DatePattern.NORM_DATETIME_MINUTE_FORMAT); case 2: - if(StrUtil.contains(dateStr, CharUtil.DOT)){ + if (StrUtil.contains(dateStr, CharUtil.DOT)) { // yyyy-MM-dd HH:mm:ss.SSS return parse(dateStr, DatePattern.NORM_DATETIME_MS_FORMAT); } @@ -1838,32 +1822,7 @@ public class DateUtil extends CalendarUtil { * @since 5.0.2 */ public static Instant toInstant(TemporalAccessor temporalAccessor) { - if (null == temporalAccessor) { - return null; - } - - Instant result; - if (temporalAccessor instanceof Instant) { - result = (Instant) temporalAccessor; - } else if (temporalAccessor instanceof LocalDateTime) { - result = ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault()).toInstant(); - } else if (temporalAccessor instanceof ZonedDateTime) { - result = ((ZonedDateTime) temporalAccessor).toInstant(); - } else if (temporalAccessor instanceof OffsetDateTime) { - result = ((OffsetDateTime) temporalAccessor).toInstant(); - } else if (temporalAccessor instanceof LocalDate) { - result = ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault()).toInstant(); - } else if (temporalAccessor instanceof LocalTime) { - // 指定本地时间转换 为Instant,取当天日期 - result = ((LocalTime) temporalAccessor).atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant(); - } else if (temporalAccessor instanceof OffsetTime) { - // 指定本地时间转换 为Instant,取当天日期 - result = ((OffsetTime) temporalAccessor).atDate(LocalDate.now()).toInstant(); - } else { - result = Instant.from(temporalAccessor); - } - - return result; + return TemporalAccessorUtil.toInstant(temporalAccessor); } /** @@ -1871,8 +1830,8 @@ public class DateUtil extends CalendarUtil { * * @param instant {@link Instant} * @return {@link LocalDateTime} - * @since 5.0.5 * @see LocalDateTimeUtil#of(Instant) + * @since 5.0.5 */ public static LocalDateTime toLocalDateTime(Instant instant) { return LocalDateTimeUtil.of(instant); @@ -1883,8 +1842,8 @@ public class DateUtil extends CalendarUtil { * * @param date {@link Date} * @return {@link LocalDateTime} - * @since 5.0.5 * @see LocalDateTimeUtil#of(Date) + * @since 5.0.5 */ public static LocalDateTime toLocalDateTime(Date date) { return LocalDateTimeUtil.of(date); diff --git a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java index f452fb9e7..3562e85ff 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java @@ -158,7 +158,7 @@ public class LocalDateTimeUtil { } /** - * {@link Date}转{@link LocalDateTime},使用默认时区 + * {@link TemporalAccessor}转{@link LocalDateTime},使用默认时区 * * @param temporalAccessor {@link TemporalAccessor} * @return {@link LocalDateTime} @@ -183,6 +183,29 @@ public class LocalDateTimeUtil { ); } + /** + * {@link TemporalAccessor}转{@link LocalDate},使用默认时区 + * + * @param temporalAccessor {@link TemporalAccessor} + * @return {@link LocalDate} + * @since 5.3.10 + */ + public static LocalDate ofDate(TemporalAccessor temporalAccessor) { + if (null == temporalAccessor) { + return null; + } + + if(temporalAccessor instanceof LocalDateTime){ + return ((LocalDateTime)temporalAccessor).toLocalDate(); + } + + return LocalDate.of( + TemporalAccessorUtil.get(temporalAccessor, ChronoField.YEAR), + TemporalAccessorUtil.get(temporalAccessor, ChronoField.MONTH_OF_YEAR), + TemporalAccessorUtil.get(temporalAccessor, ChronoField.DAY_OF_MONTH) + ); + } + /** * 解析日期时间字符串为{@link LocalDateTime},仅支持yyyy-MM-dd'T'HH:mm:ss格式,例如:2007-12-03T10:15:30 * @@ -225,6 +248,50 @@ public class LocalDateTimeUtil { return parse(text, DateTimeFormatter.ofPattern(format)); } + /** + * 解析日期时间字符串为{@link LocalDate},仅支持yyyy-MM-dd'T'HH:mm:ss格式,例如:2007-12-03T10:15:30 + * + * @param text 日期时间字符串 + * @return {@link LocalDate} + * @since 5.3.10 + */ + public static LocalDate parseDate(CharSequence text) { + return parseDate(text, (DateTimeFormatter)null); + } + + /** + * 解析日期时间字符串为{@link LocalDate},格式支持日期 + * + * @param text 日期时间字符串 + * @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter} + * @return {@link LocalDate} + * @since 5.3.10 + */ + public static LocalDate parseDate(CharSequence text, DateTimeFormatter formatter) { + if (null == text) { + return null; + } + if (null == formatter) { + return LocalDate.parse(text); + } + + return ofDate(formatter.parse(text)); + } + + /** + * 解析日期字符串为{@link LocalDate} + * + * @param text 日期字符串 + * @param format 日期格式,类似于yyyy-MM-dd + * @return {@link LocalDateTime} + */ + public static LocalDate parseDate(CharSequence text, String format) { + if (null == text) { + return null; + } + return parseDate(text, DateTimeFormatter.ofPattern(format)); + } + /** * 格式化日期时间为指定格式 * @@ -233,10 +300,7 @@ public class LocalDateTimeUtil { * @return 格式化后的字符串 */ public static String format(LocalDateTime time, DateTimeFormatter formatter) { - if (null == time) { - return null; - } - return time.format(formatter); + return TemporalAccessorUtil.format(time, formatter); } /** @@ -253,6 +317,33 @@ public class LocalDateTimeUtil { return format(time, DateTimeFormatter.ofPattern(format)); } + /** + * 格式化日期时间为指定格式 + * + * @param date {@link LocalDate} + * @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter} + * @return 格式化后的字符串 + * @since 5.3.10 + */ + public static String format(LocalDate date, DateTimeFormatter formatter) { + return TemporalAccessorUtil.format(date, formatter); + } + + /** + * 格式化日期时间为指定格式 + * + * @param date {@link LocalDate} + * @param format 日期格式,类似于yyyy-MM-dd + * @return 格式化后的字符串 + * @since 5.3.10 + */ + public static String format(LocalDate date, String format) { + if (null == date) { + return null; + } + return format(date, DateTimeFormatter.ofPattern(format)); + } + /** * 日期偏移,根据field不同加不同值(偏移会修改传入的对象) * diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java index 8dc0a0d73..8df054c6d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java @@ -1,5 +1,16 @@ package cn.hutool.core.date; +import cn.hutool.core.util.StrUtil; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; @@ -25,4 +36,79 @@ public class TemporalAccessorUtil { return (int)field.range().getMinimum(); } + + /** + * 格式化日期时间为指定格式 + * + * @param time {@link TemporalAccessor} + * @param formatter 日期格式化器,预定义的格式见:{@link DateTimeFormatter} + * @return 格式化后的字符串 + * @since 5.3.10 + */ + public static String format(TemporalAccessor time, DateTimeFormatter formatter) { + if (null == time) { + return null; + } + + if(null == formatter){ + formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + } + + return formatter.format(time); + } + + /** + * 格式化日期时间为指定格式 + * + * @param time {@link TemporalAccessor} + * @param format 日期格式 + * @return 格式化后的字符串 + * @since 5.3.10 + */ + public static String format(TemporalAccessor time, String format) { + if (null == time) { + return null; + } + + final DateTimeFormatter formatter = StrUtil.isBlank(format) + ? null : DateTimeFormatter.ofPattern(format); + + return format(time, formatter); + } + + /** + * {@link TemporalAccessor}转换为 {@link Instant}对象 + * + * @param temporalAccessor Date对象 + * @return {@link Instant}对象 + * @since 5.3.10 + */ + public static Instant toInstant(TemporalAccessor temporalAccessor) { + if (null == temporalAccessor) { + return null; + } + + Instant result; + if (temporalAccessor instanceof Instant) { + result = (Instant) temporalAccessor; + } else if (temporalAccessor instanceof LocalDateTime) { + result = ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault()).toInstant(); + } else if (temporalAccessor instanceof ZonedDateTime) { + result = ((ZonedDateTime) temporalAccessor).toInstant(); + } else if (temporalAccessor instanceof OffsetDateTime) { + result = ((OffsetDateTime) temporalAccessor).toInstant(); + } else if (temporalAccessor instanceof LocalDate) { + result = ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault()).toInstant(); + } else if (temporalAccessor instanceof LocalTime) { + // 指定本地时间转换 为Instant,取当天日期 + result = ((LocalTime) temporalAccessor).atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant(); + } else if (temporalAccessor instanceof OffsetTime) { + // 指定本地时间转换 为Instant,取当天日期 + result = ((OffsetTime) temporalAccessor).atDate(LocalDate.now()).toInstant(); + } else { + result = Instant.from(temporalAccessor); + } + + return result; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/CRC16.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/CRC16.java index 72084346b..ebccedb2f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/CRC16.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/CRC16.java @@ -3,13 +3,15 @@ package cn.hutool.core.io.checksum; import cn.hutool.core.io.checksum.crc16.CRC16Checksum; import cn.hutool.core.io.checksum.crc16.CRC16IBM; +import java.util.zip.Checksum; + /** * CRC16 循环冗余校验码(Cyclic Redundancy Check)实现,默认IBM算法 * * @author looly * @since 4.4.1 */ -public class CRC16 extends CRC16Checksum { +public class CRC16 implements Checksum { private static final long serialVersionUID = 1L; private final CRC16Checksum crc16; 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 b3d144159..45bdf51f6 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 @@ -751,7 +751,7 @@ public class DateUtilTest { String strDate1 = DateUtil.formatLocalDateTime(ldt); Assert.assertEquals(strDate, strDate1); - String strDate2 = "2019年12月01日 17:02:30.111"; + String strDate2 = "2019-12-01 17:02:30.111"; ldt = DateUtil.parseLocalDateTime(strDate2, DatePattern.NORM_DATETIME_MS_PATTERN); strDate1 = DateUtil.format(ldt, DatePattern.NORM_DATETIME_PATTERN); Assert.assertEquals(strDate, strDate1); diff --git a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java index 24d8ada86..32ddd03b9 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java @@ -4,6 +4,7 @@ import org.junit.Assert; import org.junit.Test; import java.time.Duration; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; @@ -58,6 +59,15 @@ public class LocalDateTimeUtilTest { Assert.assertEquals("2020-01-23T12:23:56", localDateTime.toString()); } + @Test + public void parseDateTest() { + LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23"); + Assert.assertEquals("2020-01-23", localDate.toString()); + + localDate = LocalDateTimeUtil.parseDate("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME); + Assert.assertEquals("2020-01-23", localDate.toString()); + } + @Test public void formatTest() { final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); @@ -68,6 +78,13 @@ public class LocalDateTimeUtilTest { Assert.assertEquals("2020-01-23", format); } + @Test + public void formatLocalDateTest() { + final LocalDate localDateTime = LocalDate.parse("2020-01-23"); + String format = LocalDateTimeUtil.format(localDateTime, DatePattern.NORM_DATE_PATTERN); + Assert.assertEquals("2020-01-23", format); + } + @Test public void offset() { final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56"); diff --git a/hutool-core/src/test/java/cn/hutool/core/io/checksum/CrcTest.java b/hutool-core/src/test/java/cn/hutool/core/io/checksum/CrcTest.java index dbffdcc03..7c5b1cd27 100644 --- a/hutool-core/src/test/java/cn/hutool/core/io/checksum/CrcTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/io/checksum/CrcTest.java @@ -1,10 +1,9 @@ package cn.hutool.core.io.checksum; +import cn.hutool.core.util.HexUtil; import org.junit.Assert; import org.junit.Test; -import cn.hutool.core.util.HexUtil; - /** * CRC校验单元测试 *