Java TimeZone 令人头疼

Mon*_*ded 1 java timezone

我想以夏令时证明格式保存一些用户时区。
我的目标是在代码执行时获得正确的 GMT 偏移量。
为了找出最好的选择,我写了以下内容:

ArrayList<String> list = new ArrayList<String>();
list.add( "EST");
list.add( "EDT");
list.add( "America/New_York");
long now = System.currentTimeMillis();
for( String tzID: list) {
    TimeZone tz = TimeZone.getTimeZone( tzID);
    System.out.println( tzID + " now=" + tz.getOffset( now) / 3600000 + " / +182=" + tz.getOffset( now + ( 182 * 86400000)) / 3600000);
}
Run Code Online (Sandbox Code Playgroud)

简而言之,现在给我偏移量,在
9 月 3 日执行的 182 天内,输出是

EST now=-5 / +182=-5
EDT now=0 / +182=0
America/New_York now=-4 / +182=-4
Run Code Online (Sandbox Code Playgroud)

这是意外的,有几个原因
1) 为什么 America/New_York 不给出 -4/-5 ?,它不应该对日期敏感吗?
2) 为什么 EDT == UTC?

Arv*_*ash 5

java.time

该问题和接受的答案使用java.util日期时间 API,这在 2012 年是正确的做法。2014 年 3 月,现代日期时间 API作为Java 8 标准库的一部分发布,取代了旧的日期时间 API从那时起,强烈建议切换到java.time现代日期时间 API。

解决方案使用java.time

您可以使用ZonedDateTime它自动调整给定的时区偏移ZoneId

演示:

import java.time.ZoneId;
import java.time.ZonedDateTime;

class Main {
    public static void main(String[] args) {
        ZoneId zone = ZoneId.of("America/New_York");
        ZonedDateTime now = ZonedDateTime.now(zone);
        ZonedDateTime after182Days = now.plusDays(182);
        System.out.println(zone + " now=" + now.getOffset() + " / +182=" + after182Days.getOffset());
    }
}
Run Code Online (Sandbox Code Playgroud)

截至目前的输出

America/New_York now=-05:00 / +182=-04:00
Run Code Online (Sandbox Code Playgroud)

ONLINE DEMO

从Trail: Date Time中了解有关现代日期时间 API 的更多信息。

不要使用三个字母的时区 ID:Java 7Timezone 文档中的注释:

三字母时区 ID

为了与 JDK 1.1.x 兼容,还支持一些其他三字母时区 ID(例如“PST”、“CTT”、“AST”)。然而,它们的使用已被弃用,因为相同的缩写通常用于多个时区(例如,“CST”可能是美国“中部标准时间”和“中国标准时间”),并且 Java 平台只能识别其中之一他们。