From 72af4101bc203c07daae0da04c8f62207baabff1 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 2 Aug 2021 13:41:54 +0800 Subject: [PATCH] enhance parseUTC --- CHANGELOG.md | 1 + .../java/cn/hutool/core/date/DatePattern.java | 18 +++++++++++ .../java/cn/hutool/core/date/DateUtil.java | 30 ++++++++++++++----- .../cn/hutool/core/date/DateUtilTest.java | 22 +++++++++++++- .../core/date/LocalDateTimeUtilTest.java | 8 ++++- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec05bcc48..0f859e2cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * 【core 】 增加JNDIUtil(issue#1727@Github) * 【core 】 SpringUtil增加unregisterBean方法(pr#388@Gitee) * 【core 】 优化TextSimilarity公共子串算法(issue#I42A6V@Gitee) +* 【core 】 优化DateUtil.parse对UTC附带时区字符串解析(issue#I437AP@Gitee) ### 🐞Bug修复 * 【jwt 】 修复JWTUtil中几个方法非static的问题(issue#1735@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java b/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java index 8feeac0ce..4107fb2a8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DatePattern.java @@ -267,6 +267,15 @@ public class DatePattern { */ public static final FastDateFormat UTC_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + /** + * UTC时间:yyyy-MM-dd'T'HH:mm:ssXXX + */ + public static final String UTC_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssXXX"; + /** + * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssXXX + */ + public static final FastDateFormat UTC_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_WITH_XXX_OFFSET_PATTERN); + /** * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' */ @@ -285,6 +294,15 @@ public class DatePattern { */ public static final FastDateFormat UTC_MS_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + /** + * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSSXXX + */ + public static final String UTC_MS_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; + /** + * UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSSXXX + */ + public static final FastDateFormat UTC_MS_WITH_XXX_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_XXX_OFFSET_PATTERN); + /** * 创建并为 {@link DateTimeFormatter} 赋予默认时区和位置信息,默认值为系统默认值。 * 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 7cbe2f836..865c27c6b 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 @@ -809,6 +809,8 @@ public class DateUtil extends CalendarUtil { *
  • yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
  • *
  • yyyy-MM-dd'T'HH:mm:ssZ
  • *
  • yyyy-MM-dd'T'HH:mm:ss.SSSZ
  • + *
  • yyyy-MM-dd'T'HH:mm:ss+0800
  • + *
  • yyyy-MM-dd'T'HH:mm:ss+08:00
  • * * * @param utcString UTC时间 @@ -832,14 +834,28 @@ public class DateUtil extends CalendarUtil { if (length <= patternLength - 4 && length >= patternLength - 6) { return parse(utcString, DatePattern.UTC_MS_FORMAT); } + } else if(StrUtil.contains(utcString, '+')){ + // 去除类似2019-06-01T19:45:43 +08:00加号前的空格 + utcString = utcString.replace(" +", "+"); + final String zoneOffset = StrUtil.subAfter(utcString, '+', true); + if(StrUtil.isBlank(zoneOffset)){ + throw new DateException("Invalid format: [{}]", utcString); + } + if(false == StrUtil.contains(zoneOffset, ':')){ + // +0800转换为+08:00 + final String pre = StrUtil.subBefore(utcString, '+', true); + utcString = pre + "+" + zoneOffset.substring(0, 2) + ":" + "00"; + } + + if(StrUtil.contains(utcString, CharUtil.DOT)) { + // 带毫秒,格式类似:2018-09-13T05:34:31.999+08:00 + return parse(utcString, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT); + } else { + // 格式类似:2018-09-13T05:34:31+08:00 + return parse(utcString, DatePattern.UTC_WITH_XXX_OFFSET_FORMAT); + } } else { - if (length == DatePattern.UTC_WITH_ZONE_OFFSET_PATTERN.length() + 2 || length == DatePattern.UTC_WITH_ZONE_OFFSET_PATTERN.length() + 3) { - // 格式类似:2018-09-13T05:34:31+0800 或 2018-09-13T05:34:31+08:00 - return parse(utcString, DatePattern.UTC_WITH_ZONE_OFFSET_FORMAT); - } 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) { + if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 2) { // 格式类似:2018-09-13T05:34:31 return parse(utcString, DatePattern.UTC_SIMPLE_FORMAT); } else if (StrUtil.contains(utcString, CharUtil.DOT)) { 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 39d95cf71..79e9d638d 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 @@ -438,7 +438,13 @@ public class DateUtilTest { @Test public void parseTest7() { String str = "2019-06-01T19:45:43.000 +0800"; - DateTime dateTime = DateUtil.parse(str, "yyyy-MM-dd'T'HH:mm:ss.SSS Z"); + DateTime dateTime = DateUtil.parse(str); + assert dateTime != null; + Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString()); + + str = "2019-06-01T19:45:43 +08:00"; + dateTime = DateUtil.parse(str); + assert dateTime != null; Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString()); } @@ -450,6 +456,20 @@ public class DateUtilTest { Assert.assertEquals("2020-06-28 02:14:13", dateTime.toString()); } + @Test + public void parseUTCOffsetTest() { + // issue#I437AP@Gitee + String str = "2019-06-01T19:45:43+08:00"; + DateTime dateTime = DateUtil.parse(str); + assert dateTime != null; + Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString()); + + str = "2019-06-01T19:45:43 +08:00"; + dateTime = DateUtil.parse(str); + assert dateTime != null; + Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString()); + } + @Test public void parseAndOffsetTest() { // 检查UTC时间偏移是否准确 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 aa22faf78..0d3fa84a6 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 @@ -29,6 +29,12 @@ public class LocalDateTimeUtilTest { Assert.assertEquals(dateStr, of.toString()); } + @Test + public void parseOffsetTest() { + final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2021-07-30T16:27:27+08:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME); + Assert.assertEquals("2021-07-30T16:27:27", localDateTime.toString()); + } + @Test public void parseTest() { final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME); @@ -137,4 +143,4 @@ public class LocalDateTimeUtilTest { final LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(localDateTime); Assert.assertEquals("2020-01-23T23:59:59.999999999", endOfDay.toString()); } -} \ No newline at end of file +}