一尘不染

设置了时区的SimpleDateFormat获取正确的值,但时区错误

spring-boot

我在Spring应用程序中进行了一个简单的测试,该应用程序的默认时区设置为UTC

@SpringBootApplication
public class MemberIntegrationApp {

    @Autowired
    private TimeZoneProperties timeZoneProperties;

    @PostConstruct
    void started() {
        TimeZone.setDefault(TimeZone.getTimeZone(timeZoneProperties.getAppDefault()));  // which is UTC
    }

    public static void main(String[] args) {
        SpringApplication.run(MemberIntegrationApp.class, args);
    }

}

而且,这个简单的测试:( 测试类也带有注释,@SpringBootTest以将配置加载到主类中并被@SpringRunner应用

/**
 * Test the effect of setting timezone
 */
@Test
public void testTimezoneSettingOnSimpleDateFormat() throws ParseException {
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String d = "2018-08-08 12:34:56";
    log.info("Trying to parse the date string: {}", d);
    Date result = f.parse(d);
    log.info("The result should be 12:34 UTC: {}", result);

    f.setTimeZone(TimeZone.getTimeZone("UTC"));
    result = f.parse(d);
    log.info("The result should be 12:34 UTC: {}", result);

    f.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
    result = f.parse(d);
    log.info("The result should be 10:34 CEST: {}", result);
    log.info("Now the offset(depre): {}", result.getTimezoneOffset());
}

我有输出:

Trying to parse the date string: 2018-08-08 12:34:56
The result should be 12:34 UTC: Wed Aug 08 12:34:56 UTC 2018
The result should be 12:34 UTC: Wed Aug 08 12:34:56 UTC 2018
The result should be 10:34 CEST: Wed Aug 08 10:34:56 UTC 2018
Now the offset(depre): 0

现在,为什么第四行的值正确,但时区错误?应该是Europe/Madrid。偏移量(在Java
8中已弃用,好的,我可以原谅),它应该是+0200,而不是0。

之所以是UTC,是因为当转换为in时log.info(),slf4j会干扰吗?要不然是啥?我不这么认为,因为也System.out.println()给我UTC。

我知道我应该使用OffsetDateTime,但是这是遗留的,我们暂时无法将所有日期字段更改为该字段。我想知道为什么Java错误地解析了它。

Timezone.getDefault()使用SimpleDateFormat进行解析有什么作用?那是什么f.getTimezone()呢?他们似乎在流程的不同部分起作用。

我问这个问题,因为在内部Jackson
SimpleDateFormat用来处理日期字符串/格式日期。配置是否ObjectMapper影响SimpleDateFormat映射器使用的?


阅读 645

收藏
2020-05-30

共1个答案

一尘不染

我不认为这是一个错误,而是对行的错误理解:

    f.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
    result = f.parse(d);
    log.info("The result should be 10:34 CEST: {}", result);

这是什么意思 ?

您首先设置一个时区,告诉解析器您将要解析欧洲/马德里时区的时间。

然后显示它。它无法猜测您希望在哪个时区,因此它以默认时区(在您的情况下为UTC)显示。


注意:

  • 它实际上是UTC的10:34,而马德里是12:34,而不是相反。
  • Date.getTimezoneOffset()UTC与默认时区(在您的情况下为0)之间偏移量,与用于配置解析器的时区无关。此外,从Java 1.1开始不推荐使用,您不再应该真正使用它。

要显示不同时区的日期值,SimpleDateFormat.format()可以使用,例如:

    f.setTimeZone(TimeZone.getTimeZone("UTC"));
    log.info("UTC {}", f.format(new Date()));
    f.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
    log.info("Europe/Madrid {}", f.format(new Date()));
2020-05-30