SimpleDateFormat setTimeZone 不起作用

mbh*_*n88 6 java groovy timezone datetime simpledateformat

我使用下面的代码来施法时间为UTC这是工作

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
Run Code Online (Sandbox Code Playgroud)

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

它只与 TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

为什么这样?

评论后更新:输出需要在 CET 但在 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();
Run Code Online (Sandbox Code Playgroud)

? 输出:

Mon Mar 19 05:00:00 UTC 2018
2018-03-19 05:00:00.0
Run Code Online (Sandbox Code Playgroud)

Ole*_*.V. 5

时间

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

这打印

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

与过时的Date类相反,现代 Java 日期和时间 API 中的OffsetDateTimefromjava.time确实包含 UTC 偏移量,顾名思义。我没有使用 Groovy 的经验,很抱歉不得不信任您从我的 Java 代码中进行翻译。

如果您想确保获得特定的时区,而不管字符串中的偏移量:

    ZoneId zone = ZoneId.of("Europe/Brussels");
    ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);
Run Code Online (Sandbox Code Playgroud)

这次的结果是:

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

不要依赖三个字母的时区缩写,如 CET。CET 是许多欧洲时区的标准时间一半(没有夏令时/DST 的部分)的通用名称,这些时区通常共享时间,但并非总是如此,并且在涉及历史日期时往往会出现分歧。其他三个字母的缩写含糊不清,因此会导致更多的混乱。始终将时区作为地区/城市,就像我对欧洲/布鲁塞尔所做的那样。当然,选择与您所需时区相匹配的城市。

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

    Instant inst = dateTime.toInstant();
    System.out.println(inst);
Run Code Online (Sandbox Code Playgroud)

输出

2018-03-19T05:00:00Z

Instants 总是以 UTC 打印。如果足够新的 JDBC 驱动程序不可用,您可以Timestamp通过以下两种方式之一转换为:

    System.out.println(Timestamp.from(inst));
    System.out.println(Timestamp.valueOf(dateTime.toLocalDateTime()));
Run Code Online (Sandbox Code Playgroud)

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

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

你的代码出了什么问题?

当您SimpleDateFormat用于解析带有 UTC 偏移量的字符串时,它会使用该偏移量来确定时间点。在这种情况下,它不会使用您setTimeZone为任何内容设置的时区。它不会将任何时区或偏移量放入Date它返回的内容中,因为 aDate不能包含时区。这只是一个时间点。

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

TimeZoneDateTimestamp类早已过时。SimpleDateFormat太麻烦了,同时也是出了名的麻烦。我建议您根本不要使用这些类。java.time使用起来要好得多。

关联

Oracle 教程:解释如何使用java.time.