Browse Source

add TemporalAccessorConverter

Looly 6 years ago
parent
commit
cb7912717e

+ 1 - 0
CHANGELOG.md

@@ -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)

+ 40 - 37
hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java

@@ -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

+ 0 - 130
hutool-core/src/main/java/cn/hutool/core/convert/impl/Jdk8DateConverter.java

@@ -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;
-	}
-}

+ 160 - 0
hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java

@@ -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;
+	}
+}

+ 43 - 7
hutool-core/src/main/java/cn/hutool/core/date/DateTime.java

@@ -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;
@@ -144,6 +147,26 @@ public class DateTime extends Date {
 	}
 
 	/**
+	 * 给定日期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));
+	}
+
+	/**
 	 * 给定日期毫秒数的构造
 	 *
 	 * @param timeMillis 日期毫秒数
@@ -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,18 +208,30 @@ 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)));
+	}
+
+	/**
 	 * 构造
 	 *
 	 * @param dateStr    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);
 		}

+ 55 - 28
hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java

@@ -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;
+
 /**
  * 时间工具类
  * 
@@ -106,6 +108,18 @@ public class DateUtil {
 	}
 
 	/**
+	 * {@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对象,时间为默认时区的当前时间
 	 * 
 	 * @return 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,18 +653,30 @@ 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对象
 	 * 
 	 * @param dateStr 特定格式的日期
 	 * @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();

+ 12 - 8
hutool-core/src/main/java/cn/hutool/core/lang/Assert.java

@@ -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");
 	}
 

+ 1 - 1
hutool-core/src/main/java/cn/hutool/core/lang/Validator.java

@@ -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);
 	}
 

+ 5 - 6
hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java

@@ -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;

+ 57 - 0
hutool-core/src/test/java/cn/hutool/core/convert/TemporalAccessorConverterTest.java

@@ -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());
+	}
+}