修复bug
This commit is contained in:
1 parent
2c10db5b24
commit
e046c67f64
1 file changed
+55
-2
+55
-2
@@ -1,27 +1,80 @@
|
||||
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 基于时间戳的 LocalDateTime 反序列化器
|
||||
*
|
||||
* 支持两种 JSON 写法:
|
||||
* 1. 时间戳:13 位毫秒(yudao 前端默认),兼容 10 位秒级时间戳
|
||||
* 2. 日期字符串:"yyyy-MM-dd HH:mm:ss"、"yyyy-MM-dd"、ISO-8601("yyyy-MM-dd'T'HH:mm:ss")
|
||||
*
|
||||
* 注意:原实现直接 {@code p.getValueAsLong()},传入 "yyyy-MM-dd HH:mm:ss" 字符串时
|
||||
* 会静默解析失败并返回 0,导致入库时间变成 1970-01-01 08:00:00(东八区 epoch 0)。
|
||||
*
|
||||
* @author 老五
|
||||
*/
|
||||
public class TimestampLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
|
||||
|
||||
public static final TimestampLocalDateTimeDeserializer INSTANCE = new TimestampLocalDateTimeDeserializer();
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
@Override
|
||||
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
// 将 Long 时间戳,转换为 LocalDateTime 对象
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
|
||||
// 1. 数字:直接按毫秒时间戳处理(与原行为一致)
|
||||
if (p.getCurrentToken() == JsonToken.VALUE_NUMBER_INT) {
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getLongValue()), ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
// 2. 字符串:先尝试时间戳,再尝试常见日期格式
|
||||
String text = p.getValueAsString();
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
text = text.trim();
|
||||
if (text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// 2.1 纯数字:13 位毫秒、10 位秒
|
||||
if (text.matches("\\d+")) {
|
||||
long timestamp = Long.parseLong(text);
|
||||
if (text.length() <= 10) { // 秒级时间戳,转毫秒
|
||||
timestamp *= 1000;
|
||||
}
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
|
||||
}
|
||||
// 2.2 "yyyy-MM-dd HH:mm:ss"
|
||||
try {
|
||||
return LocalDateTime.parse(text, DATE_TIME_FORMATTER);
|
||||
} catch (Exception ignore) {
|
||||
// 继续尝试其它格式
|
||||
}
|
||||
// 2.3 "yyyy-MM-dd"(按当天 00:00:00)
|
||||
try {
|
||||
return LocalDate.parse(text, DATE_FORMATTER).atStartOfDay();
|
||||
} catch (Exception ignore) {
|
||||
// 继续尝试 ISO 格式
|
||||
}
|
||||
// 2.4 ISO-8601:"yyyy-MM-dd'T'HH:mm:ss"
|
||||
try {
|
||||
return LocalDateTime.parse(text);
|
||||
} catch (Exception ignore) {
|
||||
// 落到最后的报错
|
||||
}
|
||||
throw ctxt.weirdStringException(text, LocalDateTime.class,
|
||||
"Expected timestamp (millis or seconds) or date string (yyyy-MM-dd HH:mm:ss)");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user