java: timezone getTimeZone("GMT-0700")' 时区使用日光不正确

Posted

技术标签:

【中文标题】java: timezone getTimeZone("GMT-0700")\' 时区使用日光不正确【英文标题】:java: timezone getTimeZone("GMT-0700")' timezone useDaylight incorrectjava: timezone getTimeZone("GMT-0700")' 时区使用日光不正确 【发布时间】:2018-03-21 12:15:03 【问题描述】:

我想获取洛杉矶的时区信息,现在 2017 年 10 月 10 日是夏令时, 但是当我通过两种方式获得洛杉矶的时区时,我得到了不同的结果。

public class TimeZoneDemo2 
  public static void main(String[] args) 
    TimeZone timeZoneLosAngeles = 
    TimeZone.getTimeZone("America/Los_Angeles");
    System.out.println(timeZoneLosAngeles);

    TimeZone timeZoneGmtMinus07 = TimeZone.getTimeZone("GMT-07:00");
    System.out.println(timeZoneGmtMinus07);
  

结果是:

sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles, offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay =1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]

sun.util.calendar.ZoneInfo[id="GMT-07:00",offset=-25200000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]

我的问题是:“America/Los_Angeles”获得的时区信息中的夏令时信息。为什么不在“GMT -0700”获取的时区信息中包含夏令时信息(useDaylight = false)?

【问题讨论】:

您暗示TimeZone.getTimeZone(String) 的结果取决于当前时间是不正确的。 有多个位置是 GMT-7 mapstudio.co.za/wp-content/uploads/2014/02/9781770265646.jpg 它怎么知道你的意思是洛杉矶? GMT-07:00 是一个 offset(与 UTC 的差异),而 America/Los_Angeles 是一个 timezone(一个区域在历史),阅读更多关于区别here。如前所述,that uses the same offset 不止一个时区,所以只有拥有 GMT-7,你才能can't say which timezone is 【参考方案1】:

我想获取洛杉矶的时区信息,现在 2017 年 10 月 10 日是夏令时

所以你应该请求“America/Los_Angeles”区域。这就是它的用途。

“GMT-07:00”时区是一个固定偏移时区 - 它仅适用于您想要表示“一个永久比 UTC 晚 7 小时的时区”。这适用于洛杉矶。

还有很多其他时区有时在 UTC-7 - 为什么您认为 GMT-07:00 表示“在洛杉矶观察到的时区”?

换句话说,Java 正在做正确的事 - 是您对“GMT-07:00”区域含义的期望不正确。

【讨论】:

此外,洛杉矶一年中的部分时间是UTC-8;如果您希望 Java 在您使用 GMT-7 时猜测您的意思是 Olsen id,它怎么知道您不是指 Denver? (或在一年中的部分时间使用 -7 的任何其他地方)。 ...或 Phoenix,整个年为 -7。【参考方案2】:

Answer by Jon Skeet 是正确的,应该被接受。您无法从与 UTC 的偏移量中可靠地确定时区,因为许多区域可能同时共享一个偏移量。此外,区域的偏移量可能会随时间而变化。

这里有一些代码示例使用比问题中看到的更现代的类解决了这个问题。

java.time

您正在使用麻烦的旧日期时间类,它们现在是遗留的,被 java.time 类所取代。

正如其他人所说,如果您知道预期的时区,请始终优先使用该时区,而不是仅仅使用 offset-from-UTC。偏移量只是 UTC 之前或之后的小时数、分钟数和秒数。时区是一个地区的人们使用的偏移量变化的历史。时区知道这种偏移量变化的过去、现在和(暂时)未来。

ZoneIdZoneOffset 类替换了 TimeZone

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;  // Or "Africa/Tunis", "Pacific/Auckland", etc.

通过该区域的镜头获取当前时刻。

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Fetch current moment for that zone.

提取同一时刻,但调整为 UTC。

Instant instant = zdt.toInstant() ;  // Extract the same moment but in UTC.

将某个时刻调整到另一个区域。

ZonedDateTime zdtKolkata = instant.atZone( ZoneId.of( "Asia/Kolkata" ) ) ;  // Determine same moment, same point on timeline, but in another time zone.

所有这三个对象都代表时间轴上的同一个同时点,但以不同的挂钟时间查看。

查看当时那个地区的人们使用的偏移量。

ZoneOffset offset = z.getRules().getOffset( instant ) ;  // Get the offset in place at that moment for that time zone.

您会发现,在 2018 年的部分时间里,America/Los_Angeles 的偏移量将是 -07:00(比 UTC 晚几个小时)。在一年中的其他时间,偏移量将是-08:00(比 UTC 晚 8 小时)。这种抵消的变化是由于政客们决定遵守Daylight Saving Time (DST)。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

从哪里获得 java.time 类?

Java SE 8Java SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android,ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

以上是关于java: timezone getTimeZone("GMT-0700")' 时区使用日光不正确的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中的时区设置

Java - 我怎样才能获得一个 K-hour-shifted TimeZone?

Java如何根据TimeZone转换时间,可以给出相关的例子吗?谢谢

日历未返回 GMT

timezone

在 IST 时区 java 中生成时间戳