This commit is contained in:
Looly 2024-12-08 13:42:09 +08:00
parent 705baea568
commit dc601b880b
8 changed files with 93 additions and 82 deletions

View File

@ -138,7 +138,7 @@ public class TemporalAccessorConverter extends AbstractConverter {
}
final Instant instant;
ZoneId zoneId = null;
final ZoneId zoneId;
if (null != this.format) {
final DateTimeFormatter formatter = TimeUtil.ofPattern(this.format);

View File

@ -792,19 +792,8 @@ public class CalendarUtil {
*/
public static Calendar parse(final CharSequence str, final PositionDateParser parser,
final boolean lenient) throws DateException{
Assert.notBlank(str, "Date str must be not blank!");
Assert.notNull(parser, "Parser must be not null!");
final Calendar calendar = Calendar.getInstance(parser.getTimeZone(), parser.getLocale());
calendar.clear();
calendar.setLenient(lenient);
final ParsePosition position = new ParsePosition(0);
if (parser.parse(str.toString(), position, calendar)) {
return calendar;
}
throw new DateException("Parse [{}] with format [{}] error, at: {}",
str, parser.getPattern(), position.getErrorIndex());
return parser.parseCalendar(str, null, lenient);
}
// endregion

View File

@ -16,15 +16,14 @@
package org.dromara.hutool.core.date;
import org.dromara.hutool.core.date.format.DateFormatManager;
import org.dromara.hutool.core.date.format.DatePrinter;
import org.dromara.hutool.core.date.format.FastDateFormat;
import org.dromara.hutool.core.date.format.DateFormatManager;
import org.dromara.hutool.core.date.format.parser.DateParser;
import org.dromara.hutool.core.date.format.parser.PositionDateParser;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.util.SystemUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -297,9 +296,7 @@ public class DateTime extends Date {
* @see DateFormatPool
*/
public DateTime(final CharSequence dateStr, final String format) {
this(DateFormatManager.getInstance().isCustomFormat(format)
? DateFormatManager.getInstance().parse(dateStr, format)
: parse(dateStr, DateUtil.newSimpleFormat(format)));
this(parse(dateStr, format));
}
/**
@ -332,7 +329,7 @@ public class DateTime extends Date {
* @see DateFormatPool
*/
public DateTime(final CharSequence dateStr, final PositionDateParser dateParser) {
this(dateStr, dateParser, SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, false));
this(dateStr, dateParser, DateUtil.isGlobalLenient());
}
/**
@ -1076,6 +1073,20 @@ public class DateTime extends Date {
}
// -------------------------------------------------------------------- toString end
/**
* 转换字符串为Date
*
* @param dateStr 日期字符串
* @param format 格式字符串
* @return {@link Date}
*/
private static Date parse(final CharSequence dateStr, final String format) {
final DateFormatManager formatManager = DateFormatManager.getInstance();
return formatManager.isCustomFormat(format)
? formatManager.parse(dateStr, format)
: parse(dateStr, DateUtil.newSimpleFormat(format));
}
/**
* 转换字符串为Date
*
@ -1098,21 +1109,6 @@ public class DateTime extends Date {
}
}
/**
* 转换字符串为Date
*
* @param dateStr 日期字符串
* @param parser {@link FastDateFormat}
* @param lenient 是否宽容模式
* @return {@link Calendar}
*/
private static Calendar parse(final CharSequence dateStr, final PositionDateParser parser, final boolean lenient) {
final Calendar calendar = CalendarUtil.parse(dateStr, parser, lenient);
//noinspection MagicConstant
calendar.setFirstDayOfWeek(Week.MONDAY.getValue());
return calendar;
}
/**
* 设置日期时间
*
@ -1123,4 +1119,19 @@ public class DateTime extends Date {
super.setTime(time);
return this;
}
/**
* 转换字符串为Date
*
* @param dateStr 日期字符串
* @param parser {@link FastDateFormat}
* @param lenient 是否宽容模式
* @return {@link Calendar}
*/
private static Calendar parse(final CharSequence dateStr, final PositionDateParser parser, final boolean lenient) {
final Calendar calendar = parser.parseCalendar(dateStr, null, lenient);
//noinspection MagicConstant
calendar.setFirstDayOfWeek(Week.MONDAY.getValue());
return calendar;
}
}

View File

@ -743,24 +743,6 @@ public class DateUtil {
return new DateTime(dateStr, format);
}
/**
* 将特定格式的日期转换为Date对象
*
* @param dateStr 特定格式的日期
* @param format 格式例如yyyy-MM-dd
* @param locale 区域信息
* @return 日期对象
* @since 4.5.18
*/
public static DateTime parse(final CharSequence dateStr, final String format, final Locale locale) {
final DateFormatManager formatManager = DateFormatManager.getInstance();
if (formatManager.isCustomFormat(format)) {
// 自定义格式化器忽略Locale
return new DateTime(formatManager.parse(dateStr, format));
}
return new DateTime(dateStr, DateUtil.newSimpleFormat(format, locale, null));
}
/**
* 通过给定的日期格式解析日期时间字符串<br>
* 传入的日期格式会逐个尝试直到解析成功返回{@link DateTime}对象否则抛出{@link DateException}异常
@ -1935,6 +1917,16 @@ public class DateUtil {
return java.time.Month.of(month).length(isLeapYear);
}
/**
* 获取全局参数是否日期解析宽容模式未定义时返回false<br>
* 通过系统参数{@code hutool.date.lenient}定义
*
* @return 是否日期解析宽容模式
*/
public static boolean isGlobalLenient() {
return SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, false);
}
/**
* 创建{@link SimpleDateFormat}注意此对象非线程安全<br>
* 此对象默认为严格格式模式即parse时如果格式不正确会报错
@ -1959,8 +1951,7 @@ public class DateUtil {
*/
public static SimpleDateFormat newSimpleFormat(final String pattern,
final Locale locale, final TimeZone timeZone) {
return newSimpleFormat(pattern, locale, timeZone,
SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, false));
return newSimpleFormat(pattern, locale, timeZone, isGlobalLenient());
}
/**

View File

@ -366,11 +366,6 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr
return parser.parse(source);
}
@Override
public Date parse(final CharSequence source, final ParsePosition pos) {
return parser.parse(source, pos);
}
@Override
public boolean parse(final CharSequence source, final ParsePosition pos, final Calendar calendar) {
return parser.parse(source, pos, calendar);

View File

@ -244,16 +244,11 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse
}
@Override
public Date parse(final CharSequence source, final ParsePosition pos) {
// timing tests indicate getting new instance is 19% faster than cloning
final Calendar cal = Calendar.getInstance(timeZone, locale);
cal.clear();
public boolean parse(final CharSequence source, ParsePosition pos, final Calendar calendar) {
if(null == pos){
pos = new ParsePosition(0);
}
return parse(source, pos, cal) ? cal.getTime() : null;
}
@Override
public boolean parse(final CharSequence source, final ParsePosition pos, final Calendar calendar) {
final ListIterator<StrategyAndWidth> lt = patterns.listIterator();
while (lt.hasNext()) {
final StrategyAndWidth strategyAndWidth = lt.next();

View File

@ -16,7 +16,10 @@
package org.dromara.hutool.core.date.format.parser;
import org.dromara.hutool.core.date.DateException;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.format.DateBasic;
import org.dromara.hutool.core.lang.Assert;
import java.text.ParsePosition;
import java.util.Calendar;
@ -26,10 +29,23 @@ import java.util.Date;
* 带有{@link ParsePosition}的日期解析接口用于解析日期字符串为 {@link Date} 对象<br>
* Thanks to Apache Commons Lang 3.5
*
* @since 2.16.2
* @author Looly
* @since 6.0.0
*/
public interface PositionDateParser extends DateParser, DateBasic {
/**
* 根据给定格式更新{@link Calendar}<br>
* 解析成功后{@link ParsePosition#getIndex()}更新成转换到的位置<br>
* 失败则{@link ParsePosition#getErrorIndex()}更新到解析失败的位置
*
* @param source 被转换的日期字符串
* @param pos 定义开始转换的位置转换结束后更新转换到的位置{@code null}表示忽略从第一个字符开始转换
* @param calendar 解析并更新的{@link Calendar}
* @return 解析成功返回 {@code true}否则返回{@code false}
*/
boolean parse(CharSequence source, ParsePosition pos, Calendar calendar);
/**
* 将日期字符串解析并转换为 {@link Date} 对象<br>
* 等价于 {@link java.text.DateFormat#parse(String, ParsePosition)}
@ -38,17 +54,31 @@ public interface PositionDateParser extends DateParser, DateBasic {
* @param pos {@link ParsePosition}
* @return {@link Date}
*/
Date parse(CharSequence source, ParsePosition pos);
default Date parse(final CharSequence source, final ParsePosition pos){
return parseCalendar(source, pos, DateUtil.isGlobalLenient()).getTime();
}
/**
* 根据给定格式更新{@link Calendar}<br>
* 解析成功后{@link ParsePosition#getIndex()}更新成转换到的位置<br>
* 失败则{@link ParsePosition#getErrorIndex()}更新到解析失败的位置
* 将日期字符串解析并转换为 {@link Calendar} 对象<br>
*
* @param source 被转换的日期字符串
* @param pos 定义开始转换的位置转换结束后更新转换到的位置
* @param calendar 解析并更新的{@link Calendar}
* @return 解析成功返回 {@code true}否则返回{@code false}
* @param source 日期字符串
* @param pos {@link ParsePosition}
* @param lenient 是否宽容模式
* @return {@link Calendar}
*/
boolean parse(CharSequence source, ParsePosition pos, Calendar calendar);
default Calendar parseCalendar(final CharSequence source, final ParsePosition pos, final boolean lenient){
Assert.notBlank(source, "Date str must be not blank!");
// timing tests indicate getting new instance is 19% faster than cloning
final Calendar calendar = Calendar.getInstance(getTimeZone(), getLocale());
calendar.clear();
calendar.setLenient(lenient);
if (parse(source.toString(), pos, calendar)) {
return calendar;
}
throw new DateException("Parse [{}] with format [{}] error, at: {}",
source, getPattern(), pos.getErrorIndex());
}
}

View File

@ -17,10 +17,10 @@
/**
* 提供日期解析相关封装主要包括
* <pre>
* DateParser
* / \
* FastDateParser RegisterDateParser
* 根据日期格式解析 根据注册的模式匹配解析
* DateParser
* / | \
* FastDateParser RegisterDateParser RegexDateParser
* 根据日期格式解析 根据注册的模式匹配解析 通过预定义正则解析
* </pre>
*
* @author looly