From 5753444de24710b8d384f56ebce40f773800690d Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 9 Feb 2023 20:59:26 +0800 Subject: [PATCH] fix code --- .../date/format/parser/UTCDateParser.java | 26 +++++++++++++++++++ .../cn/hutool/core/date/DateUtilTest.java | 21 +++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java index 76edffa21..a60cb6a0c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java @@ -25,6 +25,9 @@ import cn.hutool.core.util.CharUtil; public class UTCDateParser extends DefaultDateBasic implements DateParser { private static final long serialVersionUID = 1L; + /** + * 单例对象 + */ public static UTCDateParser INSTANCE = new UTCDateParser(); @Override @@ -57,6 +60,7 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { if (StrUtil.contains(source, CharUtil.DOT)) { // 带毫秒,格式类似:2018-09-13T05:34:31.999+08:00 + source = normalizeMillSeconds(source, ".", "+"); return new DateTime(source, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT); } else { // 格式类似:2018-09-13T05:34:31+08:00 @@ -73,6 +77,7 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { if (StrUtil.contains(source, CharUtil.DOT)) { // 带毫秒,格式类似:2018-09-13T05:34:31.999-08:00 + source = normalizeMillSeconds(source, ".", "-"); return new DateTime(source, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT); } else { // 格式类似:2018-09-13T05:34:31-08:00 @@ -87,10 +92,31 @@ public class UTCDateParser extends DefaultDateBasic implements DateParser { return new DateTime(source + ":00", DatePattern.UTC_SIMPLE_FORMAT); } else if (StrUtil.contains(source, CharUtil.DOT)) { // 可能为: 2021-03-17T06:31:33.99 + source = normalizeMillSeconds(source, ".", null); return new DateTime(source, DatePattern.UTC_SIMPLE_MS_FORMAT); } } // 没有更多匹配的时间格式 throw new DateException("No UTC format fit for date String [{}] !", source); } + + /** + * 如果日期中的毫秒部分超出3位,会导致秒数增加,因此只保留前三位
+ * issue#2887 + * + * @param dateStr 日期字符串 + * @param before 毫秒部分的前一个字符 + * @param after 毫秒部分的后一个字符 + * @return 规范之后的毫秒部分 + */ + private static String normalizeMillSeconds(final String dateStr, final CharSequence before, final CharSequence after) { + if (StrUtil.isBlank(after)) { + final String millOrNaco = StrUtil.subPre(StrUtil.subAfter(dateStr, before, true), 3); + return StrUtil.subBefore(dateStr, before, true) + before + millOrNaco; + } + final String millOrNaco = StrUtil.subPre(StrUtil.subBetween(dateStr, before, after), 3); + return StrUtil.subBefore(dateStr, before, true) + + before + + millOrNaco + after + StrUtil.subAfter(dateStr, after, true); + } } 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 f40dfd505..eb874c6c3 100755 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1079,4 +1079,25 @@ public class DateUtilTest { Assert.assertEquals(dayOfMonth, Objects.requireNonNull(dateTime).dayOfMonth()); Assert.assertTrue("not is last day of this month !!",DateUtil.isLastDayOfMonth(dateTime)); } + + /** + * issue#2887 由于UTC时间的毫秒部分超出3位导致的秒数增加的问题 + */ + @Test + public void parseUTCTest4() { + final String dateStr = "2023-02-07T00:02:16.12345+08:00"; + final DateTime dateTime = DateUtil.parse(dateStr); + Assert.assertNotNull(dateTime); + Assert.assertEquals("2023-02-07 00:02:16", dateTime.toString()); + + final String dateStr2 = "2023-02-07T00:02:16.12345-08:00"; + final DateTime dateTime2 = DateUtil.parse(dateStr2); + Assert.assertNotNull(dateTime2); + Assert.assertEquals("2023-02-07 00:02:16", dateTime2.toString()); + + final String dateStr3 = "2021-03-17T06:31:33.9999"; + final DateTime dateTime3 = DateUtil.parse(dateStr3); + Assert.assertNotNull(dateTime3); + Assert.assertEquals("2021-03-17 06:31:33", dateTime3.toString()); + } }