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; final Instant instant;
ZoneId zoneId = null; final ZoneId zoneId;
if (null != this.format) { if (null != this.format) {
final DateTimeFormatter formatter = TimeUtil.ofPattern(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, public static Calendar parse(final CharSequence str, final PositionDateParser parser,
final boolean lenient) throws DateException{ final boolean lenient) throws DateException{
Assert.notBlank(str, "Date str must be not blank!");
Assert.notNull(parser, "Parser must be not null!"); Assert.notNull(parser, "Parser must be not null!");
final Calendar calendar = Calendar.getInstance(parser.getTimeZone(), parser.getLocale()); return parser.parseCalendar(str, null, lenient);
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());
} }
// endregion // endregion

View File

@ -16,15 +16,14 @@
package org.dromara.hutool.core.date; 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.DatePrinter;
import org.dromara.hutool.core.date.format.FastDateFormat; 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.DateParser;
import org.dromara.hutool.core.date.format.parser.PositionDateParser; import org.dromara.hutool.core.date.format.parser.PositionDateParser;
import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.core.util.SystemUtil;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -297,9 +296,7 @@ public class DateTime extends Date {
* @see DateFormatPool * @see DateFormatPool
*/ */
public DateTime(final CharSequence dateStr, final String format) { public DateTime(final CharSequence dateStr, final String format) {
this(DateFormatManager.getInstance().isCustomFormat(format) this(parse(dateStr, format));
? DateFormatManager.getInstance().parse(dateStr, format)
: parse(dateStr, DateUtil.newSimpleFormat(format)));
} }
/** /**
@ -332,7 +329,7 @@ public class DateTime extends Date {
* @see DateFormatPool * @see DateFormatPool
*/ */
public DateTime(final CharSequence dateStr, final PositionDateParser dateParser) { 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 // -------------------------------------------------------------------- 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 * 转换字符串为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); super.setTime(time);
return this; 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); 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> * 通过给定的日期格式解析日期时间字符串<br>
* 传入的日期格式会逐个尝试直到解析成功返回{@link DateTime}对象否则抛出{@link DateException}异常 * 传入的日期格式会逐个尝试直到解析成功返回{@link DateTime}对象否则抛出{@link DateException}异常
@ -1935,6 +1917,16 @@ public class DateUtil {
return java.time.Month.of(month).length(isLeapYear); 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> * 创建{@link SimpleDateFormat}注意此对象非线程安全<br>
* 此对象默认为严格格式模式即parse时如果格式不正确会报错 * 此对象默认为严格格式模式即parse时如果格式不正确会报错
@ -1959,8 +1951,7 @@ public class DateUtil {
*/ */
public static SimpleDateFormat newSimpleFormat(final String pattern, public static SimpleDateFormat newSimpleFormat(final String pattern,
final Locale locale, final TimeZone timeZone) { final Locale locale, final TimeZone timeZone) {
return newSimpleFormat(pattern, locale, timeZone, return newSimpleFormat(pattern, locale, timeZone, isGlobalLenient());
SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, false));
} }
/** /**

View File

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

View File

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

View File

@ -16,7 +16,10 @@
package org.dromara.hutool.core.date.format.parser; 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.date.format.DateBasic;
import org.dromara.hutool.core.lang.Assert;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.util.Calendar; import java.util.Calendar;
@ -26,10 +29,23 @@ import java.util.Date;
* 带有{@link ParsePosition}的日期解析接口用于解析日期字符串为 {@link Date} 对象<br> * 带有{@link ParsePosition}的日期解析接口用于解析日期字符串为 {@link Date} 对象<br>
* Thanks to Apache Commons Lang 3.5 * Thanks to Apache Commons Lang 3.5
* *
* @since 2.16.2 * @author Looly
* @since 6.0.0
*/ */
public interface PositionDateParser extends DateParser, DateBasic { 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 Date} 对象<br>
* 等价于 {@link java.text.DateFormat#parse(String, ParsePosition)} * 等价于 {@link java.text.DateFormat#parse(String, ParsePosition)}
@ -38,17 +54,31 @@ public interface PositionDateParser extends DateParser, DateBasic {
* @param pos {@link ParsePosition} * @param pos {@link ParsePosition}
* @return {@link Date} * @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 Calendar} 对象<br>
* 解析成功后{@link ParsePosition#getIndex()}更新成转换到的位置<br>
* 失败则{@link ParsePosition#getErrorIndex()}更新到解析失败的位置
* *
* @param source 被转换的日期字符串 * @param source 日期字符串
* @param pos 定义开始转换的位置转换结束后更新转换到的位置 * @param pos {@link ParsePosition}
* @param calendar 解析并更新的{@link Calendar} * @param lenient 是否宽容模式
* @return 解析成功返回 {@code true}否则返回{@code false} * @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

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