我想获得洛杉矶的时区信息,现在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之前或之后的小时、分钟和秒数。时区是一个地区的人们使用的偏移量变化的历史。时区知道这种偏移变化的过去、现在和(暂时)未来。
ZoneId
和ZoneOffset
类取代了TimeZone
。
以continent/region
的格式指定适当的时区名称,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。千万不要使用3-4个字母的缩写,如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
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.Date
、Calendar
、&SimpleDateFormat
。
JodaTime项目现在处于维护模式,建议迁移到java.Time类。
要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。
从哪里获得java.time类?
- Java SE 8、Java SE 9及更高版本
- 内置
- 标准Java API的一部分,带有捆绑实现
- Java 9添加了一些小功能和修复程序
- Java SE 6和Java SE 7
- 大部分Java.time功能都是向后移植到Java 6&7英寸ThreeTen背包
- Android
- java.time类的Android捆绑包实现的后续版本
- 对于早期的Android,ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…
ThreeTen Extra项目通过附加类扩展java.time。这个项目是将来可能添加到java.time的试验场。您可以在这里找到一些有用的类,如Interval
、YearWeek
、YearQuarter
等等。