【问题标题】:java.util.Date is parsing wrong dates with dates before 1912java.util.Date 正在使用 1912 年之前的日期解析错误的日期
【发布时间】:2023-04-04 14:25:01
【问题描述】:

我不明白 Jackson 库在 1912 年之前解析错误日期的原因。我想问题是 java.util.Date 转换,因为 Gson 仍然存在问题。

这是我的代码:

ObjectMapper mapper = new ObjectMapper();
String tmp = "{\"date\":\"1911-01-01T00:00:00+00:00\"}";
        
Response resp = mapper.readValue(tmp, Response.class);
System.out.println("Date->"+resp.date);

日期是 java.util.Date 类型的字段

如你所见,输入为:1911-01-01T00:00:00+00:00

而输出是:Sun Jan 01 00:09:21 CET 1911(我不明白为什么要设置那个时间)

但是如果我设置这个输入:1912-01-01T00:00:00+00:00

输出正确:Mon Jan 01 00:00:00 CET 1912

仅发生在 1912 年之前的日期。

JDK v1.8.0_101

谢谢。

【问题讨论】:

  • 我不打算花时间调查这个,因为正如 Basil Bourque 的回答所说,你应该切换到 java.time 包而不是使用旧的 java.util.Date 类 - 但是 - “我想问题出在 java.util.Date 转换”——一般来说,你不应该假设错误出现在完善的库或包中;这几乎总是软件包用户的误解或错误。在彻底调查自己的代码之前,不要责怪包。 1912 年是民国历中的一个重要日期,也是明治时代的结束,因此可以考虑。
  • 您的默认时区是哪个?欧洲/马德里?欧洲/巴黎?还有什么?
  • 输出正确。过去发生了一些奇怪的时区变化。我知道有一个现有的 Stack Overflow 问题涵盖了这个……

标签: java json date parsing


【解决方案1】:

java.time

永远不要使用遗留类Date。不要浪费时间去理解DateCalendar 的混乱。

只使用现代的 java.time 类。更高版本的 Jackson 支持 java.time

OffsetDateTime odt = OffsetDateTime.parse( "1911-01-01T00:00:00+00:00" ) ;

当被要求生成表示其值的文本时,OffsetDateTime 生成:

odt.toString(): 1911-01-01T00:00Z

末尾的Z 表示与UTC 零时分秒的偏移量,发音为“Zulu”。


有关使用遗留类的代码发生了什么的解释,请参阅excellent Answer by Ole V.V. 但请注意,在 java.time 中使用正确设计的类可以避免潜在问题:应用一个不需要的时区。

时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史记录。您的输入带有偏移量(零),没有时区指示。因此,在处理您的输入时无需涉及时区。

【讨论】:

  • 好建议。但这给出了什么输出?它解决了问题吗?
  • @ErwinBolwidt 在该OffsetDateTime 上调用toString 会生成与输入几乎相同的文本。不涉及不必要的时区,问题解决了。
【解决方案2】:

Basil Bourque 已发布了具有良好解决方案的良好答案。以下是解释您观察到的原因的答案。

从定义标准时间到 1911 年 3 月 11 日,欧洲/巴黎时区的偏移量为 +00:09:21。我相信北非(阿尔及利亚、突尼斯)的一些法国属地也会效仿。因此,如果您的默认时区位于其中一个地方,那么 VGR 在您的输出正确的注释中是正确的。

挑剔:只有时区缩写是值得商榷的。根据下面的链接,它应该是 PMT(据说是巴黎标准时间),而不是 CET(据说是中欧时间)。我不认为现在已经过时的Date 课程曾经有过提供正确的历史时区缩写的野心。它可能只是给出CET,因为这些天巴黎使用中欧时间。

曾几何时,每个首都和许多其他大都市的时间都由它们的平均太阳时定义,而不是从某个标准时间参考(GMT 后来获得的角色以及更晚的 UTC)开始的整数小时数。所以当时 +00:09:21 的偏移量并没有什么特别的。

    ZonedDateTime dateTimeInFrance = OffsetDateTime.parse("1911-01-01T00:00:00+00:00")
            .atZoneSameInstant(ZoneId.of("Europe/Paris"));
    System.out.println(dateTimeInFrance);

输出:

1911-01-01T00:09:21+00:09:21[欧洲/巴黎]

近乎重复:Convert a timestamp before year 1900 in java

更多链接:Time Changes in Paris Over the Years

【讨论】:

    猜你喜欢
    • 2017-09-23
    • 2018-03-20
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多