如何在特定日期设置时区?

How do I set timezone on a specific date?

我遇到了一个问题,我尝试了所有方法(包括在线 Whosebug 线程),但无法在特定日期按预期设置时区。 这是我的代码:

Date until = DateTimeUtils.getNewBookUntilDate();
//which returns : Wed Aug 28 11:00:02 EDT 2019 

SimpleDateFormat isoFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
            isoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles");
try {
    until = isoFormat.parse(until.toString());
} catch (ParseException e) {
     e.printStackTrace();
}

但我仍然得到:Wed Aug 28 11:00:02 EDT 2019,而不是 Wed Aug 28 8:00:02 PDT 2019

知道怎么做吗?

避免java.util.Date

A java.util.Date 表示 UTC 中的一个时刻。无需将其作为文本进行操作。当心:方法 Date::toString 撒谎 ,在生成文本时动态应用 JVM 当前的默认时区。

而是使用 java.time.Instant

首先从可怕的遗产 class 转换为现代替代品 java.time.Instant。请注意添加到旧 classes 的新转换方法。

Instant instant = myDate.toInstant() ;

ZonedDateTime

一个Instant也是UTC中的一个时刻。要通过某个地区的人们使用的与 UTC 的偏移量来查看同一时刻,请应用 ZoneId 以获得 ZonedDateTime 对象。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

要清楚:这个zdt对象和这个instant对象都代表同一时刻,时间轴上的同一点。它们仅在挂钟时间上有所不同。想象一下 Iceland 中的某个人(始终使用 UTC)给魁北克的某个人打电话,他们都抬头看着各自墙上的时钟。

从现代转换为传统

如果您手头有一个 ZonedDateTime 对象,并且您必须获得一个 java.util.Date 用于与尚未更新到 java.time[=108 的旧代码进行互操作=],可以转换。通过从 ZonedDateTime 对象中提取 Instant,从 Instant 变为 Date

Instant instant = zdt.toInstant() ;
java.util.Date date = java.util.Date.from ( instant ) ;

如果您需要 Calendar 而不是 Date,转换会更直接。

Calendar cal = GregorianCalendar.from( zdt ) ;

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?