This commit is contained in:
Looly
2024-04-20 16:39:14 +08:00
parent 4240bc6523
commit 2fbb2b641a
3 changed files with 115 additions and 45 deletions

View File

@@ -15,21 +15,12 @@ package org.dromara.hutool.core.convert.impl;
import org.dromara.hutool.core.convert.AbstractConverter; import org.dromara.hutool.core.convert.AbstractConverter;
import org.dromara.hutool.core.date.DateTime; import org.dromara.hutool.core.date.DateTime;
import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.dromara.hutool.core.date.format.GlobalCustomFormat; import org.dromara.hutool.core.date.format.GlobalCustomFormat;
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 java.time.DayOfWeek; import java.time.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.MonthDay;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.chrono.Era; import java.time.chrono.Era;
import java.time.chrono.IsoEra; import java.time.chrono.IsoEra;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@@ -103,7 +94,7 @@ public class TemporalAccessorConverter extends AbstractConverter {
protected TemporalAccessor convertInternal(final Class<?> targetClass, final Object value) { protected TemporalAccessor convertInternal(final Class<?> targetClass, final Object value) {
if (value instanceof Long) { if (value instanceof Long) {
return parseFromLong(targetClass, (Long) value); return parseFromLong(targetClass, (Long) value);
}else if (value instanceof Integer) { } else if (value instanceof Integer) {
return parseFromLong(targetClass, ((Integer) value).longValue()); return parseFromLong(targetClass, ((Integer) value).longValue());
} else if (value instanceof TemporalAccessor) { } else if (value instanceof TemporalAccessor) {
return parseFromTemporalAccessor(targetClass, (TemporalAccessor) value); return parseFromTemporalAccessor(targetClass, (TemporalAccessor) value);
@@ -129,20 +120,27 @@ public class TemporalAccessorConverter extends AbstractConverter {
return null; return null;
} }
if(DayOfWeek.class == targetClass){ if (DayOfWeek.class == targetClass) {
return DayOfWeek.valueOf(StrUtil.toString(value)); return DayOfWeek.valueOf(StrUtil.toString(value));
} else if(Month.class == targetClass){ } else if (Month.class == targetClass) {
return Month.valueOf(StrUtil.toString(value)); return Month.valueOf(StrUtil.toString(value));
} else if(Era.class == targetClass){ } else if (Era.class == targetClass) {
return IsoEra.valueOf(StrUtil.toString(value)); return IsoEra.valueOf(StrUtil.toString(value));
} else if(MonthDay.class == targetClass){ } else if (MonthDay.class == targetClass) {
return MonthDay.parse(value); return MonthDay.parse(value);
} }
final Instant instant; final Instant instant;
final ZoneId zoneId; final ZoneId zoneId;
if (null != this.format) { if (null != this.format) {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(this.format); final DateTimeFormatter formatter = TimeUtil.ofPattern(this.format);
// issue#I9HQQE
final TemporalAccessor temporalAccessor = parseWithFormat(targetClass, value, formatter);
if(null != temporalAccessor){
return temporalAccessor;
}
instant = formatter.parse(value, Instant::from); instant = formatter.parse(value, Instant::from);
zoneId = formatter.getZone(); zoneId = formatter.getZone();
} else { } else {
@@ -153,6 +151,26 @@ public class TemporalAccessorConverter extends AbstractConverter {
return parseFromInstant(targetClass, instant, zoneId); return parseFromInstant(targetClass, instant, zoneId);
} }
/**
* 对于自定义格式的字符串,单独解析为{@link TemporalAccessor}
*
* @param targetClass 目标类型
* @param value 日期字符串
* @param formatter 格式
* @return {@link TemporalAccessor}
*/
private TemporalAccessor parseWithFormat(final Class<?> targetClass, final CharSequence value, final DateTimeFormatter formatter) {
// issue#I9HQQE
if (LocalDate.class == targetClass) {
return LocalDate.parse(value, formatter);
} else if (LocalDateTime.class == targetClass) {
return LocalDateTime.parse(value, formatter);
} else if (LocalTime.class == targetClass) {
return LocalTime.parse(value, formatter);
}
return null;
}
/** /**
* 将Long型时间戳转换为java.time中的对象 * 将Long型时间戳转换为java.time中的对象
* *
@@ -161,20 +179,20 @@ public class TemporalAccessorConverter extends AbstractConverter {
* @return java.time中的对象 * @return java.time中的对象
*/ */
private TemporalAccessor parseFromLong(final Class<?> targetClass, final Long time) { private TemporalAccessor parseFromLong(final Class<?> targetClass, final Long time) {
if(targetClass == Month.class){ if (targetClass == Month.class) {
return Month.of(Math.toIntExact(time)); return Month.of(Math.toIntExact(time));
} else if(targetClass == DayOfWeek.class){ } else if (targetClass == DayOfWeek.class) {
return DayOfWeek.of(Math.toIntExact(time)); return DayOfWeek.of(Math.toIntExact(time));
} else if(Era.class == targetClass){ } else if (Era.class == targetClass) {
return IsoEra.of(Math.toIntExact(time)); return IsoEra.of(Math.toIntExact(time));
} }
final Instant instant; final Instant instant;
if(GlobalCustomFormat.FORMAT_SECONDS.equals(this.format)){ if (GlobalCustomFormat.FORMAT_SECONDS.equals(this.format)) {
// https://gitee.com/dromara/hutool/issues/I6IS5B // https://gitee.com/dromara/hutool/issues/I6IS5B
// Unix时间戳 // Unix时间戳
instant = Instant.ofEpochSecond(time); instant = Instant.ofEpochSecond(time);
}else{ } else {
instant = Instant.ofEpochMilli(time); instant = Instant.ofEpochMilli(time);
} }
return parseFromInstant(targetClass, instant, null); return parseFromInstant(targetClass, instant, null);
@@ -187,11 +205,11 @@ public class TemporalAccessorConverter extends AbstractConverter {
* @return java.time中的对象 * @return java.time中的对象
*/ */
private TemporalAccessor parseFromTemporalAccessor(final Class<?> targetClass, final TemporalAccessor temporalAccessor) { private TemporalAccessor parseFromTemporalAccessor(final Class<?> targetClass, final TemporalAccessor temporalAccessor) {
if(DayOfWeek.class == targetClass){ if (DayOfWeek.class == targetClass) {
return DayOfWeek.from(temporalAccessor); return DayOfWeek.from(temporalAccessor);
} else if(Month.class == targetClass){ } else if (Month.class == targetClass) {
return Month.from(temporalAccessor); return Month.from(temporalAccessor);
} else if(MonthDay.class == targetClass){ } else if (MonthDay.class == targetClass) {
return MonthDay.from(temporalAccessor); return MonthDay.from(temporalAccessor);
} }

View File

@@ -21,6 +21,7 @@ import java.time.*;
import java.time.chrono.ChronoLocalDate; import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoLocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.*; import java.time.temporal.*;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
@@ -167,26 +168,26 @@ public class TimeUtil extends TemporalAccessorUtil {
if (temporalAccessor instanceof LocalDate) { if (temporalAccessor instanceof LocalDate) {
return ((LocalDate) temporalAccessor).atStartOfDay(); return ((LocalDate) temporalAccessor).atStartOfDay();
} else if(temporalAccessor instanceof Instant){ } else if (temporalAccessor instanceof Instant) {
return LocalDateTime.ofInstant((Instant) temporalAccessor, ZoneId.systemDefault()); return LocalDateTime.ofInstant((Instant) temporalAccessor, ZoneId.systemDefault());
} }
// issue#3301 // issue#3301
try{ try {
return LocalDateTime.from(temporalAccessor); return LocalDateTime.from(temporalAccessor);
} catch (final Exception ignore){ } catch (final Exception ignore) {
//ignore //ignore
} }
try{ try {
return ZonedDateTime.from(temporalAccessor).toLocalDateTime(); return ZonedDateTime.from(temporalAccessor).toLocalDateTime();
} catch (final Exception ignore){ } catch (final Exception ignore) {
//ignore //ignore
} }
try{ try {
return LocalDateTime.ofInstant(Instant.from(temporalAccessor), ZoneId.systemDefault()); return LocalDateTime.ofInstant(Instant.from(temporalAccessor), ZoneId.systemDefault());
} catch (final Exception ignore){ } catch (final Exception ignore) {
//ignore //ignore
} }
@@ -605,4 +606,22 @@ public class TimeUtil extends TemporalAccessorUtil {
public static boolean isSameDay(final ChronoLocalDate date1, final ChronoLocalDate date2) { public static boolean isSameDay(final ChronoLocalDate date1, final ChronoLocalDate date2) {
return date1 != null && date2 != null && date1.isEqual(date2); return date1 != null && date2 != null && date1.isEqual(date2);
} }
/**
* 通过日期时间字符串构建{@link DateTimeFormatter}
*
* @param pattern 格式如yyyy-MM-dd
* @return {@link DateTimeFormatter}
* @since 6.0.0
*/
public static DateTimeFormatter ofPattern(final String pattern) {
return new DateTimeFormatterBuilder()
.appendPattern(pattern)
//
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
.toFormatter();
}
} }

View File

@@ -0,0 +1,33 @@
package org.dromara.hutool.json;
import lombok.Data;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class IssueI9HQQETest {
@Test
public void toBeanTest(){
final String json = "{\"currentDate\":\"18/04/2024\", \"currentDateTime\":\"18/04/2024\"}";
final JSONConfig jsonConfig = new JSONConfig();
jsonConfig.setDateFormat("dd/MM/yyyy");
final JSONObject entries = JSONUtil.parseObj(json, jsonConfig);
final MMHBo mmh = entries.toBean(MMHBo.class);
Assertions.assertNotNull(mmh.getCurrentDate());
Assertions.assertNotNull(mmh.getCurrentDateTime());
}
@Data
public static class MMHBo {
/**
* 当前时间
*/
private LocalDate currentDate;
private LocalDateTime currentDateTime;
}
}