【问题标题】:Will Offset value handle Daylight Saving Timezone in Java?偏移值会处理 Java 中的夏令时区吗?
【发布时间】:2020-01-19 09:25:44
【问题描述】:
TimeZone.setDefault(TimeZone.getTimeZone("GMT-7:00"));

这会处理夏令时时区吗?

只需要像“America/Lost_Angeles”这样的地区名称吗?

【问题讨论】:

  • 我建议你不要使用TimeZone。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time APIZoneId。或者,如果您已经在使用 Joda-Time,那么它的DateTimeZone 也是一个选项。

标签: java datetime timezone jodatime


【解决方案1】:

您可能知道,洛杉矶在一年中的标准时间偏移量为 -08:00,而夏季时间 (DST) 的偏移量为 -07:00(就像现在一样)。其他时区使用偏移量 -07:00 的部分年份或全部年份。美国/凤凰城全年使用 -07:00。美国/丹佛在标准时间使用 -07:00,在夏季使用 -06:00。

Java 不是思想读者,因此无法猜测到 -07:00 您可能表示这些时区之一或许多其他也使用 -07:00 的时区之一。因此,当您要求 -07:00 时,您全年都会得到 -07:00。

这会处理夏令时时区吗?

没有。

只需要像 'America/Los(t)_Angeles' 这样的地区名称吗?

是的。

我建议您不要使用 TimeZone 类。它设计得很糟糕,而且已经过时了。而是使用现代 Java 日期和时间 API java.time 中的ZoneId。或者,如果您已经在使用 Joda-Time,那么它的 DateTimeZone 也是一个选项,但 Joda-Time 项目处于维护模式,不建议用于新代码。

尤其不要使用TimeZone.setDefault()。这将影响程序的每个部分以及在同一 JVM 中运行的所有其他程序。最好的解决方案是在所有日期时间操作中明确时区,这样您就可以独立于任何默认时区设置。如果由于某种原因你不能这样做(也许现在无法承受对代码库的更改),请在启动程序时从命令行设置默认时区。例如:

java -Duser.timezone=America/Los_Angeles YourJavaMainClass

链接:List of tz database time zones 包括 36 个使用偏移量 -07:00 部分或全年的时区。

【讨论】:

    【解决方案2】:

    Answer by Ole V.V. 是正确的。

    此外,请谨慎使用。请注意,设置默认时区会立即影响在该 JVM 中运行的所有应用程序的所有线程中的所有代码。仅将TimeZone.setDefault 用作绝望的最后手段。

    不要依赖默认时区。这会让您的应用程序的结果受制于系统管理员和其他 Java 程序员。您在运行时的结果可能会有所不同。

    相反,始终指定您希望/预期的时区。将 ZoneId 对象作为可选参数传递给各种日期时间方法。如果省略,Java 会隐式回退到使用 JVM 当前的默认时区。最好明确指定时区。在我看来,将时区参数设为可选是其他极好的 java.time 类中为数不多的设计错误之一,因为太多的程序员没有意识到时区所起的关键作用。

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

    “GMT-7:00”

    如果您必须使用与 UTC 的偏移量,请使用智能对象,而不是哑字符串。适当的类是ZoneOffset

    ZoneOffset offset = ZoneOffset.of( -7 ) ; 
    

    但是总是使用时区而不是仅仅使用偏移量。偏移量是 UTC 基线之前或之后的小时-分钟-秒数。

    相比之下,时区要多得多。时区是一个地区的人们使用的偏移量的过去、现在和未来变化的历史。

    任何区域的偏移量都变化得惊人。一方面,许多地方的政客都因夏令时 (DST) 的愚蠢而堕落。几十年来,这些政客一直忙于采用 DST,更改 DST 的开始和停止日期,取消 DST,重新加入 DST。现在,当前的时尚决定永久留在 DST。旋转木马转来转去。但政客们也会因为其他原因改变偏移量,比如像印度一样统一他们的国家,或者像最近朝鲜那样通过匹配或改变邻国的时区来发表声明。

    所以避免依赖固定的偏移量。使用确定的时区。

    并且保持最新的“tzdata”时区数据库副本位于:

    • 你的 JVM。
    • 您的操作系统,例如 BSD/macOS/Linux/Windows/Solaris/AIX。
    • 您的数据库引擎,例如 Postgres。
    • 您的软件库执行日期时间功能。

    【讨论】:

    • 我明白你的意思。但我只需要在应用程序的服务器启动时设置时区。但是有什么方法可以使用 Java8 类设置时区吗?与 "TimeZone.setDefault(TimeZone.getTimeZone("...."));" 相同的方式我找不到任何方法。如果你能在这方面提供帮助。
    • @MilanKamboya 不,设置默认时间是我在 java.time 中没有发现的旧类中唯一的功能。我认为这是因为以编程方式设置时区是个坏主意。正如我在回答中解释的那样,您的代码不应依赖于 JVM 的默认时区。
    • 我知道我们不应该在开始时这样做。但在我们的要求中,我需要将应用时区设置为与数据库相同。当我在 docker 容器中启动应用程序时,容器会选择 UTC 时区。因此,我需要与 db 同步并做出适当的调整。所以我正在检查不同的选项。
    【解决方案3】:

    对于日常节光timezone,在温暖的月份,从 11 月到 3 月,时间将提前一小时。 您需要检查timezone 是否适用于夏令时以及给定日期是否在这些持续时间之间。

    Java 为它们提供了方法

    TimeZone tz = TimeZone.getTimeZone("GMT5:00");
    if(tz.useDaylightTime() && tz.inDaylightTime(date1)) {
                        dst =TimeZone.getTimeZone(userTzStr).getDSTSavings();
    }
    

    该值将以毫秒为单位,相当于一小时,并且可以在返回给定格式的日期之前添加到小时。

    【讨论】:

      猜你喜欢
      • 2015-02-04
      • 2016-04-09
      • 2015-06-08
      • 2012-11-21
      • 1970-01-01
      • 2014-05-06
      • 2016-11-25
      • 1970-01-01
      • 2019-09-06
      相关资源
      最近更新 更多