时区ID错误地显示夏令时

3

有人可以解释一下这个吗?

TimeZone tz1 = TimeZone.getTimeZone(“CST”); ==> ID of tz1 is CST
TimeZone tz2 = TimeZone.getTimeZone(“CDT”); ==> ID of tz2 is GMT ????

2
从[Java Docs](http://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html)中得知:为了与JDK 1.1.x兼容,还支持一些其他三个字母的时区ID(例如“ PST”,“ CTT”,“ AST”)。但是,它们的使用已被弃用,因为同一缩写通常用于多个时区(例如,“ CST”可以是美国“中央标准时间”和“中国标准时间”),而Java平台只能识别其中一个。 - anycard
1
+1 给anycard的评论。你应该使用完整的时区标识符。Central时间是America/Chicago。它包括CST和CDT两个时区。 - Matt Johnson-Pint
2个回答

1

对我来说,以下测试代码会产生“未找到 => CDT”的结果:

for (String tz : TimeZone.getAvailableIDs()) {
    if (tz.equals("CDT")) {
        System.out.println("Found: " + tz);
    }
}

System.out.println("Not found => CDT");

这意味着java.util.TimeZone会从不存在的CDT区域回退到"GMT",如文档所述:

返回:指定的TimeZone,如果无法理解给定的ID,则为GMT区域。

在Java 8中,您可以选择使用ZoneId,它没有令人困惑的后备行为,而是抛出一个我认为更好的ZoneRulesException

为什么我们必须完全获得 ZoneRulesException 异常? - IgorGanapolsky
1
@IgorGanapolsky 不抛出异常意味着默默地回退到任何时区(这里是GMT),这只是猜测,并与用户可能期望的无关。通常,用户在客户端机器上的标准时区不是GMT,因此回退区域GMT通常会导致错误的时区计算,这更糟糕。异常至少会警告用户检查他的程序代码或输入(这里是CDT)或他的区域配置。 - Meno Hochschild

0

简而言之

CSTCDT不是时区。

请使用真正的时区,例如America/Chicago

ZoneId
.of( "America/Chicago" ) 
.getRules()
.isDaylightSavings( 
    Instant.now()
)

false

伪时区

TimeZone.getTimeZone(“CST”)

糟糕,那一行没有意义。CST不是一个时区。

永远不要使用2-4个字母的伪时区,例如PSTPDTCSTIST等。这些不是真正的时区,也没有标准化,甚至不是唯一的!例如,我猜你认为CST是“中央标准时间”。但是CST也是“中国标准时间”。

请以大陆/地区的格式指定正确的时区名称,例如America/MontrealAfrica/CasablancaPacific/Auckland。永远不要使用2-4个字母的缩写,例如ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的!

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;  

ZoneId

挖掘以发现您感兴趣的区域使用的实时时区。如果您通过CST指的是北美中西部的某个时区,也许您真正需要的是像America/ChicagoAmerica/Winnipeg这样的东西。

ZoneId z = ZoneId.of( "America/Chicago" ) ;  

America/Chicago 时区参与所谓的夏令时(DST),因此我们可以询问当前是否正在使用DST。当媒体发布CSTCDT时,这表示DST当前是否在使用。

ZoneRules

获取该时区的规则。

ZoneRules rules = z.getRules() ;

即时

查询特定时刻的夏令时状态和偏移量。这里我们将使用当前时刻。

Instant now = Instant.now() ;

now.toString(): 2020-02-10T00:06:26.000116Z

ZonedDateTime

以我们的时区查看同一时刻。

ZonedDateTime zdt = now.atZone( z ) ;

zdt.toString(): 2020-02-09T18:06:26.000116-06:00[America/Chicago]
现在问有关偏移和夏令时的问题。
ZoneOffset offset = rules.getOffset( now );
boolean inDST = rules.isDaylightSavings( now );

offset.toString(): -06:00

inDST: false

请参见IdeOne.com上的实时代码运行

Table of date-time types in Java, both modern and legacy


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接