请查看您能否告诉我如何处理我的情况下的DST问题。
首先,我的应用程序是一个物流系统,适用于全局用户,因此涉及时区问题,在设置用户本地预订日期时,我将按以下方式进行处理:
1.当用户登录应用程序时,我们可以根据登录IP来获取用户的时区,但这只是一个偏移量(我不记得这些术语),例如“GMT + 08”(北京)或“GMT-06” (芝加哥) 。
2.在用户保存预订之前,我们需要设置预订本地日期,因为我无法直接获取用户本地日期。因此我将首先获取服务器日期(在我的情况下,这是北京时间),然后根据该日期计算本地日期服务器日期和用户时区,例如,如果用户时区为“GMT-08”,则服务器日期为2013-08-29 17:45:00。服务器时区为“GMT + 08”,那么我将使用服务器日期8-8,结果将为2013-08-29 01:45:00。但由于我不考虑DST,因此计算出的本地日期将为与实际日期有所不同。例如,现在在旧金山,实际的本地日期会比我使用这种方式计算的结果早一小时,
我发现Java TimeZone已经考虑了DST问题,但是在构造TimeZone时,我需要提供“位置”名称(例如US/Alaska,Pacific/Apia)。而就我而言,我所能得到的只是offset.So,您能告诉我如何解决我的情况下的DST问题吗?
最佳答案
是的,您应该在Java 8中使用Joda-Time或新的java.time包(受Joda-Time启发)。
偏移量是距UTC(GMT)的小时-分钟-秒数,它由某个日期时间值表示。西海岸是-08:00(忽略Daylight Saving Time废话),这意味着比世界标准时间晚8小时。
请注意,java.time在其初始发行版中存在一个小错误,即它无法处理仅数小时(例如+08
)而没有分钟(例如+08:00
)的偏移量。
time zone是过去,现在和将来更改特定区域的人们使用的偏移量的历史。
使用适当的time zone names(主要是大陆斜线城市)。避免使用既不是标准化也不是唯一的3或4个字母代码,例如EST。java.util.Date
没有时区,而Joda-Time DateTime
没有时区。
要获取网络浏览器的时区,请参阅this question。但是,通常情况下,这种方法效果不佳。您可能已经看到,许多网站都要求用户选择时区。
您的确切用例令人困惑。通常,最好的方法是使用UTC的日期时间值,然后根据需要调整为用户的本地时间。通常最适合您的软件以UTC的形式工作和存储日期时间。然后显示经过调整以适合用户的本地日期时间。换句话说,全局考虑(UTC),本地提出(已调整本地时区)。
通常,系统管理员会将其服务器计算机设置为UTC(无时区偏移)。如果您的操作系统(如Mac OS X)不提供UTC,请使用Reykjavik
,因为冰岛全年都使用UTC,且没有任何夏令时。同样,数据库引擎几乎总是将日期时间值转换为UTC进行存储。
当您真正不在乎时区或时间时,Joda-Time确实提供了LocalDate类。但是通常最好使用日期时间(DateTime实例),并根据需要设置仅日期字符串的格式。
Joda-Time 2.3中的示例代码。
DateTimeZone timeZoneChina = DateTimeZone.forID( "Asia/Shanghai" );
DateTime dateTimeChina = new DateTime( 2013, 8, 29, 17, 45, 00, timeZoneChina );
DateTime dateTimeUtc = dateTimeChina.withZone( DateTimeZone.UTC );
DateTime dateTimeParis = dateTimeChina.withZone( DateTimeZone.forID( "Europe/Paris" ) );
DateTimeZone timeZoneUsWestCoast = DateTimeZone.forID( "America/Los_Angeles" );
DateTime dateTimeUnitedStatesWestCoast = dateTimeChina.withZone( timeZoneUsWestCoast );
DateTimeFormatter formatter = ISODateTimeFormat.date();
String outputDateOnlyForUnitedStatesWestCoast = formatter.withZone( timeZoneUsWestCoast ).print( dateTimeUtc );
转储到控制台...
System.out.println( "dateTimeChina: " + dateTimeChina );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUnitedStatesWestCoast: " + dateTimeUnitedStatesWestCoast );
System.out.println( "outputDateOnlyForUnitedStatesWestCoast: " + outputDateOnlyForUnitedStatesWestCoast );
运行时...
dateTimeChina: 2013-08-29T17:45:00.000+08:00
dateTimeUtc: 2013-08-29T09:45:00.000Z
dateTimeParis: 2013-08-29T11:45:00.000+02:00
dateTimeUnitedStatesWestCoast: 2013-08-29T02:45:00.000-07:00
outputDateOnlyForUnitedStatesWestCoast: 2013-08-29
java.time
java.time中的类似代码。
UTC当前时刻。
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
调整为芝加哥地区的时区,产生一个
ZonedDateTime
对象。ZoneId zChicago = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdtChicago = instant.atZone( z ) ;
调整为中国时区。
ZoneId zShanghai = ZoneId.of( "Asia/Shanghai" ) ;
ZonedDateTime zdtShanghai = zdtChicago.withZoneSameInstant( zChicago ) ;
所有三个对象(
instant
,zdtChicago
和zdtShanghai
)表示时间轴上的相同时刻和相同点。同时进行,但通过各种挂钟时间可以看到。显然,出于某些目的,您只需要日期部分,而没有时间和时区。为此,提取一个
LocalDate
对象。LocalDate ld = zdtChicago.toLocalDate() ;
当然,该日期可能与
zdtShanghai.toLocalDate()
返回的日期不同。您可能需要构建一个特定的时刻。
ZonedDateTime zdtShanghai = ZonedDateTime.of( 2013, 8, 29, 17, 45, 0, 0 , zShanghai ) ;
位置和时区
你说:
i need to provide "location" name
位置与时区无关。来自魁北克的商人在日本东京旅行时可能想在
America/Montreal
区中查看特定的时间表。您可以向用户的Web浏览器或本地JVM询问其当前的默认时区。但最终,如果很关键,则必须与用户确认所需/预期的时区。
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如
java.util.Date
, Calendar
和 SimpleDateFormat
。要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310。
现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用兼容JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要
java.sql.*
类。 Hibernate 5和JPA 2.2支持java.time。在哪里获取java.time类?
关于java - 夏令时在Java中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18504174/