java:timezone getTimeZone(" GMT-0700")' timezone useDaylight不正确

时间:2017-10-10 07:23:06

标签: java timezone dst timezone-offset

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

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 ="美国/洛杉矶",偏移= -28800000,dstSavings = 3600000,useDaylight =真,过渡= 185,lastRule = java.util.SimpleTimeZone中[ID =美洲/洛杉矶,偏移= -28800000,dstSavings = 3600000,useDaylight =真,startYear = 0,STARTMODE = 3,startMonth = 2,朝九特派= 8,startDayOfWeek = 1,开始时间= 7200000,startTimeMode = 0,endMode = 3, endMonth = 10,endday指定= 1,一个endDayOfWeek = 1,结束时间= 7200000,endTimeMode = 0]]

     

sun.util.calendar.ZoneInfo [ID =" GMT-07:00",偏移= -25200000,dstSavings = 0,useDaylight =假,过渡= 0,lastRule =空]

我的问题是:" America / Los_Angeles"获得的有关夏令时时区信息的信息。为什么不在" GMT -0700"?

获得的时区信息中包含夏令时信息(useDaylight = false)?

2 个答案:

答案 0 :(得分:9)

  

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

所以你应该要求" America / Los_Angeles"区。这就是它的用途。

" GMT-07:00" zone是一个固定偏移区域 - 它只适用于你想要表示"一个永久性地落后UTC七小时的时区"。 适用于洛杉矶。

有很多其他时区有时在UTC-7 - 为什么你会期望GMT-07:00意味着"在洛杉矶观察到的时区" ?

换句话说,Java正在做正确的事情 - 它是你对GMT-07:00"" GMT-07:00"区域意味着不正确。

答案 1 :(得分:0)

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。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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.DateCalendar和& SimpleDateFormat

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

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore