mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
add TemporalAccessorConverter
This commit is contained in:
parent
4702174334
commit
cb7912717e
@ -11,6 +11,7 @@
|
||||
* 【all】 部分接口添加FunctionalInterface修饰
|
||||
* 【crypto】 KeyUtil增加readKeyStore重载
|
||||
* 【extra】 JschUtil增加私钥传入支持(issue#INKDR@Gitee)
|
||||
* 【core】 DateUtil、DateTime、Convert全面支持jdk8的time包
|
||||
|
||||
### Bug修复
|
||||
* 【http】 修复Cookie中host失效导致的问题(issue#583@Github)
|
||||
|
@ -1,28 +1,5 @@
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Currency;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.impl.ArrayConverter;
|
||||
import cn.hutool.core.convert.impl.AtomicBooleanConverter;
|
||||
@ -37,7 +14,6 @@ import cn.hutool.core.convert.impl.CollectionConverter;
|
||||
import cn.hutool.core.convert.impl.CurrencyConverter;
|
||||
import cn.hutool.core.convert.impl.DateConverter;
|
||||
import cn.hutool.core.convert.impl.EnumConverter;
|
||||
import cn.hutool.core.convert.impl.Jdk8DateConverter;
|
||||
import cn.hutool.core.convert.impl.LocaleConverter;
|
||||
import cn.hutool.core.convert.impl.MapConverter;
|
||||
import cn.hutool.core.convert.impl.NumberConverter;
|
||||
@ -46,17 +22,47 @@ import cn.hutool.core.convert.impl.PrimitiveConverter;
|
||||
import cn.hutool.core.convert.impl.ReferenceConverter;
|
||||
import cn.hutool.core.convert.impl.StackTraceElementConverter;
|
||||
import cn.hutool.core.convert.impl.StringConverter;
|
||||
import cn.hutool.core.convert.impl.TemporalAccessorConverter;
|
||||
import cn.hutool.core.convert.impl.TimeZoneConverter;
|
||||
import cn.hutool.core.convert.impl.URIConverter;
|
||||
import cn.hutool.core.convert.impl.URLConverter;
|
||||
import cn.hutool.core.convert.impl.UUIDConverter;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Currency;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 转换器登记中心
|
||||
* <p>
|
||||
@ -371,6 +377,15 @@ public class ConverterRegistry implements Serializable{
|
||||
defaultConverterMap.put(java.sql.Time.class, new DateConverter(java.sql.Time.class));
|
||||
defaultConverterMap.put(java.sql.Timestamp.class, new DateConverter(java.sql.Timestamp.class));
|
||||
|
||||
// 日期时间 JDK8+(since 5.0.0)
|
||||
defaultConverterMap.put(Instant.class, new TemporalAccessorConverter(Instant.class));
|
||||
defaultConverterMap.put(LocalDateTime.class, new TemporalAccessorConverter(LocalDateTime.class));
|
||||
defaultConverterMap.put(LocalDate.class, new TemporalAccessorConverter(LocalDate.class));
|
||||
defaultConverterMap.put(LocalTime.class, new TemporalAccessorConverter(LocalTime.class));
|
||||
defaultConverterMap.put(ZonedDateTime.class, new TemporalAccessorConverter(ZonedDateTime.class));
|
||||
defaultConverterMap.put(OffsetDateTime.class, new TemporalAccessorConverter(OffsetDateTime.class));
|
||||
defaultConverterMap.put(OffsetTime.class, new TemporalAccessorConverter(OffsetTime.class));
|
||||
|
||||
// Reference
|
||||
defaultConverterMap.put(WeakReference.class, new ReferenceConverter(WeakReference.class));// since 3.0.8
|
||||
defaultConverterMap.put(SoftReference.class, new ReferenceConverter(SoftReference.class));// since 3.0.8
|
||||
@ -386,18 +401,6 @@ public class ConverterRegistry implements Serializable{
|
||||
defaultConverterMap.put(UUID.class, new UUIDConverter());// since 4.0.10
|
||||
defaultConverterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2
|
||||
|
||||
// JDK8+
|
||||
try {
|
||||
Class<?> clazz;
|
||||
for (String className : Jdk8DateConverter.supportClassNames) {
|
||||
clazz = ClassUtil.loadClass(className);
|
||||
defaultConverterMap.put(clazz, new Jdk8DateConverter(clazz));// since 4.5.1
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
// 在使用jdk8以下版本时,其转换器自动跳过失效
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
// ----------------------------------------------------------- Private method end
|
||||
|
@ -1,130 +0,0 @@
|
||||
package cn.hutool.core.convert.impl;
|
||||
|
||||
import cn.hutool.core.convert.AbstractConverter;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* JDK8中新加入的java.time包对象解析转换器<br>
|
||||
* 通过反射调用“parse方法”,支持的对象包括:
|
||||
*
|
||||
* <pre>
|
||||
* java.time.LocalDateTime
|
||||
* java.time.LocalDate
|
||||
* java.time.LocalTime
|
||||
* java.time.ZonedDateTime
|
||||
* java.time.OffsetDateTime
|
||||
* java.time.OffsetTime
|
||||
* java.time.Period
|
||||
* java.time.Instant
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public class Jdk8DateConverter extends AbstractConverter<Object> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 支持的JDK中的类名 */
|
||||
public static String[] supportClassNames = new String[] { //
|
||||
"java.time.LocalDateTime", //
|
||||
"java.time.LocalDate", //
|
||||
"java.time.LocalTime", //
|
||||
"java.time.ZonedDateTime", //
|
||||
"java.time.OffsetDateTime", //
|
||||
"java.time.OffsetTime", //
|
||||
"java.time.Period", //
|
||||
"java.time.Instant"//
|
||||
};
|
||||
|
||||
private Class<?> targetType;
|
||||
/** 日期格式化 */
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
*/
|
||||
public Jdk8DateConverter(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @param format 日期格式
|
||||
*/
|
||||
public Jdk8DateConverter(Class<?> targetType, String format) {
|
||||
this.targetType = targetType;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期格式
|
||||
*
|
||||
* @return 设置日期格式
|
||||
*/
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日期格式
|
||||
*
|
||||
* @param format 日期格式
|
||||
*/
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return parseFromLong((Long) value);
|
||||
} else {
|
||||
return parseFromCharSequence(convertToStr(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射从字符串转java.time中的对象
|
||||
*
|
||||
* @param value 字符串值
|
||||
* @return 日期对象
|
||||
*/
|
||||
private Object parseFromCharSequence(CharSequence value) {
|
||||
Method method;
|
||||
if (null != this.format) {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(this.format);
|
||||
method = ReflectUtil.getMethod(this.targetType, "parse", CharSequence.class, DateTimeFormatter.class);
|
||||
if(Instant.class.isAssignableFrom(this.targetType)){
|
||||
return formatter.parse(value, Instant::from);
|
||||
}
|
||||
return ReflectUtil.invokeStatic(method, value, formatter);
|
||||
} else {
|
||||
method = ReflectUtil.getMethod(this.targetType, "parse", CharSequence.class);
|
||||
return ReflectUtil.invokeStatic(method, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射将Long型时间戳转换为java.time中的对象
|
||||
*
|
||||
* @param time 时间戳
|
||||
* @return java.time中的对象
|
||||
*/
|
||||
private Object parseFromLong(Long time) {
|
||||
String targetName = this.targetType.getName();
|
||||
if ("java.time.Instant".equals(targetName)) {
|
||||
return Instant.ofEpochMilli(time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package cn.hutool.core.convert.impl;
|
||||
|
||||
import cn.hutool.core.convert.AbstractConverter;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* JDK8中新加入的java.time包对象解析转换器<br>
|
||||
* 支持的对象包括:
|
||||
*
|
||||
* <pre>
|
||||
* java.time.Instant
|
||||
* java.time.LocalDateTime
|
||||
* java.time.LocalDate
|
||||
* java.time.LocalTime
|
||||
* java.time.ZonedDateTime
|
||||
* java.time.OffsetDateTime
|
||||
* java.time.OffsetTime
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public class TemporalAccessorConverter extends AbstractConverter<TemporalAccessor> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Class<?> targetType;
|
||||
/**
|
||||
* 日期格式化
|
||||
*/
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
*/
|
||||
public TemporalAccessorConverter(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param targetType 目标类型
|
||||
* @param format 日期格式
|
||||
*/
|
||||
public TemporalAccessorConverter(Class<?> targetType, String format) {
|
||||
this.targetType = targetType;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期格式
|
||||
*
|
||||
* @return 设置日期格式
|
||||
*/
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置日期格式
|
||||
*
|
||||
* @param format 日期格式
|
||||
*/
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TemporalAccessor convertInternal(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return parseFromLong((Long) value);
|
||||
} else if (value instanceof TemporalAccessor) {
|
||||
return parseFromTemporalAccessor((TemporalAccessor) value);
|
||||
} else if (value instanceof Date) {
|
||||
return parseFromTemporalAccessor(((Date) value).toInstant());
|
||||
}else if (value instanceof Calendar) {
|
||||
return parseFromTemporalAccessor(((Calendar) value).toInstant());
|
||||
} else {
|
||||
return parseFromCharSequence(convertToStr(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射从字符串转java.time中的对象
|
||||
*
|
||||
* @param value 字符串值
|
||||
* @return 日期对象
|
||||
*/
|
||||
private TemporalAccessor parseFromCharSequence(CharSequence value) {
|
||||
final Instant instant;
|
||||
if (null != this.format) {
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(this.format);
|
||||
instant = formatter.parse(value, Instant::from);
|
||||
} else {
|
||||
instant = DateUtil.parse(value).toInstant();
|
||||
}
|
||||
return parseFromTemporalAccessor(instant);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Long型时间戳转换为java.time中的对象
|
||||
*
|
||||
* @param time 时间戳
|
||||
* @return java.time中的对象
|
||||
*/
|
||||
private TemporalAccessor parseFromLong(Long time) {
|
||||
return parseFromTemporalAccessor(Instant.ofEpochMilli(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将TemporalAccessor型时间戳转换为java.time中的对象
|
||||
*
|
||||
* @param temporalAccessor TemporalAccessor对象
|
||||
* @return java.time中的对象
|
||||
*/
|
||||
private TemporalAccessor parseFromTemporalAccessor(TemporalAccessor temporalAccessor) {
|
||||
return parseFromIntant(Instant.from(temporalAccessor));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将TemporalAccessor型时间戳转换为java.time中的对象
|
||||
*
|
||||
* @param instant TemporalAccessor对象
|
||||
* @return java.time中的对象
|
||||
*/
|
||||
private TemporalAccessor parseFromIntant(Instant instant) {
|
||||
if(Instant.class.equals(this.targetType)){
|
||||
return instant;
|
||||
}else if (LocalDateTime.class.equals(this.targetType)) {
|
||||
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
} else if (LocalDate.class.equals(this.targetType)) {
|
||||
return instant.atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
} else if (LocalTime.class.equals(this.targetType)) {
|
||||
return instant.atZone(ZoneId.systemDefault()).toLocalTime();
|
||||
} else if (ZonedDateTime.class.equals(this.targetType)) {
|
||||
return instant.atZone(ZoneId.systemDefault());
|
||||
} else if (OffsetDateTime.class.equals(this.targetType)) {
|
||||
return OffsetDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
} else if (OffsetTime.class.equals(this.targetType)) {
|
||||
return OffsetTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -3,6 +3,9 @@ package cn.hutool.core.date;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
@ -143,6 +146,26 @@ public class DateTime extends Date {
|
||||
this.setFirstDayOfWeek(Week.of(calendar.getFirstDayOfWeek()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定日期Instant的构造
|
||||
*
|
||||
* @param instant {@link Instant} 对象
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public DateTime(Instant instant) {
|
||||
this(instant.toEpochMilli());
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定日期TemporalAccessor的构造
|
||||
*
|
||||
* @param temporalAccessor {@link TemporalAccessor} 对象
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public DateTime(TemporalAccessor temporalAccessor) {
|
||||
this(Instant.from(temporalAccessor));
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定日期毫秒数的构造
|
||||
*
|
||||
@ -174,7 +197,7 @@ public class DateTime extends Date {
|
||||
* @param format 格式
|
||||
* @see DatePattern
|
||||
*/
|
||||
public DateTime(String dateStr, String format) {
|
||||
public DateTime(CharSequence dateStr, String format) {
|
||||
this(dateStr, new SimpleDateFormat(format));
|
||||
}
|
||||
|
||||
@ -185,10 +208,22 @@ public class DateTime extends Date {
|
||||
* @param dateFormat 格式化器 {@link SimpleDateFormat}
|
||||
* @see DatePattern
|
||||
*/
|
||||
public DateTime(String dateStr, DateFormat dateFormat) {
|
||||
public DateTime(CharSequence dateStr, DateFormat dateFormat) {
|
||||
this(parse(dateStr, dateFormat), dateFormat.getTimeZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建DateTime对象
|
||||
*
|
||||
* @param dateStr Date字符串
|
||||
* @param formatter 格式化器,{@link DateTimeFormatter}
|
||||
* @return DateTime对象
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public DateTime(CharSequence dateStr, DateTimeFormatter formatter) {
|
||||
this(Instant.from(formatter.parse(dateStr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
@ -196,7 +231,7 @@ public class DateTime extends Date {
|
||||
* @param dateParser 格式化器 {@link DateParser},可以使用 {@link FastDateFormat}
|
||||
* @see DatePattern
|
||||
*/
|
||||
public DateTime(String dateStr, DateParser dateParser) {
|
||||
public DateTime(CharSequence dateStr, DateParser dateParser) {
|
||||
this(parse(dateStr, dateParser), dateParser.getTimeZone());
|
||||
}
|
||||
|
||||
@ -869,9 +904,10 @@ public class DateTime extends Date {
|
||||
* @param dateFormat {@link SimpleDateFormat}
|
||||
* @return {@link Date}
|
||||
*/
|
||||
private static Date parse(String dateStr, DateFormat dateFormat) {
|
||||
private static Date parse(CharSequence dateStr, DateFormat dateFormat) {
|
||||
Assert.notBlank(dateStr, "Date String must be not blank !");
|
||||
try {
|
||||
return dateFormat.parse(dateStr);
|
||||
return dateFormat.parse(dateStr.toString());
|
||||
} catch (Exception e) {
|
||||
String pattern;
|
||||
if (dateFormat instanceof SimpleDateFormat) {
|
||||
@ -890,11 +926,11 @@ public class DateTime extends Date {
|
||||
* @param parser {@link FastDateFormat}
|
||||
* @return {@link Date}
|
||||
*/
|
||||
private static Date parse(String dateStr, DateParser parser) {
|
||||
private static Date parse(CharSequence dateStr, DateParser parser) {
|
||||
Assert.notNull(parser, "Parser or DateFromat must be not null !");
|
||||
Assert.notBlank(dateStr, "Date String must be not blank !");
|
||||
try {
|
||||
return parser.parse(dateStr);
|
||||
return parser.parse(dateStr.toString());
|
||||
} catch (Exception e) {
|
||||
throw new DateException("Parse [{}] with format [{}] error!", dateStr, parser.getPattern(), e);
|
||||
}
|
||||
|
@ -1,15 +1,5 @@
|
||||
package cn.hutool.core.date;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@ -18,10 +8,22 @@ 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.lang.PatternPool;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 时间工具类
|
||||
*
|
||||
@ -105,6 +107,18 @@ public class DateUtil {
|
||||
return new DateTime(calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TemporalAccessor}类型时间转为{@link DateTime}<br>
|
||||
* 始终根据已有{@link TemporalAccessor} 产生新的{@link DateTime}对象
|
||||
*
|
||||
* @param temporalAccessor {@link TemporalAccessor}
|
||||
* @return 时间对象
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static DateTime date(TemporalAccessor temporalAccessor) {
|
||||
return new DateTime(temporalAccessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Calendar对象,时间为默认时区的当前时间
|
||||
*
|
||||
@ -628,7 +642,7 @@ public class DateUtil {
|
||||
* @param dateFormat 格式化器 {@link SimpleDateFormat}
|
||||
* @return DateTime对象
|
||||
*/
|
||||
public static DateTime parse(String dateStr, DateFormat dateFormat) {
|
||||
public static DateTime parse(CharSequence dateStr, DateFormat dateFormat) {
|
||||
return new DateTime(dateStr, dateFormat);
|
||||
}
|
||||
|
||||
@ -639,10 +653,22 @@ public class DateUtil {
|
||||
* @param parser 格式化器,{@link FastDateFormat}
|
||||
* @return DateTime对象
|
||||
*/
|
||||
public static DateTime parse(String dateStr, DateParser parser) {
|
||||
public static DateTime parse(CharSequence dateStr, DateParser parser) {
|
||||
return new DateTime(dateStr, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建DateTime对象
|
||||
*
|
||||
* @param dateStr Date字符串
|
||||
* @param formatter 格式化器,{@link DateTimeFormatter}
|
||||
* @return DateTime对象
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static DateTime parse(CharSequence dateStr, DateTimeFormatter formatter) {
|
||||
return new DateTime(dateStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将特定格式的日期转换为Date对象
|
||||
*
|
||||
@ -650,7 +676,7 @@ public class DateUtil {
|
||||
* @param format 格式,例如yyyy-MM-dd
|
||||
* @return 日期对象
|
||||
*/
|
||||
public static DateTime parse(String dateStr, String format) {
|
||||
public static DateTime parse(CharSequence dateStr, String format) {
|
||||
return new DateTime(dateStr, format);
|
||||
}
|
||||
|
||||
@ -663,7 +689,7 @@ public class DateUtil {
|
||||
* @return 日期对象
|
||||
* @since 4.5.18
|
||||
*/
|
||||
public static DateTime parse(String dateStr, String format, Locale locale) {
|
||||
public static DateTime parse(CharSequence dateStr, String format, Locale locale) {
|
||||
return new DateTime(dateStr, new SimpleDateFormat(format, locale));
|
||||
}
|
||||
|
||||
@ -673,7 +699,7 @@ public class DateUtil {
|
||||
* @param dateString 标准形式的时间字符串
|
||||
* @return 日期对象
|
||||
*/
|
||||
public static DateTime parseDateTime(String dateString) {
|
||||
public static DateTime parseDateTime(CharSequence dateString) {
|
||||
dateString = normalize(dateString);
|
||||
return parse(dateString, DatePattern.NORM_DATETIME_FORMAT);
|
||||
}
|
||||
@ -684,7 +710,7 @@ public class DateUtil {
|
||||
* @param dateString 标准形式的日期字符串
|
||||
* @return 日期对象
|
||||
*/
|
||||
public static DateTime parseDate(String dateString) {
|
||||
public static DateTime parseDate(CharSequence dateString) {
|
||||
dateString = normalize(dateString);
|
||||
return parse(dateString, DatePattern.NORM_DATE_FORMAT);
|
||||
}
|
||||
@ -695,7 +721,7 @@ public class DateUtil {
|
||||
* @param timeString 标准形式的日期字符串
|
||||
* @return 日期对象
|
||||
*/
|
||||
public static DateTime parseTime(String timeString) {
|
||||
public static DateTime parseTime(CharSequence timeString) {
|
||||
timeString = normalize(timeString);
|
||||
return parse(timeString, DatePattern.NORM_TIME_FORMAT);
|
||||
}
|
||||
@ -707,7 +733,7 @@ public class DateUtil {
|
||||
* @return 日期对象
|
||||
* @since 3.1.1
|
||||
*/
|
||||
public static DateTime parseTimeToday(String timeString) {
|
||||
public static DateTime parseTimeToday(CharSequence timeString) {
|
||||
timeString = StrUtil.format("{} {}", today(), timeString);
|
||||
if (1 == StrUtil.count(timeString, ':')) {
|
||||
// 时间格式为 HH:mm
|
||||
@ -767,7 +793,7 @@ public class DateUtil {
|
||||
* @return 日期对象
|
||||
* @since 4.6.9
|
||||
*/
|
||||
public static DateTime parseCST(String cstString) {
|
||||
public static DateTime parseCST(CharSequence cstString) {
|
||||
if (cstString == null) {
|
||||
return null;
|
||||
}
|
||||
@ -800,18 +826,19 @@ public class DateUtil {
|
||||
* <li>yyyy-MM-dd'T'HH:mm:ss.SSSZ</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param dateStr 日期字符串
|
||||
* @param dateCharSequence 日期字符串
|
||||
* @return 日期
|
||||
*/
|
||||
public static DateTime parse(String dateStr) {
|
||||
if (null == dateStr) {
|
||||
public static DateTime parse(CharSequence dateCharSequence) {
|
||||
if (StrUtil.isBlank(dateCharSequence)) {
|
||||
return null;
|
||||
}
|
||||
String dateStr = dateCharSequence.toString();
|
||||
// 去掉两边空格并去掉中文日期中的“日”和“秒”,以规范长度
|
||||
dateStr = StrUtil.removeAll(dateStr.trim(), '日', '秒');
|
||||
int length = dateStr.length();
|
||||
|
||||
if (Validator.isNumber(dateStr)) {
|
||||
if (NumberUtil.isNumber(dateStr)) {
|
||||
// 纯数字形式
|
||||
if (length == DatePattern.PURE_DATETIME_PATTERN.length()) {
|
||||
return parse(dateStr, DatePattern.PURE_DATETIME_FORMAT);
|
||||
@ -1938,13 +1965,13 @@ public class DateUtil {
|
||||
* </pre>
|
||||
*
|
||||
* 当末位是":"时去除之(不存在毫秒时)
|
||||
*
|
||||
*
|
||||
* @param dateStr 日期时间字符串
|
||||
* @return 格式化后的日期字符串
|
||||
*/
|
||||
private static String normalize(String dateStr) {
|
||||
private static String normalize(CharSequence dateStr) {
|
||||
if (StrUtil.isBlank(dateStr)) {
|
||||
return dateStr;
|
||||
return StrUtil.str(dateStr);
|
||||
}
|
||||
|
||||
// 日期时间分开处理
|
||||
@ -1952,7 +1979,7 @@ public class DateUtil {
|
||||
final int size = dateAndTime.size();
|
||||
if (size < 1 || size > 2) {
|
||||
// 非可被标准处理的格式
|
||||
return dateStr;
|
||||
return StrUtil.str(dateStr);
|
||||
}
|
||||
|
||||
final StringBuilder builder = StrUtil.builder();
|
||||
|
@ -157,7 +157,8 @@ public class Assert {
|
||||
* <pre class="code">
|
||||
* Assert.notEmpty(name, "Name must not be empty");
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param <T> 字符串类型
|
||||
* @param text 被检查字符串
|
||||
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
||||
* @param params 参数
|
||||
@ -165,7 +166,7 @@ public class Assert {
|
||||
* @see StrUtil#isNotEmpty(CharSequence)
|
||||
* @throws IllegalArgumentException 被检查字符串为空
|
||||
*/
|
||||
public static String notEmpty(String text, String errorMsgTemplate, Object... params) throws IllegalArgumentException {
|
||||
public static <T extends CharSequence> T notEmpty(T text, String errorMsgTemplate, Object... params) throws IllegalArgumentException {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
throw new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params));
|
||||
}
|
||||
@ -178,13 +179,14 @@ public class Assert {
|
||||
* <pre class="code">
|
||||
* Assert.notEmpty(name);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param <T> 字符串类型
|
||||
* @param text 被检查字符串
|
||||
* @return 被检查的字符串
|
||||
* @see StrUtil#isNotEmpty(CharSequence)
|
||||
* @throws IllegalArgumentException 被检查字符串为空
|
||||
*/
|
||||
public static String notEmpty(String text) throws IllegalArgumentException {
|
||||
public static <T extends CharSequence> T notEmpty(T text) throws IllegalArgumentException {
|
||||
return notEmpty(text, "[Assertion failed] - this String argument must have length; it must not be null or empty");
|
||||
}
|
||||
|
||||
@ -194,7 +196,8 @@ public class Assert {
|
||||
* <pre class="code">
|
||||
* Assert.notBlank(name, "Name must not be blank");
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param <T> 字符串类型
|
||||
* @param text 被检查字符串
|
||||
* @param errorMsgTemplate 错误消息模板,变量使用{}表示
|
||||
* @param params 参数
|
||||
@ -202,7 +205,7 @@ public class Assert {
|
||||
* @see StrUtil#isNotBlank(CharSequence)
|
||||
* @throws IllegalArgumentException 被检查字符串为空白
|
||||
*/
|
||||
public static String notBlank(String text, String errorMsgTemplate, Object... params) throws IllegalArgumentException {
|
||||
public static <T extends CharSequence> T notBlank(T text, String errorMsgTemplate, Object... params) throws IllegalArgumentException {
|
||||
if (StrUtil.isBlank(text)) {
|
||||
throw new IllegalArgumentException(StrUtil.format(errorMsgTemplate, params));
|
||||
}
|
||||
@ -215,13 +218,14 @@ public class Assert {
|
||||
* <pre class="code">
|
||||
* Assert.notBlank(name, "Name must not be blank");
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param <T> 字符串类型
|
||||
* @param text 被检查字符串
|
||||
* @return 非空字符串
|
||||
* @see StrUtil#isNotBlank(CharSequence)
|
||||
* @throws IllegalArgumentException 被检查字符串为空白
|
||||
*/
|
||||
public static String notBlank(String text) throws IllegalArgumentException {
|
||||
public static <T extends CharSequence> T notBlank(T text) throws IllegalArgumentException {
|
||||
return notBlank(text, "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ public class Validator {
|
||||
* @param value 字符串内容
|
||||
* @return 是否是数字
|
||||
*/
|
||||
public static boolean isNumber(String value) {
|
||||
public static boolean isNumber(CharSequence value) {
|
||||
return NumberUtil.isNumber(value);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
@ -11,10 +14,6 @@ import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Console;
|
||||
|
||||
/**
|
||||
* 数字工具类<br>
|
||||
* 对于精确值计算应该使用 {@link BigDecimal}<br>
|
||||
@ -1057,11 +1056,11 @@ public class NumberUtil {
|
||||
* @param str 字符串值
|
||||
* @return 是否为数字
|
||||
*/
|
||||
public static boolean isNumber(String str) {
|
||||
public static boolean isNumber(CharSequence str) {
|
||||
if (StrUtil.isBlank(str)) {
|
||||
return false;
|
||||
}
|
||||
char[] chars = str.toCharArray();
|
||||
char[] chars = str.toString().toCharArray();
|
||||
int sz = chars.length;
|
||||
boolean hasExp = false;
|
||||
boolean hasDecPoint = false;
|
||||
|
@ -0,0 +1,57 @@
|
||||
package cn.hutool.core.convert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public class TemporalAccessorConverterTest {
|
||||
|
||||
@Test
|
||||
public void toInstantTest(){
|
||||
Instant instant = Convert.convert(Instant.class, "2019-02-18");
|
||||
Assert.assertNotNull(instant);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toLocalDateTimeTest(){
|
||||
LocalDateTime localDateTime = Convert.convert(LocalDateTime.class, "2019-02-18");
|
||||
Assert.assertEquals("2019-02-18T00:00", localDateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toLocalDateTest(){
|
||||
LocalDate localDate = Convert.convert(LocalDate.class, "2019-02-18");
|
||||
Assert.assertEquals("2019-02-18", localDate.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toLocalTimeTest(){
|
||||
LocalTime localTime = Convert.convert(LocalTime.class, "2019-02-18");
|
||||
Assert.assertEquals("00:00", localTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toZonedDateTimeTest(){
|
||||
ZonedDateTime zonedDateTime = Convert.convert(ZonedDateTime.class, "2019-02-18");
|
||||
Assert.assertEquals("2019-02-18T00:00+08:00[GMT+08:00]", zonedDateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toOffsetDateTimeTest(){
|
||||
OffsetDateTime zonedDateTime = Convert.convert(OffsetDateTime.class, "2019-02-18");
|
||||
Assert.assertEquals("2019-02-18T00:00+08:00", zonedDateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toOffsetTimeTest(){
|
||||
OffsetTime offsetTime = Convert.convert(OffsetTime.class, "2019-02-18");
|
||||
Assert.assertEquals("00:00+08:00", offsetTime.toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user