java - 夏令时在Java中

标签 java datetime timezone

请查看您能否告诉我如何处理我的情况下的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 ) ;

所有三个对象(instantzdtChicagozdtShanghai)表示时间轴上的相同时刻和相同点。同时进行,但通过各种挂钟时间可以看到。

显然,出于某些目的,您只需要日期部分,而没有时间和时区。为此,提取一个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询问其当前的默认时区。但最终,如果很关键,则必须与用户确认所需/预期的时区。

Table of date-time types in Java, both modern and legacy

关于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 SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。
  • Java 9添加了一些次要功能和修复。
  • Java SE 6Java SE 7
  • 大部分java.time功能都在ThreeTen-Backport中反向移植到Java 6和7。
  • Android
  • 更高版本的java.time类的Android捆绑实现。
  • 对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。参见How to use ThreeTenABP…
  • 关于java - 夏令时在Java中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18504174/

    相关文章:

    java - sql "between statement"不适用于 spring

    java - UTC Unix 时间戳存储在错误时区的 Java 程序中的 HSQLDB 中

    java - 重启后恢复报警计数器

    java - RxJava 中的指数退避

    java - 在我自己的项目中使用jrawio,导致错误

    python - 开始和结束时间到日期时间的字符串

    r - R 中的日期时间/日期操作

    python - python中的时间格式

    javascript - 将 Javascript 日期转换为带有时区信息的 UTC

    javascript - 如何通过 Node 调度模块在特定时区的任何时间调度作业