设置了时区的SimpleDateFormat获取正确的值但是区域错误 [英] SimpleDateFormat with Timezone set gets correct value but wrong zone

查看:139
本文介绍了设置了时区的SimpleDateFormat获取正确的值但是区域错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  @SpringBootApplication 
公共类MemberIntegrationApp {

@Autowired
private TimeZoneProperties timeZoneProperties;

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

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

}

而且,这个简单的测试:( 测试类使用 @SpringBootTest 进行批注,以在主类中加载配置,并应用 @SpringRunner ,太

  / ** 
*测试设置时区的效果
* /
@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(试图解析日期字符串:{},d);
日期结果= f.parse(d);
log.info(结果应该是12:34 UTC:{},结果);

f.setTimeZone(TimeZone.getTimeZone(UTC));
result = f.parse(d);
log.info(结果应该是12:34 UTC:{},结果);

f.setTimeZone(TimeZone.getTimeZone(Europe / Madrid));
result = f.parse(d);
log.info(结果应为10:34 CEST:{},结果);
log.info(Now offset(depre):{},result.getTimezoneOffset());
}

我有输出:

 尝试解析日期字符串:2018-08-08 12:34:56 
结果应该是12:34 UTC:Wed Aug 08 12:34:56 UTC 2018
结果应该是12:34 UTC:Wed Aug 08 12:34:56 UTC 2018
结果应该是10:34 CEST:Wed Aug 08 10:34:56 UTC 2018
现在偏移量(depre):0

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



它是UTC,因为转换为字符串时在 log.info()中,slf4j是干扰????或者是什么?我不这么认为,因为 System.out.println()也给了我UTC。



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



解析时 Timezone.getDefault()的影响是什么使用SimpleDateFormat?什么是 f.getTimezone()?他们似乎在这个过程的不同部分行动.....



我问这个问题,因为内部杰克逊使用 SimpleDateFormat 处理日期字符串/格式化日期。 ObjectMapper 上的配置会影响映射器使用的 SimpleDateFormat 吗?

解决方案

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

  f.setTimeZone(TimeZone.getTimeZone(Europe / Madrid)); 
result = f.parse(d);
log.info(结果应为10:34 CEST:{},结果);

这是什么意思?



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



然后你显示它。它无法猜测您想要的时区,因此它会在您的情况下以默认时区UTC显示。






<请注意:




  • 它实际上是UTC的10:34而马德里的时间是12:34,而不是相反。 / li>
  • Date.getTimezoneOffset() UTC与默认时区之间的偏移量(因此在您的情况下为0),与您使用的时区无关配置解析器。此外,自java 1.1以来它已被弃用,你不应该再使用它了。



要在不同时区显示日期值,<可以使用code> 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()));


I have a simple test in a Spring application, which has default timezone set to 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);
    }

}

And, this simple test: (The test class is annotated with @SpringBootTest to load the configuration in main class and @SpringRunner is applied, too)

/**
 * 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());
}

I have output:

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

Now, why the fourth line has the value correct, but the timezone is wrong? It should be Europe/Madrid. And the offset(which is deprecated in Java 8, OK I can forgive it), it should be +0200, not 0.

It is UTC because when converting to string in log.info(), slf4j is interferring???? Or what? I don't think so because System.out.println() gives me UTC too.

I know I should use OffsetDateTime, but it is legacy and we cannot change all fields of date to that, for now. I want to know why Java parsed it wrongly.

What is the effect of Timezone.getDefault() when parsing with SimpleDateFormat? And what is that of f.getTimezone()? They seem to act in different part of the process.....

I ask this question, because internally Jackson uses SimpleDateFormat to process date string/formatting dates. Does the config on an ObjectMapper affect the SimpleDateFormat that the mapper uses?

解决方案

I don't think it's a bug, but rather a misinterpretation of the lines:

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

What does it mean ?

You first set a time zone, telling the parser you are about to parse a time in Europe/Madrid zone.

Then you display it. It cannot guess in which time zone you want it, so it displays it in the default time zone, UTC in your case.


Note that:

  • it's actually 10:34 in UTC while it's 12:34 in Madrid, and not the other way round.
  • Date.getTimezoneOffset() is the offset between UTC and the default timezone (thus 0 in your case), nothing to do with the time zone you used to configure the parser. Moreover it is deprecated since java 1.1, you should not really use it anymore.

To display a date value in different time zone, SimpleDateFormat.format() can be used, for instance:

    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()));

这篇关于设置了时区的SimpleDateFormat获取正确的值但是区域错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆