diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c56ae8dd..60ced74bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ * 【core 】 isMactchRegex失效标记,增加isMatchRegex(issue#I1IPJG@Gitee) * 【core 】 优化Validator.isChinese * 【core 】 ArrayUtil.addAll增加原始类型支持(issue#898@Github) +* 【core 】 DateUtil.parse支持2020-1-1这类日期解析(issue#I1HGWW@Github) ### Bug修复 * 【core 】 修复SimpleCache死锁问题(issue#I1HOKB@Gitee) 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 46e78f846..8a82b9eb4 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 @@ -1,9 +1,10 @@ package cn.hutool.core.date; +import cn.hutool.core.date.format.FastDateFormat; + import java.util.Locale; import java.util.TimeZone; - -import cn.hutool.core.date.format.FastDateFormat; +import java.util.regex.Pattern; /** * 日期格式化类,提供常用的日期格式化对象 @@ -13,86 +14,97 @@ import cn.hutool.core.date.format.FastDateFormat; */ public class DatePattern { + /** + * 标准日期时间正则,每个字段支持单个数字或2个数字,包括: + *
+	 *     yyyy-MM-dd HH:mm:ss
+	 *     yyyy-MM-dd HH:mm
+	 *     yyyy-MM-dd
+	 * 
+ * @since 5.3.6 + */ + public static final Pattern REGEX_NORM = Pattern.compile("\\d{4}-\\d{1,2}-\\d{1,2}( \\d{1,2}:\\d{1,2}(:\\d{1,2})?)?"); + //-------------------------------------------------------------------------------------------------------------------------------- Normal /** 标准日期格式:yyyy-MM-dd */ - public final static String NORM_DATE_PATTERN = "yyyy-MM-dd"; + public static final String NORM_DATE_PATTERN = "yyyy-MM-dd"; /** 标准日期格式 {@link FastDateFormat}:yyyy-MM-dd */ - public final static FastDateFormat NORM_DATE_FORMAT = FastDateFormat.getInstance(NORM_DATE_PATTERN); + public static final FastDateFormat NORM_DATE_FORMAT = FastDateFormat.getInstance(NORM_DATE_PATTERN); /** 标准时间格式:HH:mm:ss */ - public final static String NORM_TIME_PATTERN = "HH:mm:ss"; + public static final String NORM_TIME_PATTERN = "HH:mm:ss"; /** 标准时间格式 {@link FastDateFormat}:HH:mm:ss */ - public final static FastDateFormat NORM_TIME_FORMAT = FastDateFormat.getInstance(NORM_TIME_PATTERN); + public static final FastDateFormat NORM_TIME_FORMAT = FastDateFormat.getInstance(NORM_TIME_PATTERN); /** 标准日期时间格式,精确到分:yyyy-MM-dd HH:mm */ - public final static String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm"; + public static final String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm"; /** 标准日期时间格式,精确到分 {@link FastDateFormat}:yyyy-MM-dd HH:mm */ - public final static FastDateFormat NORM_DATETIME_MINUTE_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MINUTE_PATTERN); + public static final FastDateFormat NORM_DATETIME_MINUTE_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MINUTE_PATTERN); /** 标准日期时间格式,精确到秒:yyyy-MM-dd HH:mm:ss */ - public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; /** 标准日期时间格式,精确到秒 {@link FastDateFormat}:yyyy-MM-dd HH:mm:ss */ - public final static FastDateFormat NORM_DATETIME_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_PATTERN); + public static final FastDateFormat NORM_DATETIME_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_PATTERN); /** 标准日期时间格式,精确到毫秒:yyyy-MM-dd HH:mm:ss.SSS */ - public final static String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; + public static final String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; /** 标准日期时间格式,精确到毫秒 {@link FastDateFormat}:yyyy-MM-dd HH:mm:ss.SSS */ - public final static FastDateFormat NORM_DATETIME_MS_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MS_PATTERN); + public static final FastDateFormat NORM_DATETIME_MS_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MS_PATTERN); /** 标准日期格式:yyyy年MM月dd日 */ - public final static String CHINESE_DATE_PATTERN = "yyyy年MM月dd日"; + public static final String CHINESE_DATE_PATTERN = "yyyy年MM月dd日"; /** 标准日期格式 {@link FastDateFormat}:yyyy年MM月dd日 */ - public final static FastDateFormat CHINESE_DATE_FORMAT = FastDateFormat.getInstance(CHINESE_DATE_PATTERN); + public static final FastDateFormat CHINESE_DATE_FORMAT = FastDateFormat.getInstance(CHINESE_DATE_PATTERN); //-------------------------------------------------------------------------------------------------------------------------------- Pure /** 标准日期格式:yyyyMMdd */ - public final static String PURE_DATE_PATTERN = "yyyyMMdd"; + public static final String PURE_DATE_PATTERN = "yyyyMMdd"; /** 标准日期格式 {@link FastDateFormat}:yyyyMMdd */ - public final static FastDateFormat PURE_DATE_FORMAT = FastDateFormat.getInstance(PURE_DATE_PATTERN); + public static final FastDateFormat PURE_DATE_FORMAT = FastDateFormat.getInstance(PURE_DATE_PATTERN); /** 标准日期格式:HHmmss */ - public final static String PURE_TIME_PATTERN = "HHmmss"; + public static final String PURE_TIME_PATTERN = "HHmmss"; /** 标准日期格式 {@link FastDateFormat}:HHmmss */ - public final static FastDateFormat PURE_TIME_FORMAT = FastDateFormat.getInstance(PURE_TIME_PATTERN); + public static final FastDateFormat PURE_TIME_FORMAT = FastDateFormat.getInstance(PURE_TIME_PATTERN); /** 标准日期格式:yyyyMMddHHmmss */ - public final static String PURE_DATETIME_PATTERN = "yyyyMMddHHmmss"; + public static final String PURE_DATETIME_PATTERN = "yyyyMMddHHmmss"; /** 标准日期格式 {@link FastDateFormat}:yyyyMMddHHmmss */ - public final static FastDateFormat PURE_DATETIME_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_PATTERN); + public static final FastDateFormat PURE_DATETIME_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_PATTERN); /** 标准日期格式:yyyyMMddHHmmssSSS */ - public final static String PURE_DATETIME_MS_PATTERN = "yyyyMMddHHmmssSSS"; + public static final String PURE_DATETIME_MS_PATTERN = "yyyyMMddHHmmssSSS"; /** 标准日期格式 {@link FastDateFormat}:yyyyMMddHHmmssSSS */ - public final static FastDateFormat PURE_DATETIME_MS_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_MS_PATTERN); + public static final FastDateFormat PURE_DATETIME_MS_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_MS_PATTERN); //-------------------------------------------------------------------------------------------------------------------------------- Others /** HTTP头中日期时间格式:EEE, dd MMM yyyy HH:mm:ss z */ - public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; + public static final String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; /** HTTP头中日期时间格式 {@link FastDateFormat}:EEE, dd MMM yyyy HH:mm:ss z */ - public final static FastDateFormat HTTP_DATETIME_FORMAT = FastDateFormat.getInstance(HTTP_DATETIME_PATTERN, TimeZone.getTimeZone("GMT"), Locale.US); + public static final FastDateFormat HTTP_DATETIME_FORMAT = FastDateFormat.getInstance(HTTP_DATETIME_PATTERN, TimeZone.getTimeZone("GMT"), Locale.US); /** JDK中日期时间格式:EEE MMM dd HH:mm:ss zzz yyyy */ - public final static String JDK_DATETIME_PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy"; + public static final String JDK_DATETIME_PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy"; /** JDK中日期时间格式 {@link FastDateFormat}:EEE MMM dd HH:mm:ss zzz yyyy */ - public final static FastDateFormat JDK_DATETIME_FORMAT = FastDateFormat.getInstance(JDK_DATETIME_PATTERN, Locale.US); + public static final FastDateFormat JDK_DATETIME_FORMAT = FastDateFormat.getInstance(JDK_DATETIME_PATTERN, Locale.US); /** UTC时间:yyyy-MM-dd'T'HH:mm:ss'Z' */ - public final static String UTC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + public static final String UTC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; /** UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss'Z' */ - public final static FastDateFormat UTC_FORMAT = FastDateFormat.getInstance(UTC_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat UTC_FORMAT = FastDateFormat.getInstance(UTC_PATTERN, TimeZone.getTimeZone("UTC")); /** UTC时间:yyyy-MM-dd'T'HH:mm:ssZ */ - public final static String UTC_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ"; + public static final String UTC_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ"; /** UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssZ */ - public final static FastDateFormat UTC_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + 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:ss.SSS'Z' */ - public final static String UTC_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + public static final String UTC_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; /** UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' */ - public final static FastDateFormat UTC_MS_FORMAT = FastDateFormat.getInstance(UTC_MS_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat UTC_MS_FORMAT = FastDateFormat.getInstance(UTC_MS_PATTERN, TimeZone.getTimeZone("UTC")); /** UTC时间:yyyy-MM-dd'T'HH:mm:ssZ */ - public final static String UTC_MS_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + public static final String UTC_MS_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; /** UTC时间{@link FastDateFormat}:yyyy-MM-dd'T'HH:mm:ssZ */ - public final static FastDateFormat UTC_MS_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); + public static final FastDateFormat UTC_MS_WITH_ZONE_OFFSET_FORMAT = FastDateFormat.getInstance(UTC_MS_WITH_ZONE_OFFSET_PATTERN, TimeZone.getTimeZone("UTC")); } 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 4d9e3dc5e..34bff8283 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 @@ -8,6 +8,7 @@ import cn.hutool.core.date.format.DatePrinter; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.PatternPool; +import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; @@ -918,9 +919,27 @@ public class DateUtil extends CalendarUtil { // yyyy-MM-dd HH:mm return parse(normalize(dateStr), DatePattern.NORM_DATETIME_MINUTE_FORMAT); } else if (length >= DatePattern.NORM_DATETIME_MS_PATTERN.length() - 2) { + //yyyy-MM-dd HH:mm:ss.SSS return parse(normalize(dateStr), DatePattern.NORM_DATETIME_MS_FORMAT); } + //含有单个位数数字的日期时间格式 + dateStr = normalize(dateStr); + if (ReUtil.isMatch(DatePattern.REGEX_NORM, dateStr)) { + final int colonCount = StrUtil.count(dateStr, CharUtil.COLON); + switch (colonCount) { + case 0: + // yyyy-MM-dd + return parseDate(dateStr); + case 1: + // yyyy-MM-dd HH:mm + return parse(normalize(dateStr), DatePattern.NORM_DATETIME_MINUTE_FORMAT); + case 2: + // yyyy-MM-dd HH:mm:ss + return parseDateTime(dateStr); + } + } + // 没有更多匹配的时间格式 throw new DateException("No format fit for date String [{}] !", dateStr); } 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 e643afd0d..42e95c441 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 @@ -761,4 +761,21 @@ public class DateUtilTest { int lengthOfYear = DateUtil.lengthOfYear(2020); Assert.assertEquals(366, lengthOfYear); } + + @SuppressWarnings("ConstantConditions") + @Test + public void parseSingleNumberTest(){ + DateTime dateTime = DateUtil.parse("2020-5-08"); + Assert.assertEquals("2020-05-08 00:00:00", dateTime.toString()); + dateTime = DateUtil.parse("2020-5-8"); + Assert.assertEquals("2020-05-08 00:00:00", dateTime.toString()); + dateTime = DateUtil.parse("2020-05-8"); + Assert.assertEquals("2020-05-08 00:00:00", dateTime.toString()); + + //datetime + dateTime = DateUtil.parse("2020-5-8 3:12:3"); + Assert.assertEquals("2020-05-08 03:12:03", dateTime.toString()); + dateTime = DateUtil.parse("2020-5-8 3:2:3"); + Assert.assertEquals("2020-05-08 03:02:03", dateTime.toString()); + } }