This commit is contained in:
Looly 2023-12-14 23:28:10 +08:00
parent 251c6ee6ee
commit 175881681c
11 changed files with 96 additions and 86 deletions

View File

@ -19,9 +19,6 @@ import org.dromara.hutool.core.date.format.FastDateFormat;
import org.dromara.hutool.core.date.format.GlobalCustomFormat;
import org.dromara.hutool.core.date.format.parser.*;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.regex.PatternPool;
import org.dromara.hutool.core.regex.ReUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
@ -807,21 +804,9 @@ public class DateUtil extends CalendarUtil {
// 去掉两边空格并去掉中文日期中的以规范长度
dateStr = StrUtil.removeAll(dateStr.trim(), '日', '秒');
if (PureDateParser.INSTANCE.test(dateStr)) {
// 纯数字形式
return PureDateParser.INSTANCE.parse(dateStr);
} else if (TimeParser.INSTANCE.test(dateStr)) {
// HH:mm:ss 或者 HH:mm 时间格式匹配单独解析
return TimeParser.INSTANCE.parse(dateStr);
} else if (CSTDateParser.INSTANCE.test(dateStr)) {
// 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 CSTDateParser.INSTANCE.parse(dateStr);
} else if (ISO8601DateParser.INSTANCE.test(dateStr)) {
// ISO8601标准时间
return ISO8601DateParser.INSTANCE.parse(dateStr);
final Date result = RegisterDateParser.INSTANCE.parse(dateStr);
if(null != result){
return date(result);
}
//标准日期格式包括单个数字的日期时间

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.core.date.format;
import org.dromara.hutool.core.date.DateException;
import org.dromara.hutool.core.date.DatePattern;
import org.dromara.hutool.core.date.format.parser.FastDateParser;
import org.dromara.hutool.core.date.format.parser.PositionDateParser;
@ -344,7 +345,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
// ----------------------------------------------------------------------- Parsing
@Override
public Date parse(final String source) throws ParseException {
public Date parse(final String source) throws DateException {
return parser.parse(source);
}
@ -360,7 +361,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
@Override
public Object parseObject(final String source, final ParsePosition pos) {
return parser.parseObject(source, pos);
return parser.parse(source, pos);
}
// ----------------------------------------------------------------------- Accessors

View File

@ -47,8 +47,8 @@ public class GlobalCustomFormat {
parserMap = new SafeConcurrentHashMap<>();
// Hutool预设的几种自定义格式
putFormatter(FORMAT_SECONDS, (date) -> String.valueOf(Math.floorDiv(date.getTime(), 1000)));
putParser(FORMAT_SECONDS, (dateStr) -> DateUtil.date(Math.multiplyExact(Long.parseLong(dateStr.toString()), 1000)));
putFormatter(FORMAT_SECONDS, (date) -> String.valueOf(Math.floorDiv(date.getTime(), 1000L)));
putParser(FORMAT_SECONDS, (dateStr) -> DateUtil.date(Math.multiplyExact(Long.parseLong(dateStr.toString()), 1000L)));
putFormatter(FORMAT_MILLISECONDS, (date) -> String.valueOf(date.getTime()));
putParser(FORMAT_MILLISECONDS, (dateStr) -> DateUtil.date(Long.parseLong(dateStr.toString())));

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.core.date.format.parser;
import org.dromara.hutool.core.date.DateException;
import org.dromara.hutool.core.date.format.DateBasic;
import java.text.ParseException;
@ -29,19 +30,7 @@ public interface DateParser extends DateBasic{
*
* @param source 被解析的日期字符串
* @return {@link Date}对象
* @throws ParseException 转换异常被转换的字符串格式错误
* @throws DateException 转换异常被转换的字符串格式错误
*/
Date parse(String source) throws ParseException;
/**
* 将日期字符串解析并转换为 {@link Date} 对象<br>
*
* @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);
}
Date parse(String source) throws DateException;
}

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.core.date.format.parser;
import org.dromara.hutool.core.date.DateException;
import org.dromara.hutool.core.date.format.FastDateFormat;
import org.dromara.hutool.core.date.format.FastDatePrinter;
import org.dromara.hutool.core.date.format.SimpleDateBasic;
@ -20,21 +21,8 @@ import org.dromara.hutool.core.map.SafeConcurrentHashMap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -236,16 +224,16 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse
}
@Override
public Date parse(final String source) throws ParseException {
public Date parse(final String source) throws DateException {
final ParsePosition pp = new ParsePosition(0);
final Date date = parse(source, pp);
if (date == null) {
// Add a note re supported date range
if (locale.equals(JAPANESE_IMPERIAL)) {
throw new ParseException("(The " + locale + " locale does not support dates before 1868 AD)\n" +
throw new DateException("(The " + locale + " locale does not support dates before 1868 AD)\n" +
"Unparseable date: \"" + source, pp.getErrorIndex());
}
throw new ParseException("Unparseable date: " + source, pp.getErrorIndex());
throw new DateException("Unparseable date: " + source, pp.getErrorIndex());
}
return date;
}
@ -367,16 +355,6 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse
this.pattern = Pattern.compile(regex);
}
/**
* Is this field a number? The default implementation returns false.
*
* @return true, if field is a number
*/
@Override
boolean isNumber() {
return false;
}
@Override
boolean parse(final FastDateParser parser, final Calendar calendar, final String source, final ParsePosition pos, final int maxWidth) {
final Matcher matcher = pattern.matcher(source.substring(pos.getIndex()));
@ -507,11 +485,6 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse
this.formatField = formatField;
}
@Override
boolean isNumber() {
return false;
}
@Override
boolean parse(final FastDateParser parser, final Calendar calendar, final String source, final ParsePosition pos, final int maxWidth) {
for (int idx = 0; idx < formatField.length(); ++idx) {

View File

@ -49,7 +49,7 @@ public class ISO8601DateParser extends DefaultDateBasic implements PredicateDate
}
@Override
public DateTime parse(String source) {
public DateTime parse(String source) throws DateException{
final int length = source.length();
if (StrUtil.contains(source, 'Z')) {
if (length == DatePattern.UTC_PATTERN.length() - 4) {

View File

@ -52,7 +52,7 @@ public class NormalDateParser extends DefaultDateBasic implements PredicateDateP
}
@Override
public DateTime parse(String source) {
public DateTime parse(String source) throws DateException{
final int colonCount = StrUtil.count(source, CharUtil.COLON);
switch (colonCount) {
case 0:

View File

@ -47,16 +47,4 @@ public interface PositionDateParser extends DateParser {
* @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 ParsePosition} 给定将日期字符串解析并转换为 {@link Date} 对象<br>
*
* @param source A {@code String} whose beginning should be parsed.
* @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) {
return parse(source, pos);
}
}

View File

@ -3,7 +3,8 @@ package org.dromara.hutool.core.date.format.parser;
import java.util.function.Predicate;
/**
* 通过判断字符串的匹配解析为日期
* 通过判断字符串的匹配解析为日期<br>
* 通过实现{@link #test(Object)}方法判断字符串是否符合此解析器的规则如果符合则调用{@link #parse(String)}完成解析
*
* @author looly
* @since 6.0.0

View File

@ -0,0 +1,68 @@
package org.dromara.hutool.core.date.format.parser;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateException;
import org.dromara.hutool.core.date.format.DefaultDateBasic;
import java.util.Date;
import java.util.List;
/**
* 基于注册的日期解析器通过遍历列表找到合适的解析器然后解析为日期<br>
* 默认的可以调用{@link #INSTANCE}使用全局的解析器亦或者通过构造自定义独立的注册解析器
*
* @author looly
* @since 6.0.0
*/
public class RegisterDateParser extends DefaultDateBasic implements DateParser {
private static final long serialVersionUID = 1L;
/**
* 单例
*/
public static final RegisterDateParser INSTANCE = new RegisterDateParser();
private final List<PredicateDateParser> parserList;
/**
* 构造
*/
public RegisterDateParser() {
parserList = ListUtil.of(
// 纯数字形式
PureDateParser.INSTANCE,
// HH:mm:ss 或者 HH:mm 时间格式匹配单独解析
TimeParser.INSTANCE,
// 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
CSTDateParser.INSTANCE,
// ISO8601标准时间
// yyyy-MM-dd'T'HH:mm:ss'Z'
// yyyy-MM-dd'T'HH:mm:ss+0800
ISO8601DateParser.INSTANCE
);
}
@Override
public Date parse(final String source) throws DateException {
return parserList
.stream()
.filter(predicateDateParser -> predicateDateParser.test(source))
.findFirst()
.map(predicateDateParser -> predicateDateParser.parse(source)).orElse(null);
}
/**
* 注册自定义的{@link PredicateDateParser}<br>
* 通过此方法用户可以自定义日期字符串的匹配和解析通过循环匹配找到合适的解析器解析之
*
* @param dateParser {@link PredicateDateParser}
* @return this
*/
public RegisterDateParser register(final PredicateDateParser dateParser) {
this.parserList.add(dateParser);
return this;
}
}

View File

@ -11,9 +11,14 @@
*/
/**
* 提供日期解析相关封装
* 提供日期解析相关封装主要包括
* <pre>
* DateParser
* / \
* FastDateParser RegisterDateParser
* 根据日期格式解析 根据注册的模式匹配解析
* </pre>
*
* @author looly
*
*/
package org.dromara.hutool.core.date.format.parser;