SimpleDateFormat setTimeZone无法正常工作 [英] SimpleDateFormat setTimeZone not working

查看:120
本文介绍了SimpleDateFormat setTimeZone无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码将时间转换为 UTC 起作用

I am using the below code to cast time as UTC which is working

import java.text.SimpleDateFormat;
import static java.util.Calendar.* 

def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"

TimeZone tz  = TimeZone.getDefault(); //getting up local time zone
TimeZone.setDefault(TimeZone.getTimeZone("UTC")); 
SimpleDateFormat sdf = new SimpleDateFormat(format);      
Date d = sdf.parse(dt);
TimeZone.setDefault(tz);

println d //output: 2018-03-19T05:00:00Z

println d.toTimestamp(); //Output: 2018-03-19 06:00:00.0

但是当我使用 TimeZone.setTimeZone(TimeZone.getTimeZone( UTC)); 则它不起作用。

But when I use TimeZone.setTimeZone(TimeZone.getTimeZone("UTC")); then it not working.

仅在 TimeZone.setDefault(TimeZone.getTimeZone( UTC));

为什么?

评论后进行更新:输出必须在CET中,但必须在UTC中

Update after comments: Outputs needs to be in CET but in UTC

def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"
SimpleDateFormat sdf = new SimpleDateFormat(format);      
sdf.setTimeZone(TimeZone.getTimeZone("CET"))
Date d = sdf.parse(dt);

println d
println d.toTimestamp();


输出:

Mon Mar 19 05:00:00 UTC 2018
2018-03-19 05:00:00.0


推荐答案

java.time



java.time

    String dt = "2018-03-19T06:00:00+01:00";
    OffsetDateTime dateTime = OffsetDateTime.parse(dt);
    System.out.println(dateTime);

此打印文件


2018-03-19T06:00 + 01:00

2018-03-19T06:00+01:00

与过时的 Date 类是现代Java日期和时间API java.time 中的 OffsetDateTime 顾名思义,UTC偏移量。我没有Groovy的经验,所以很抱歉不得不信任您从我的Java代码进行翻译。

Contrary to the outdated Date class, an OffsetDateTime from java.time, the modern Java date and time API, does contain a UTC offset, as the name also says. I don’t have experience with Groovy, so sorry to have to trust you to translate from my Java code.

如果您要确保获得特定的时区不管字符串中的偏移量是什么:

If you want to make sure you get a specific time zone regardless of which offset is in the string:

    ZoneId zone = ZoneId.of("Europe/Brussels");
    ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);

这次结果是:


2018-03-19T06:00 + 01:00 [欧洲/布鲁塞尔]

2018-03-19T06:00+01:00[Europe/Brussels]

不要依赖在三个字母的时区缩写上,例如CET。 CET是许多欧洲时区的标准时区(不含夏令时/ DST的部分)的通用名称,这些时区通常共享时间,但并非总是如此,并且在历史日期的时间上往往存在分歧。其他三个字母的缩写含糊不清,从而导致更加混乱。就像我在欧洲/布鲁塞尔所做的那样,始终将时区指定为地区/城市。当然,请选择与所需时区匹配的城市。

Don’t rely on three letter time zone abbreviations like CET. CET is a common name for the standard time half (the part without summer time/DST) of very many European time zones that generally share time, but have not always done so and tend to disagree on the time when it comes to historic dates. Other three letter abbreviations are ambiguous and thus lead to even more confusion. Always give time zone as region/city, as I did with Europe/Brussels. Of course, pick the city that matches your desired time zone.

如果您认为需要 java.sql.Timestamp -您可能不需要。如果使用JDBC 4.2或更高版本或类似的现代JPA实现,最好存储 Instant LocalDateTime 到您的数据库。选择取决于您的确切要求和数据库列的确切数据类型。

If you think you need a java.sql.Timestamp — you may not need that. If using JDBC 4.2 or higher or a similarly modern JPA implementation, it is better to store either an Instant or a LocalDateTime to your database. The choice depends on your exact requirements and the exact datatype of your database column.

    Instant inst = dateTime.toInstant();
    System.out.println(inst);

输出


2018-03-19T05:00:00Z

2018-03-19T05:00:00Z

即时总是以UTC打印。如果没有足够新的JDBC驱动程序,则可以通过以下两种方式之一转换为 Timestamp

Instants always print in UTC. If a sufficiently new JDBC driver is unavailable, you may convert to Timestamp in either of two ways:

    System.out.println(Timestamp.from(inst));
    System.out.println(Timestamp.valueOf(dateTime.toLocalDateTime()));




2018-03-19 06:00:00.0
2018-03-19 06:00:00.0

2018-03-19 06:00:00.0
2018-03-19 06:00:00.0

因为我的时区与日期时间对象中的时区一致,所以我从两次转换中获得相同的结果。在其他时区中,结果可能会有所不同,您需要小心选择正确的时区。

Because my time zone agrees with the time zone in the date-time object, I get the same result from both conversions. In other time zones the result may not be the same, and you will need to take care to pick the correct one.

当您使用 SimpleDateFormat 解析带有UTC偏移量的字符串时,它将使用该偏移量来确定时间点。在这种情况下,它不会使用您通过 setTimeZone 设置的时区进行任何操作。并且它不会在返回的 Date 中添加任何时区或偏移量,因为 Date 不能包含时区。只是一个时间点。

When you use SimpleDateFormat for parsing a string with a UTC offset in it, it uses that offset for determining the point in time. In this case it does not use the time zone you have set through setTimeZone for anything. And it doesn’t put any time zone or offset into the Date it returns because a Date cannot contain a time zone. It is just a point in time.

令人困惑的是, Date.toString()的结果似乎包含时区缩写,例如输出中的UTC Mon Mar 19 05:00:00 UTC 2018 。发生的情况是 toString()使用JVM的时区设置来生成字符串。这就是为什么 TimeZone.setDefault()影响您获得的输出的原因:它设置JVM设置,影响在同一JVM中运行的所有程序。它不影响 Date 对象本身,但是仅影响其 toString()的结果。

What confuses many is that the result of Date.toString() seems to contain a time zone abbreviation, as UTC in your output Mon Mar 19 05:00:00 UTC 2018. What happens is that toString() uses the JVM’s time zone setting for generating the string. This is why TimeZone.setDefault() affects the output you get: it sets the JVM setting, affecting all programs running in the same JVM. It doesn’t affect the Date object itself, however, only the result of its toString().

TimeZone Date Timestamp 类早已过时。 SimpleDateFormat 也太麻烦了。我建议您完全不要使用这些类。 java.time 更好用。

The TimeZone, Date and Timestamp classes are long outdated. SimpleDateFormat is too and at the same time notoriously troublesome. I recommend you don’t use those classes at all. java.time is so much nicer to work with.

Oracle教程:日期时间解释了如何使用 java.time

这篇关于SimpleDateFormat setTimeZone无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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