Browse Source

date parse support like 2020-1-1

Looly 5 years ago
parent
commit
06fa24edb0

+ 1 - 0
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)

+ 46 - 34
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个数字,包括:
+	 * <pre>
+	 *     yyyy-MM-dd HH:mm:ss
+	 *     yyyy-MM-dd HH:mm
+	 *     yyyy-MM-dd
+	 * </pre>
+	 * @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"));
 }

+ 19 - 0
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);
 	}

+ 17 - 0
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());
+	}
 }