package com.vincent.rsf.openApi.entity.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; /** * 将 JSON 反序列化为 Unix 时间戳(秒,Long)。 * 支持:数字(秒或毫秒)、字符串 "yyyy-MM-dd HH:mm:ss" 或 "yyyy-MM-dd"。 */ public class FlexibleTimestampDeserializer extends JsonDeserializer { private static final long MS_THRESHOLD = 10_000_000_000L; // 大于此为毫秒 private static final TimeZone DEFAULT_TZ = TimeZone.getTimeZone("GMT+8"); @Override public Long 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(); return v >= MS_THRESHOLD ? v / 1000 : v; } if (t == JsonToken.VALUE_STRING) { String s = p.getText().trim(); if (s.isEmpty()) { return null; } try { long v = Long.parseLong(s); return v >= MS_THRESHOLD ? v / 1000 : v; } catch (NumberFormatException ignored) { } try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(DEFAULT_TZ); sdf.setLenient(false); Date d = sdf.parse(s); return d != null ? d.getTime() / 1000 : null; } catch (Exception ignored) { } 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); Date d = sdf.parse(s.substring(0, 10)); return d != null ? d.getTime() / 1000 : null; } catch (Exception ignored) { } } return null; } if (t == JsonToken.VALUE_NULL) { return null; } return (Long) ctxt.handleUnexpectedToken(Long.class, p); } }