diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
index 105be0cd9..107034c51 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
@@ -2,9 +2,10 @@ package cn.hutool.core.date;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.convert.NumberChineseFormatter;
-import cn.hutool.core.date.format.DateParser;
-import cn.hutool.core.date.format.FastDateParser;
+import cn.hutool.core.date.format.parser.DateParser;
+import cn.hutool.core.date.format.parser.FastDateParser;
import cn.hutool.core.date.format.GlobalCustomFormat;
+import cn.hutool.core.date.format.parser.PositionDateParser;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.text.StrUtil;
@@ -758,7 +759,7 @@ public class CalendarUtil {
* @return 解析后的 {@link Calendar},解析失败返回{@code null}
* @since 5.7.14
*/
- public static Calendar parse(final CharSequence str, final boolean lenient, final DateParser parser) {
+ public static Calendar parse(final CharSequence str, final boolean lenient, final PositionDateParser parser) {
final Calendar calendar = Calendar.getInstance(parser.getTimeZone(), parser.getLocale());
calendar.clear();
calendar.setLenient(lenient);
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java b/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java
index 9a748656e..9178b4a34 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java
@@ -1,12 +1,13 @@
package cn.hutool.core.date;
-import cn.hutool.core.date.format.DateParser;
import cn.hutool.core.date.format.DatePrinter;
import cn.hutool.core.date.format.FastDateFormat;
import cn.hutool.core.date.format.GlobalCustomFormat;
+import cn.hutool.core.date.format.parser.DateParser;
+import cn.hutool.core.date.format.parser.PositionDateParser;
import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.text.StrUtil;
+import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.SystemUtil;
import java.sql.Timestamp;
@@ -310,7 +311,7 @@ public class DateTime extends Date {
* @param dateParser 格式化器 {@link DateParser},可以使用 {@link FastDateFormat}
* @see DatePattern
*/
- public DateTime(final CharSequence dateStr, final DateParser dateParser) {
+ public DateTime(final CharSequence dateStr, final PositionDateParser dateParser) {
this(dateStr, dateParser, SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, true));
}
@@ -322,7 +323,7 @@ public class DateTime extends Date {
* @param lenient 是否宽容模式
* @see DatePattern
*/
- public DateTime(final CharSequence dateStr, final DateParser dateParser, final boolean lenient) {
+ public DateTime(final CharSequence dateStr, final PositionDateParser dateParser, final boolean lenient) {
this(parse(dateStr, dateParser, lenient));
}
@@ -1087,7 +1088,7 @@ public class DateTime extends Date {
* @param lenient 是否宽容模式
* @return {@link Calendar}
*/
- private static Calendar parse(final CharSequence dateStr, final DateParser parser, final boolean lenient) {
+ private static Calendar parse(final CharSequence dateStr, final PositionDateParser parser, final boolean lenient) {
Assert.notNull(parser, "Parser or DateFromat must be not null !");
Assert.notBlank(dateStr, "Date String must be not blank !");
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 2946f4a55..c5e69f613 100755
--- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java
@@ -2,16 +2,20 @@ package cn.hutool.core.date;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.comparator.CompareUtil;
-import cn.hutool.core.date.format.DateParser;
import cn.hutool.core.date.format.DatePrinter;
import cn.hutool.core.date.format.FastDateFormat;
import cn.hutool.core.date.format.GlobalCustomFormat;
+import cn.hutool.core.date.format.parser.CSTDateParser;
+import cn.hutool.core.date.format.parser.DateParser;
+import cn.hutool.core.date.format.parser.NormalDateParser;
+import cn.hutool.core.date.format.parser.PureDateParser;
+import cn.hutool.core.date.format.parser.TimeParser;
+import cn.hutool.core.date.format.parser.UTCDateParser;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.regex.PatternPool;
import cn.hutool.core.regex.ReUtil;
import cn.hutool.core.text.StrUtil;
-import cn.hutool.core.util.CharUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -656,28 +660,6 @@ public class DateUtil extends CalendarUtil {
// ------------------------------------ Parse start ----------------------------------------------
- /**
- * 构建LocalDateTime对象
- * 格式:yyyy-MM-dd HH:mm:ss
- *
- * @param dateStr 时间字符串(带格式)
- * @return LocalDateTime对象
- */
- public static LocalDateTime parseLocalDateTime(final CharSequence dateStr) {
- return parseLocalDateTime(dateStr, DatePattern.NORM_DATETIME_PATTERN);
- }
-
- /**
- * 构建LocalDateTime对象
- *
- * @param dateStr 时间字符串(带格式)
- * @param format 使用{@link DatePattern}定义的格式
- * @return LocalDateTime对象
- */
- public static LocalDateTime parseLocalDateTime(final CharSequence dateStr, final String format) {
- return TimeUtil.parse(dateStr, format);
- }
-
/**
* 构建DateTime对象
*
@@ -765,154 +747,7 @@ public class DateUtil extends CalendarUtil {
* @since 5.3.11
*/
public static DateTime parse(final String str, final String... parsePatterns) throws DateException {
- return new DateTime(CalendarUtil.parseByPatterns(str, parsePatterns));
- }
-
- /**
- * 解析日期时间字符串,格式支持:
- *
- *
- * yyyy-MM-dd HH:mm:ss
- * yyyy/MM/dd HH:mm:ss
- * yyyy.MM.dd HH:mm:ss
- * yyyy年MM月dd日 HH:mm:ss
- *
- *
- * @param dateString 标准形式的时间字符串
- * @return 日期对象
- */
- public static DateTime parseDateTime(CharSequence dateString) {
- dateString = normalize(dateString);
- return parse(dateString, DatePattern.NORM_DATETIME_FORMAT);
- }
-
- /**
- * 解析日期字符串,忽略时分秒,支持的格式包括:
- *
- * yyyy-MM-dd
- * yyyy/MM/dd
- * yyyy.MM.dd
- * yyyy年MM月dd日
- *
- *
- * @param dateString 标准形式的日期字符串
- * @return 日期对象
- */
- public static DateTime parseDate(CharSequence dateString) {
- dateString = normalize(dateString);
- return parse(dateString, DatePattern.NORM_DATE_FORMAT);
- }
-
- /**
- * 解析时间,格式HH:mm:ss,日期部分默认为1970-01-01
- *
- * @param timeString 标准形式的日期字符串
- * @return 日期对象
- */
- public static DateTime parseTime(CharSequence timeString) {
- timeString = normalize(timeString);
- return parse(timeString, DatePattern.NORM_TIME_FORMAT);
- }
-
- /**
- * 解析时间,格式HH:mm 或 HH:mm:ss,日期默认为今天
- *
- * @param timeString 标准形式的日期字符串
- * @return 日期对象
- * @since 3.1.1
- */
- public static DateTime parseTimeToday(CharSequence timeString) {
- timeString = StrUtil.format("{} {}", formatToday(), timeString);
- if (1 == StrUtil.count(timeString, ':')) {
- // 时间格式为 HH:mm
- return parse(timeString, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
- } else {
- // 时间格式为 HH:mm:ss
- return parse(timeString, DatePattern.NORM_DATETIME_FORMAT);
- }
- }
-
- /**
- * 解析UTC时间,格式:
- *
- * - yyyy-MM-dd'T'HH:mm:ss'Z'
- * - 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时间
- * @return 日期对象
- * @since 4.1.14
- */
- public static DateTime parseUTC(String utcString) {
- if (utcString == null) {
- return null;
- }
- final int length = utcString.length();
- if (StrUtil.contains(utcString, 'Z')) {
- if (length == DatePattern.UTC_PATTERN.length() - 4) {
- // 格式类似:2018-09-13T05:34:31Z,-4表示减去4个单引号的长度
- return parse(utcString, DatePattern.UTC_FORMAT);
- }
-
- final int patternLength = DatePattern.UTC_MS_PATTERN.length();
- // 格式类似:2018-09-13T05:34:31.999Z,-4表示减去4个单引号的长度
- // -4 ~ -6范围表示匹配毫秒1~3位的情况
- 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_SIMPLE_PATTERN.length() - 2) {
- // 格式类似:2018-09-13T05:34:31
- return parse(utcString, DatePattern.UTC_SIMPLE_FORMAT);
- } else if (StrUtil.contains(utcString, CharUtil.DOT)) {
- // 可能为: 2021-03-17T06:31:33.99
- return parse(utcString, DatePattern.UTC_SIMPLE_MS_FORMAT);
- }
- }
- // 没有更多匹配的时间格式
- throw new DateException("No format fit for date String [{}] !", utcString);
- }
-
- /**
- * 解析CST时间,格式:
- *
- * - EEE MMM dd HH:mm:ss z yyyy(例如:Wed Aug 01 00:00:00 CST 2012)
- *
- *
- * @param cstString UTC时间
- * @return 日期对象
- * @since 4.6.9
- */
- public static DateTime parseCST(final CharSequence cstString) {
- if (cstString == null) {
- return null;
- }
-
- return parse(cstString, DatePattern.JDK_DATETIME_FORMAT);
+ return date(CalendarUtil.parseByPatterns(str, parsePatterns));
}
/**
@@ -951,64 +786,33 @@ public class DateUtil extends CalendarUtil {
String dateStr = dateCharSequence.toString();
// 去掉两边空格并去掉中文日期中的“日”和“秒”,以规范长度
dateStr = StrUtil.removeAll(dateStr.trim(), '日', '秒');
- final int length = dateStr.length();
if (NumberUtil.isNumber(dateStr)) {
// 纯数字形式
- if (length == DatePattern.PURE_DATETIME_PATTERN.length()) {
- return parse(dateStr, DatePattern.PURE_DATETIME_FORMAT);
- } else if (length == DatePattern.PURE_DATETIME_MS_PATTERN.length()) {
- return parse(dateStr, DatePattern.PURE_DATETIME_MS_FORMAT);
- } else if (length == DatePattern.PURE_DATE_PATTERN.length()) {
- return parse(dateStr, DatePattern.PURE_DATE_FORMAT);
- } else if (length == DatePattern.PURE_TIME_PATTERN.length()) {
- return parse(dateStr, DatePattern.PURE_TIME_FORMAT);
- }
+ return PureDateParser.INSTANCE.parse(dateStr);
} else if (ReUtil.isMatch(PatternPool.TIME, dateStr)) {
// HH:mm:ss 或者 HH:mm 时间格式匹配单独解析
- return parseTimeToday(dateStr);
+ return TimeParser.INSTANCE.parse(dateStr);
} else if (StrUtil.containsAnyIgnoreCase(dateStr, wtb)) {
// JDK的Date对象toString默认格式,类似于:
// Tue Jun 4 16:25:15 +0800 2019
// Thu May 16 17:57:18 GMT+08:00 2019
// Wed Aug 01 00:00:00 CST 2012
- return parseCST(dateStr);
+ return CSTDateParser.INSTANCE.parse(dateStr);
} else if (StrUtil.contains(dateStr, 'T')) {
// UTC时间
- return parseUTC(dateStr);
+ return UTCDateParser.INSTANCE.parse(dateStr);
}
//标准日期格式(包括单个数字的日期时间)
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 parse(dateStr, DatePattern.NORM_DATE_FORMAT);
- case 1:
- // yyyy-MM-dd HH:mm
- return parse(dateStr, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
- case 2:
- final int indexOfDot = StrUtil.indexOf(dateStr, CharUtil.DOT);
- if (indexOfDot > 0) {
- final int length1 = dateStr.length();
- // yyyy-MM-dd HH:mm:ss.SSS 或者 yyyy-MM-dd HH:mm:ss.SSSSSS
- if (length1 - indexOfDot > 4) {
- // 类似yyyy-MM-dd HH:mm:ss.SSSSSS,采取截断操作
- dateStr = StrUtil.subPre(dateStr, indexOfDot + 4);
- }
- return parse(dateStr, DatePattern.NORM_DATETIME_MS_FORMAT);
- }
- // yyyy-MM-dd HH:mm:ss
- return parse(dateStr, DatePattern.NORM_DATETIME_FORMAT);
- }
+ return NormalDateParser.INSTANCE.parse(dateStr);
}
// 没有更多匹配的时间格式
throw new DateException("No format fit for date String [{}] !", dateStr);
}
-
// ------------------------------------ Parse end ----------------------------------------------
// ------------------------------------ Offset start ----------------------------------------------
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/DefaultDateBasic.java b/hutool-core/src/main/java/cn/hutool/core/date/format/DefaultDateBasic.java
new file mode 100644
index 000000000..15e3fea38
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/DefaultDateBasic.java
@@ -0,0 +1,34 @@
+package cn.hutool.core.date.format;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * 默认日期基本信息类,包括:
+ *
+ * - {@link #getPattern()}返回{@code null}
+ * - {@link #getTimeZone()} ()}返回{@link TimeZone#getDefault()}
+ * - {@link #getLocale()} ()} ()}返回{@link Locale#getDefault()}
+ *
+ *
+ * @author looly
+ */
+public class DefaultDateBasic implements DateBasic, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public String getPattern() {
+ return null;
+ }
+
+ @Override
+ public TimeZone getTimeZone() {
+ return TimeZone.getDefault();
+ }
+
+ @Override
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateFormat.java b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateFormat.java
index 088403d5d..43d8b855e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateFormat.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateFormat.java
@@ -1,6 +1,8 @@
package cn.hutool.core.date.format;
import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.format.parser.FastDateParser;
+import cn.hutool.core.date.format.parser.PositionDateParser;
import java.text.DateFormat;
import java.text.FieldPosition;
@@ -29,7 +31,7 @@ import java.util.TimeZone;
* Thanks to Apache Commons Lang 3.5
* @since 2.16.2
*/
-public class FastDateFormat extends Format implements DateParser, DatePrinter {
+public class FastDateFormat extends Format implements PositionDateParser, DatePrinter {
private static final long serialVersionUID = 8097890768636183236L;
/** FULL locale dependent date or time style. */
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java
index b69e32b86..7b7dbd518 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/FastDatePrinter.java
@@ -1,6 +1,7 @@
package cn.hutool.core.date.format;
import cn.hutool.core.date.DateException;
+import cn.hutool.core.date.format.parser.FastDateParser;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -20,7 +21,7 @@ import java.util.concurrent.ConcurrentMap;
*
* @see FastDateParser
*/
-public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
+public class FastDatePrinter extends SimpleDateBasic implements DatePrinter {
private static final long serialVersionUID = -6305750172255764887L;
/** 规则列表. */
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/AbstractDateBasic.java b/hutool-core/src/main/java/cn/hutool/core/date/format/SimpleDateBasic.java
similarity index 68%
rename from hutool-core/src/main/java/cn/hutool/core/date/format/AbstractDateBasic.java
rename to hutool-core/src/main/java/cn/hutool/core/date/format/SimpleDateBasic.java
index 889ea7006..df3fc92ca 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/AbstractDateBasic.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/SimpleDateBasic.java
@@ -4,23 +4,35 @@ import java.io.Serializable;
import java.util.Locale;
import java.util.TimeZone;
-public abstract class AbstractDateBasic implements DateBasic, Serializable {
+/**
+ * 抽象日期基本信息类,包括日期格式、时区、本地化等信息
+ *
+ * @author looly
+ */
+public class SimpleDateBasic implements DateBasic, Serializable {
private static final long serialVersionUID = 6333136319870641818L;
- /** The pattern */
- protected final String pattern;
- /** The time zone. */
+ /**
+ * The pattern
+ */
+ protected final String pattern;
+ /**
+ * The time zone.
+ */
protected final TimeZone timeZone;
- /** The locale. */
+ /**
+ * The locale.
+ */
protected final Locale locale;
/**
* 构造,内部使用
- * @param pattern 使用{@link java.text.SimpleDateFormat} 相同的日期格式
+ *
+ * @param pattern 使用{@link java.text.SimpleDateFormat} 相同的日期格式
* @param timeZone 非空时区{@link TimeZone}
- * @param locale 非空{@link Locale} 日期地理位置
+ * @param locale 非空{@link Locale} 日期地理位置
*/
- protected AbstractDateBasic(final String pattern, final TimeZone timeZone, final Locale locale) {
+ protected SimpleDateBasic(final String pattern, final TimeZone timeZone, final Locale locale) {
this.pattern = pattern;
this.timeZone = timeZone;
this.locale = locale;
@@ -48,7 +60,7 @@ public abstract class AbstractDateBasic implements DateBasic, Serializable {
if (obj instanceof FastDatePrinter == false) {
return false;
}
- final AbstractDateBasic other = (AbstractDateBasic) obj;
+ final SimpleDateBasic other = (SimpleDateBasic) obj;
return pattern.equals(other.pattern) && timeZone.equals(other.timeZone) && locale.equals(other.locale);
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java
new file mode 100644
index 000000000..dbe94f8ed
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/CSTDateParser.java
@@ -0,0 +1,26 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.format.DefaultDateBasic;
+
+/**
+ * CST日期字符串(JDK的Date对象toString默认格式)解析,支持格式类似于;
+ *
+ * Tue Jun 4 16:25:15 +0800 2019
+ * Thu May 16 17:57:18 GMT+08:00 2019
+ * Wed Aug 01 00:00:00 CST 2012
+ *
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class CSTDateParser extends DefaultDateBasic implements DateParser {
+
+ public static CSTDateParser INSTANCE = new CSTDateParser();
+
+ @Override
+ public DateTime parse(final String source) {
+ return new DateTime(source, DatePattern.JDK_DATETIME_FORMAT);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/DateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/DateParser.java
new file mode 100644
index 000000000..189be48e4
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/DateParser.java
@@ -0,0 +1,35 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.format.DateBasic;
+
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * 日期解析接口,用于解析日期字符串为 {@link Date} 对象
+ * Thanks to Apache Commons Lang 3.5
+ */
+public interface DateParser extends DateBasic {
+
+ /**
+ * 将日期字符串解析并转换为 {@link Date} 对象
+ * 等价于 {@link java.text.DateFormat#parse(String)}
+ *
+ * @param source 被解析的日期字符串
+ * @return {@link Date}对象
+ * @throws ParseException 转换异常,被转换的字符串格式错误。
+ */
+ Date parse(String source) throws ParseException;
+
+ /**
+ * 将日期字符串解析并转换为 {@link Date} 对象
+ *
+ * @param source 被解析的日期字符串
+ * @return {@link Date}对象
+ * @throws ParseException if the beginning of the specified string cannot be parsed.
+ * @see java.text.DateFormat#parseObject(String)
+ */
+ default Object parseObject(final String source) throws ParseException {
+ return parse(source);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/FastDateParser.java
similarity index 98%
rename from hutool-core/src/main/java/cn/hutool/core/date/format/FastDateParser.java
rename to hutool-core/src/main/java/cn/hutool/core/date/format/parser/FastDateParser.java
index cc4ccff59..b4b38bb8f 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/FastDateParser.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/FastDateParser.java
@@ -1,4 +1,8 @@
-package cn.hutool.core.date.format;
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.format.FastDateFormat;
+import cn.hutool.core.date.format.FastDatePrinter;
+import cn.hutool.core.date.format.SimpleDateBasic;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -30,7 +34,7 @@ import java.util.regex.Pattern;
* @see FastDatePrinter
* @since 2.16.2
*/
-public class FastDateParser extends AbstractDateBasic implements DateParser {
+public class FastDateParser extends SimpleDateBasic implements PositionDateParser {
private static final long serialVersionUID = -3199383897950947498L;
static final Locale JAPANESE_IMPERIAL = new Locale("ja", "JP", "JP");
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java
new file mode 100644
index 000000000..f090b86ac
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/NormalDateParser.java
@@ -0,0 +1,54 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.DateException;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.format.DefaultDateBasic;
+import cn.hutool.core.text.StrUtil;
+import cn.hutool.core.util.CharUtil;
+
+/**
+ * 标准日期字符串解析,支持格式;
+ *
+ * yyyy-MM-dd HH:mm:ss.SSSSSS
+ * yyyy-MM-dd HH:mm:ss.SSS
+ * yyyy-MM-dd HH:mm:ss
+ * yyyy-MM-dd HH:mm
+ * yyyy-MM-dd
+ *
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class NormalDateParser extends DefaultDateBasic implements DateParser {
+
+ public static NormalDateParser INSTANCE = new NormalDateParser();
+
+ @Override
+ public DateTime parse(String source) {
+ final int colonCount = StrUtil.count(source, CharUtil.COLON);
+ switch (colonCount) {
+ case 0:
+ // yyyy-MM-dd
+ return new DateTime(source, DatePattern.NORM_DATE_FORMAT);
+ case 1:
+ // yyyy-MM-dd HH:mm
+ return new DateTime(source, DatePattern.NORM_DATETIME_MINUTE_FORMAT);
+ case 2:
+ final int indexOfDot = StrUtil.indexOf(source, CharUtil.DOT);
+ if (indexOfDot > 0) {
+ final int length1 = source.length();
+ // yyyy-MM-dd HH:mm:ss.SSS 或者 yyyy-MM-dd HH:mm:ss.SSSSSS
+ if (length1 - indexOfDot > 4) {
+ // 类似yyyy-MM-dd HH:mm:ss.SSSSSS,采取截断操作
+ source = StrUtil.subPre(source, indexOfDot + 4);
+ }
+ return new DateTime(source, DatePattern.NORM_DATETIME_MS_FORMAT);
+ }
+ // yyyy-MM-dd HH:mm:ss
+ return new DateTime(source, DatePattern.NORM_DATETIME_FORMAT);
+ }
+
+ throw new DateException("No format fit for date String [{}] !", source);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java
new file mode 100644
index 000000000..c4332a60b
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PatternsDateParser.java
@@ -0,0 +1,73 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.CalendarUtil;
+import cn.hutool.core.date.DateException;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.format.DefaultDateBasic;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * 通过给定的日期格式解析日期时间字符串。
+ * 传入的日期格式会逐个尝试,直到解析成功,返回{@link Calendar}对象,否则抛出{@link DateException}异常。
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class PatternsDateParser extends DefaultDateBasic implements DateParser {
+
+ /**
+ * 创建 PatternsDateParser
+ *
+ * @param parsePatterns 多个日期格式
+ * @return PatternsDateParser
+ */
+ public static PatternsDateParser of(final String... parsePatterns) {
+ return new PatternsDateParser(parsePatterns);
+ }
+
+ private String[] parsePatterns;
+ private Locale locale;
+
+ /**
+ * 构造
+ *
+ * @param parsePatterns 多个日期格式
+ */
+ public PatternsDateParser(final String... parsePatterns) {
+ this.parsePatterns = parsePatterns;
+ }
+
+ /**
+ * 设置多个日期格式
+ *
+ * @param parsePatterns 日期格式列表
+ * @return this
+ */
+ public PatternsDateParser setParsePatterns(final String... parsePatterns) {
+ this.parsePatterns = parsePatterns;
+ return this;
+ }
+
+ /**
+ * 设置{@link Locale}
+ *
+ * @param locale {@link Locale}
+ * @return this
+ */
+ public PatternsDateParser setLocale(final Locale locale) {
+ this.locale = locale;
+ return this;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return locale;
+ }
+
+ @Override
+ public DateTime parse(final String source) {
+ return new DateTime(CalendarUtil.parseByPatterns(source, this.locale, this.parsePatterns));
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/DateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PositionDateParser.java
similarity index 56%
rename from hutool-core/src/main/java/cn/hutool/core/date/format/DateParser.java
rename to hutool-core/src/main/java/cn/hutool/core/date/format/parser/PositionDateParser.java
index 998b38dc4..62fbcfc89 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/DateParser.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PositionDateParser.java
@@ -1,33 +1,23 @@
-package cn.hutool.core.date.format;
+package cn.hutool.core.date.format.parser;
-import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
/**
- * 日期解析接口,用于解析日期字符串为 {@link Date} 对象
+ * 带有{@link ParsePosition}的日期解析接口,用于解析日期字符串为 {@link Date} 对象
* Thanks to Apache Commons Lang 3.5
+ *
* @since 2.16.2
*/
-public interface DateParser extends DateBasic{
-
- /**
- * 将日期字符串解析并转换为 {@link Date} 对象
- * 等价于 {@link java.text.DateFormat#parse(String)}
- *
- * @param source 日期字符串
- * @return {@link Date}
- * @throws ParseException 转换异常,被转换的字符串格式错误。
- */
- Date parse(String source) throws ParseException;
+public interface PositionDateParser extends DateParser {
/**
* 将日期字符串解析并转换为 {@link Date} 对象
* 等价于 {@link java.text.DateFormat#parse(String, ParsePosition)}
*
* @param source 日期字符串
- * @param pos {@link ParsePosition}
+ * @param pos {@link ParsePosition}
* @return {@link Date}
*/
Date parse(String source, ParsePosition pos);
@@ -38,35 +28,23 @@ public interface DateParser extends DateBasic{
* Not all source text needs to be consumed.
* Upon parse failure, ParsePosition error index is updated to the offset of the source text which does not match the supplied format.
*
- * @param source 被转换的日期字符串
- * @param pos 定义开始转换的位置,转换结束后更新转换到的位置
+ * @param source 被转换的日期字符串
+ * @param pos 定义开始转换的位置,转换结束后更新转换到的位置
* @param calendar The calendar into which to set parsed fields.
* @return true, if source has been parsed (pos parsePosition is updated); otherwise false (and pos errorIndex is updated)
* @throws IllegalArgumentException when Calendar has been set to be not lenient, and a parsed field is out of range.
*/
boolean parse(String source, ParsePosition pos, Calendar calendar);
- /**
- * 将日期字符串解析并转换为 {@link Date} 对象
- *
- * @param source A {@code String} whose beginning should be parsed.
- * @return a {@code java.util.Date} object
- * @throws ParseException if the beginning of the specified string cannot be parsed.
- * @see java.text.DateFormat#parseObject(String)
- */
- default Object parseObject(final String source) throws ParseException{
- return parse(source);
- }
-
/**
* 根据 {@link ParsePosition} 给定将日期字符串解析并转换为 {@link Date} 对象
*
* @param source A {@code String} whose beginning should be parsed.
- * @param pos the parse position
+ * @param pos the parse position
* @return a {@code java.util.Date} object
* @see java.text.DateFormat#parseObject(String, ParsePosition)
*/
- default Object parseObject(final String source, final ParsePosition pos){
+ default Object parseObject(final String source, final ParsePosition pos) {
return parse(source, pos);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java
new file mode 100644
index 000000000..e5dd0f30e
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/PureDateParser.java
@@ -0,0 +1,41 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.DateException;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.format.DefaultDateBasic;
+
+/**
+ * 纯数字的日期字符串解析,支持格式包括;
+ *
+ * - yyyyMMddHHmmss
+ * - yyyyMMddHHmmssSSS
+ * - yyyyMMdd
+ * - HHmmss
+ *
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class PureDateParser extends DefaultDateBasic implements DateParser {
+
+ public static PureDateParser INSTANCE = new PureDateParser();
+
+ @Override
+ public DateTime parse(final String source) throws DateException {
+ final int length = source.length();
+ // 纯数字形式
+ if (length == DatePattern.PURE_DATETIME_PATTERN.length()) {
+ return new DateTime(source, DatePattern.PURE_DATETIME_FORMAT);
+ } else if (length == DatePattern.PURE_DATETIME_MS_PATTERN.length()) {
+ return new DateTime(source, DatePattern.PURE_DATETIME_MS_FORMAT);
+ } else if (length == DatePattern.PURE_DATE_PATTERN.length()) {
+ return new DateTime(source, DatePattern.PURE_DATE_FORMAT);
+ } else if (length == DatePattern.PURE_TIME_PATTERN.length()) {
+ return new DateTime(source, DatePattern.PURE_TIME_FORMAT);
+ }
+
+ throw new DateException("No pure format fit for date String [{}] !", source);
+ }
+
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java
new file mode 100644
index 000000000..c8aec9a26
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/TimeParser.java
@@ -0,0 +1,34 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.format.DefaultDateBasic;
+import cn.hutool.core.text.StrUtil;
+
+/**
+ * 时间日期字符串,日期默认为当天,支持格式类似于;
+ *
+ * HH:mm:ss
+ * HH:mm
+ *
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class TimeParser extends DefaultDateBasic implements DateParser {
+
+ public static TimeParser INSTANCE = new TimeParser();
+
+ @Override
+ public DateTime parse(String source) {
+ source = StrUtil.format("{} {}", DateUtil.formatToday(), source);
+ if (1 == StrUtil.count(source, ':')) {
+ // 时间格式为 HH:mm
+ return new DateTime(source, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
+ } else {
+ // 时间格式为 HH:mm:ss
+ return new DateTime(source, DatePattern.NORM_DATETIME_FORMAT);
+ }
+ }
+}
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
new file mode 100644
index 000000000..9403c858a
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/UTCDateParser.java
@@ -0,0 +1,75 @@
+package cn.hutool.core.date.format.parser;
+
+import cn.hutool.core.date.DateException;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.format.DefaultDateBasic;
+import cn.hutool.core.text.StrUtil;
+import cn.hutool.core.util.CharUtil;
+
+/**
+ * UTC日期字符串(JDK的Date对象toString默认格式)解析,支持格式;
+ *
+ * - yyyy-MM-dd'T'HH:mm:ss'Z'
+ * - 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
+ *
+ *
+ * @author looly
+ * @since 6.0.0
+ */
+public class UTCDateParser extends DefaultDateBasic implements DateParser {
+
+ public static UTCDateParser INSTANCE = new UTCDateParser();
+
+ @Override
+ public DateTime parse(String source) {
+ final int length = source.length();
+ if (StrUtil.contains(source, 'Z')) {
+ if (length == DatePattern.UTC_PATTERN.length() - 4) {
+ // 格式类似:2018-09-13T05:34:31Z,-4表示减去4个单引号的长度
+ return new DateTime(source, DatePattern.UTC_FORMAT);
+ }
+
+ final int patternLength = DatePattern.UTC_MS_PATTERN.length();
+ // 格式类似:2018-09-13T05:34:31.999Z,-4表示减去4个单引号的长度
+ // -4 ~ -6范围表示匹配毫秒1~3位的情况
+ if (length <= patternLength - 4 && length >= patternLength - 6) {
+ return new DateTime(source, DatePattern.UTC_MS_FORMAT);
+ }
+ } else if (StrUtil.contains(source, '+')) {
+ // 去除类似2019-06-01T19:45:43 +08:00加号前的空格
+ source = source.replace(" +", "+");
+ final String zoneOffset = StrUtil.subAfter(source, '+', true);
+ if (StrUtil.isBlank(zoneOffset)) {
+ throw new DateException("Invalid format: [{}]", source);
+ }
+ if (false == StrUtil.contains(zoneOffset, ':')) {
+ // +0800转换为+08:00
+ final String pre = StrUtil.subBefore(source, '+', true);
+ source = pre + "+" + zoneOffset.substring(0, 2) + ":" + "00";
+ }
+
+ if (StrUtil.contains(source, CharUtil.DOT)) {
+ // 带毫秒,格式类似:2018-09-13T05:34:31.999+08:00
+ return new DateTime(source, DatePattern.UTC_MS_WITH_XXX_OFFSET_FORMAT);
+ } else {
+ // 格式类似:2018-09-13T05:34:31+08:00
+ return new DateTime(source, DatePattern.UTC_WITH_XXX_OFFSET_FORMAT);
+ }
+ } else {
+ if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 2) {
+ // 格式类似:2018-09-13T05:34:31
+ return new DateTime(source, DatePattern.UTC_SIMPLE_FORMAT);
+ } else if (StrUtil.contains(source, CharUtil.DOT)) {
+ // 可能为: 2021-03-17T06:31:33.99
+ return new DateTime(source, DatePattern.UTC_SIMPLE_MS_FORMAT);
+ }
+ }
+ // 没有更多匹配的时间格式
+ throw new DateException("No UTC format fit for date String [{}] !", source);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/parser/package-info.java b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/package-info.java
new file mode 100644
index 000000000..e321b02af
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/parser/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * 提供日期解析相关封装
+ *
+ * @author looly
+ *
+ */
+package cn.hutool.core.date.format.parser;
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/split/package-info.java b/hutool-core/src/main/java/cn/hutool/core/text/split/package-info.java
new file mode 100644
index 000000000..cbda2abbf
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/text/split/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * 字符串切分封装和工具类
+ *
+ * @author looly
+ */
+package cn.hutool.core.text.split;