如何解决Jackson 错误地序列化了 XMLGregorianCalendar
有一个 XMLGregorianCalendar
对象包含值 "2021-01-18T18:43:26.884Z"
(这是它在 toString()
中的输出)。当我尝试用 Jackson 序列化这个日期时,我在 3 小时后的输出中得到一个日期:
XMLGregorianCalendar date = ...;
ObjectMapper mapper = new ObjectMapper();
String out = mapper.writeValueAsstring(obj); // Output: 1610995406884 (Converted to Date: Mon Jan 18 21:43:26 MSK 2021)
我该如何解决这个问题?
解决方法
完全没有问题。
"2021-01-18T18:43:26.884Z"
中的时间 XMLGregorianCalendar
是 GMT 时区(格林威治标准时间,伦敦)或 UTC+0(由于尾随 Z
)的 18:43。
另一方面,您有一个带有字符串表示的 Date
对象
"Mon Jan 18 21:43:26 MSK 2021"
,
这是 MSK 时区(莫斯科标准时间)或 UTC+3 中的 21:43。
Date
类选择了这个时区来格式化输出
仅仅是因为您的计算机位于莫斯科附近。
所以两者实际上是同一个时间点, 只是针对两个不同的时区进行了字符串化。
,
java.util.Date
表示自纪元以来的毫秒数
java.util.Date
对象不是像 modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1,1970,00:00:00 GMT
(或 UTC)。当您打印 java.util.Date
的对象时,它的 toString
方法返回 JVM 时区中的日期时间,从这个毫秒值计算出来。如果您需要在不同的时区打印日期时间,则需要将时区设置为 SimpleDateFormat
并从中获取格式化的字符串。
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(1610995406884L);
Date date = calendar.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println(sdf.format(date));
sdf.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
System.out.println(sdf.format(date));
}
}
输出:
2021-01-18T18:43:26.884
2021-01-18T21:43:26.884
请注意,java.util
的日期时间 API 及其格式 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API。
- 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7。
- 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。
使用 java.util.Date#toInstant
将传统 java.util.Date
转换为现代 java.time.Instant
:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(1610995406884L);
Date date = calendar.getTime();
Instant instant = date.toInstant();
System.out.println(instant);
// You can convert Instant to other types e.g.
ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/Moscow"));
// Print default format i.e. the value of zdt#toString
System.out.println(zdt);
// Custom format
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss'['z']'");
String formatted = dtf.format(zdt);
System.out.println(formatted);
}
}
输出:
2021-01-18T18:43:26.884Z
2021-01-18T21:43:26.884+03:00[Europe/Moscow]
2021-01-18T21:43:26[MSK]
Z
代表 Zulu
,代表 UTC(或 GMT)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。