package com.vincent.rsf.server.api.controller.erp.params;
|
|
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.text.SimpleDateFormat;
|
import java.util.Date;
|
import java.util.TimeZone;
|
|
/**
|
* 支持时间戳(秒/毫秒)与多种字符串格式的 Date 反序列化。
|
* 字符串支持:ISO-8601(如 2024-03-03T08:00:00.000+00:00)、yyyy-MM-dd HH:mm:ss,精确到秒。
|
*/
|
public class FlexibleDateDeserializer extends JsonDeserializer<Date> {
|
|
private static final long TIMESTAMP_MS_THRESHOLD = 10_000_000_000L; // 约 1970-04-26 起为毫秒
|
|
private static final String PATTERN_SECONDS = "yyyy-MM-dd HH:mm:ss";
|
private static final TimeZone DEFAULT_TZ = TimeZone.getTimeZone("GMT+8");
|
|
@Override
|
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
JsonToken t = p.getCurrentToken();
|
if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
|
long v = p.getLongValue();
|
long ms = v < TIMESTAMP_MS_THRESHOLD ? v * 1000 : v;
|
return new Date(ms);
|
}
|
if (t == JsonToken.VALUE_STRING) {
|
String s = p.getText().trim();
|
if (s.isEmpty()) {
|
return null;
|
}
|
// 1) 尝试纯数字字符串(秒或毫秒)
|
try {
|
long v = Long.parseLong(s);
|
long ms = v < TIMESTAMP_MS_THRESHOLD ? v * 1000 : v;
|
return new Date(ms);
|
} catch (NumberFormatException ignored) {
|
}
|
// 2) ISO-8601(含 T 和时区)
|
if (s.contains("T")) {
|
try {
|
return java.util.Date.from(java.time.Instant.parse(s));
|
} catch (Exception ignored) {
|
}
|
}
|
// 3) yyyy-MM-dd HH:mm:ss
|
try {
|
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_SECONDS);
|
sdf.setTimeZone(DEFAULT_TZ);
|
sdf.setLenient(false);
|
return sdf.parse(s);
|
} catch (Exception ignored) {
|
}
|
// 4) 仅日期 yyyy-MM-dd
|
if (s.length() == 10 && s.charAt(4) == '-' && s.charAt(7) == '-') {
|
try {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
sdf.setTimeZone(DEFAULT_TZ);
|
sdf.setLenient(false);
|
return sdf.parse(s);
|
} catch (Exception ignored) {
|
}
|
}
|
throw new IOException("Cannot parse date: " + s + ", support: timestamp(seconds/ms), ISO-8601, yyyy-MM-dd HH:mm:ss");
|
}
|
if (t == JsonToken.VALUE_NULL) {
|
return null;
|
}
|
return (Date) ctxt.handleUnexpectedToken(Date.class, p);
|
}
|
}
|