3

给定以下单元测试:

@Test
public void zonedDateTimeCorrectlyRestoresItself() {

    // construct a new instance of ZonedDateTime
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Z"));
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3820} "Z"

    String converted = now.toString();

    // restore an instance of ZonedDateTime from String
    ZonedDateTime restored = ZonedDateTime.parse(converted);
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3820} "Z"

    assertThat(now).isEqualTo(restored); // ALWAYS succeeds
}

@Test
public void jacksonIncorrectlyRestoresZonedDateTime()  {

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.findAndRegisterModules();
    objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

    // construct a new instance of ZonedDateTime
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Z"));
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3820} "Z"


    String converted = objectMapper.writeValueAsString(now);

    // restore an instance of ZonedDateTime from String
    ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class);
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3821} "UTC"

    assertThat(now).isEqualTo(restored); // NEVER succeeds
}

这个解决方法:

@Test
public void usingDifferentComparisonStrategySucceeds() throws Exception  {

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.findAndRegisterModules();
    objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

    // construct a new instance of ZonedDateTime
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Z"));
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3820} "Z"

    String converted = objectMapper.writeValueAsString(now);

    // restore an instance of ZonedDateTime from String
    ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class);
    // offset = {ZoneOffset@3820} "Z"
    // zone   = {ZoneOffset@3821} "UTC"

    // the comparison succeeds when a different comparison strategy is used
    // checks whether the instants in time are equal, not the java objects
    assertThat(now.isEqual(restored)).isTrue(); 
}

我想我想弄清楚为什么杰克逊内部不打电话ZonedDateTime.parse()?我个人认为这是杰克逊的一个错误,但我没有足够的信心在没有一些反馈的情况下为它打开一个问题。

4

1 回答 1

6

引用ISO 8601的维基百科:

如果时间是 UTC,则在时间Z后直接添加一个,不带空格。Z是零 UTC 偏移的区域指示符。"09:30 UTC"因此表示为"09:30Z""0930Z""14:45:15 UTC"将是"14:45:15Z""144515Z"

UTC 时间也称为祖鲁时间,因为祖鲁是 Z 的北约拼音字母词。

Z不是区域。UTC是区域,然后使用格式化字符串表示。Z

永远不要使用ZoneId.of("Z"). 这是错的。

于 2017-06-05T15:45:13.380 回答