java: 时区 getTimeZone( "GMT-0700" )' 时区使用夏令时不正确



我想获得洛杉矶的时区信息,现在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.calender.ZoneInfo[id="America/Los_Angeles",偏移量=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Loss_Angeles,offset=-2800000,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=720000,endTimeMode=0]]

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

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

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

所以你应该申请"美国/洛杉矶"区域。这就是它的作用。

"GMT-07:00"区域是一个固定偏移区域,只有当您想表示"永久落后UTC 7小时的时区"时,它才适用。不适用于洛杉矶。

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

换句话说,Java正在做正确的事情——你对"GMT-07:00"区域的期望是不正确的。

Jon Skeet的回答是正确的,应该被接受。您无法根据UTC的偏移量可靠地确定时区,因为许多区域可能会巧合地共享一个偏移量。此外,一个区域的偏移量可能会随着时间的推移而变化。

下面是一些代码示例,它们使用了比问题中更现代的类来解决这个问题。

java.time

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

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

ZoneIdZoneOffset类取代了TimeZone

continent/region的格式指定适当的时区名称,例如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小时)。这种偏移量的变化是由于政客们决定遵守夏令时(DST)。


关于java.time

java.time框架是在java 8及更高版本中构建的。这些类取代了诸如java.util.DateCalendar、&SimpleDateFormat

JodaTime项目现在处于维护模式,建议迁移到java.Time类。

要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。

从哪里获得java.time类?

  • Java SE 8Java SE 9及更高版本
    • 内置
    • 标准Java API的一部分,带有捆绑实现
    • Java 9添加了一些小功能和修复程序
  • Java SE 6Java SE 7
    • 大部分Java.time功能都是向后移植到Java 6&7英寸ThreeTen背包
  • Android
    • java.time类的Android捆绑包实现的后续版本
    • 对于早期的Android,ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…

ThreeTen Extra项目通过附加类扩展java.time。这个项目是将来可能添加到java.time的试验场。您可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等等。

相关内容

  • 没有找到相关文章

最新更新