尝试了所有可能的组合,创建了自定义JsonDeserializer
类,并根据需要修改了DateFormat
。但仍然没有多少成果。
但结果总是在“EST'”中显示日期。 1月1日星期六14:08:56 EST 2000。 我希望我的日期以UTC显示,或者根据客户需要更加可配置。
public class CustomJsonDeserializerWithDateFormat extends JsonDeserializer<Date>{
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
TimeZone TZ = TimeZone.getTimeZone("US/Central");
dateFormat.setTimeZone(TZ);
dateFormat.getCalendar().setTimeZone(TZ);
Calendar newCalendar = new GregorianCalendar();
newCalendar.setTimeZone(TZ);
dateFormat.setCalendar(newCalendar);
//ZonedDateTime
System.out.println("Time Zone : "+dateFormat.getTimeZone());
JsonToken t = p.getCurrentToken();
if (t == JsonToken.VALUE_STRING) {
String value = p.getText().trim();
try {
Date formattedDate = dateFormat.parse(value);
DateFormat formatter = new SimpleDateFormat
("EEE MMM dd HH:mm:ss zzz yyyy");
TimeZone central = TimeZone.getTimeZone("America/Chicago");
formatter.setTimeZone(central);
Date fromDate = (Date)formatter.parse(formattedDate.toString());
System.out.println(fromDate);
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" , Locale.ENGLISH );
ZonedDateTime zdt = ZonedDateTime.parse ( formattedDate.toString() , f );
System.out.println(zdt.toString());
ZoneId z = ZoneId.of( "America/Chicago" );
ZonedDateTime zdtChicago = zdt.withZoneSameInstant( z );
System.out.println(zdtChicago.toString());
return fromDate;
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
答案 0 :(得分:0)
如果您有新的java.time
课程,则无需将其与旧SimpleDateFormat
混合使用。要解析输入2000-01-01T12:08:56.235-0700
,只需使用java.time.format.DateTimeFormatter
并将其解析为java.time.OffsetDateTime
- 这种情况的最佳选择,因为它代表日期和时间(2000-01-01T12: 08:56.235)特定偏移量(-0700)。
然后使用java.util.Date
方法将其转换为from
。你的解串器就像这样简单:
public class CustomJsonDeserializerWithDateFormat extends JsonDeserializer<Date> {
// will deserialize inputs in the format "2000-01-01T12:08:56.235-0700"
private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXX");
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// parse input
OffsetDateTime odt = OffsetDateTime.parse(p.getText(), fmt);
// convert to java.util.Date
return Date.from(odt.toInstant());
}
}
我还重新创建了您的课程,并使用一些示例数据进行了测试:
public class RuntimePropertyData {
@JsonProperty("begin-date")
@JsonDeserialize(using = CustomJsonDeserializerWithDateFormat.class)
private Date beginDate;
// getter and setter
}
ObjectMapper om = new ObjectMapper();
Map<String, String> map = new HashMap<>();
map.put("begin-date", "2000-01-01T12:08:56.235-0700");
RuntimePropertyData data = om.convertValue(map, RuntimePropertyData.class);
System.out.println(data.getBeginDate());
现在这是棘手的部分。一个java.util.Date
doesn't have any timezone information。此类只有一个值:自UTC时间(1970-01-01T00:00Z
或&#34; 1月1日 st 1970年午夜UTC&#34; )。它只是代表一个瞬间,一个特定的时间点。
当我System.out.println
一个Date
时(或者当我记录它,或者在调试器中检查它的值时),它隐含地调用toString()
method,并将日期转换为JVM默认时区。因此,当您看到Sat Jan 01 14:08:56 EST 2000
时,这是Date
&#39; toString()
的结果。
如果您想在序列化日期时更改格式,可以使用@JsonFormat
为字段添加注释,并设置所需的时区:
@JsonProperty("begin-date")
@JsonDeserialize(using = CustomJsonDeserializerWithDateFormat.class)
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX", timezone = "UTC")
private Date beginDate;
然后,如果我序列化它:
// data is the same RuntimePropertyData I've got from the code above
System.out.println(om.writeValueAsString(data));
这将产生以下JSON(日期为UTC):
{&#34;开始最新&#34;:&#34; 2000-01-01T19:08:56.235Z&#34;}
要更改时区,您还可以在ObjectMapper
中进行设置。在这种情况下,我必须从注释中删除它:
@JsonProperty("begin-date")
@JsonDeserialize(using = CustomJsonDeserializerWithDateFormat.class)
// just the format, without timezone
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX")
private Date beginDate;
然后我在映射器中设置时区:
om.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
System.out.println(om.writeValueAsString(data));
现在输出是:
{&#34;开始最新&#34;:&#34; 2000-01-01T13:08:56.235-0600&#34;}
不幸的是,如果我再次设置时区,它就不会再改变输出了(我使用Jackson 2.8.8)。显然,保留了第一个序列化中使用的时区,并且进一步修改没有任何效果 - 因此,如果您需要高度自定义的输出(时区总是可以更改),解决方案是始终创建新的ObjectMapper