确定夏令时 (DST) 在 Java 中是不是在指定日期处于活动状态

Posted

技术标签:

【中文标题】确定夏令时 (DST) 在 Java 中是不是在指定日期处于活动状态【英文标题】:Determine Whether Daylight Savings Time (DST) is Active in Java for a Specified Date确定夏令时 (DST) 在 Java 中是否在指定日期处于活动状态 【发布时间】:2010-11-06 19:47:31 【问题描述】:

我有一个 Java 类,它接受一个位置的纬度/经度,并在夏令时打开和关闭时返回 GMT 偏移量。我正在寻找一种简单的方法来确定当前日期是否在夏令时,以便在 Java 中应用正确的偏移量。目前我只对美国时区执行此计算,但最终我也想将其扩展到全球时区。

【问题讨论】:

目前我正在使用 GeoTools 库和美国国家地图集 (nationalatlas.gov/mld/timeznp.html) 提供的 shapefile 检索时区信息。幸运的是,这为我提供了一些额外的信息——主要是 2 位或 4 位数字的时区符号(即 AL、EA、EAno 等)。不幸的是,这个值与 Java 时区使用的值不对应,尽管我可以手动执行这个映射。理想情况下,如果我用世界时区 shapefile 替换此文件,我想要一个可行的解决方案,但这可能过于雄心勃勃。 timeznp020.txt 列出了Enumerated_Domains,其中包括使用的每个缩写的详细信息;将它们映射到 zoneinfo 时区名称应该不会太难。我不确定 Java 中的时区名称是否是跨平台的,但我希望如此! 另一个对这个问题有用的答案***.com/a/1449510/311525 ***.com/questions/10545960/… 【参考方案1】:

这是提出问题的机器的答案:

TimeZone.getDefault().inDaylightTime( new Date() );

试图为客户端解决这个问题的服务器将需要客户端的时区。原因见@Powerlord 回答。

对于任何特定的时区

TimeZone.getTimeZone( "US/Alaska").inDaylightTime( new Date() );

【讨论】:

我一直在解决同样的问题。我还没有找到世界时区的形状文件。 不过,我们不知道这是桌面应用还是网络应用。 Web 应用无法访问客户端上的时区信息。 android:需要 API 级别 24【参考方案2】:
TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());

【讨论】:

应避免使用后面的三个缩写,如 EST(表示标准时间),因为它们与 DST 无关。请改用时区 ID。 @Tiny 比这更令人困惑的是:其中一些对 DST 敏感,一些则不是。避免它们的所有理由。 (2021年我们也应该避免使用老式的TimeZone类,使用ZoneId)。【参考方案3】:

您将不得不使用这些坐标做更多的工作并确定它们所在的时区。一旦您知道是哪个时区,isDayLight() 方法就会很有用。

例如,您无法判断 -0500 是 EST(美国/加拿大东部标准时间)、CDT(美国/加拿大中部夏令时间)、COT(哥伦比亚时间)、AST(巴西英亩标准时间)、 ECT(厄瓜多尔时间)等...

其中一些可能支持也可能不支持夏令时。

【讨论】:

【参考方案4】:

Joda Time 包含将为您计算偏移量的处理方法。见DateTimeZone.convertLocalToUTC(...)

为了补充这一点,您需要使用您的纬度/经度信息查找当前时区。 GeoNames 为其 Web 服务提供了一个 java 客户端,以及一个简单的 Web 请求框架(即 http://ws.geonames.org/timezone?lat=47.01&lng=10.2)

【讨论】:

我之前研究过 GeoNames 网络服务,我知道它将完成我想要做的事情。不幸的是,此代码将托管在可能位于防火墙后面的服务器上,因此我尽量避免外部 Web 服务调用。对于没有此限制的用户,GeoNames 网络服务将是一个很好的解决方案。【参考方案5】:

tl;博士

ZoneId.of( "America/Montreal" )  // Represent a specific time zone, the history of past, present, and future changes to the offset-from-UTC used by the people of a certain region.  
      .getRules()                // Obtain the list of those changes in offset. 
      .isDaylightSavings(        // See if the people of this region are observing Daylight Saving Time at a specific moment.
          Instant.now()          // Specify the moment. Here we capture the current moment at runtime. 
      )                          // Returns a boolean.

java.time

这是mamboking 的correct Answer 的现代java.time(参见Tutorial)版本。

ZoneId 代表一个时区。该类知道判断DST 是否适用于a particular time zone 的规则。 ZoneRules 类为时区的所有历史和未来转换建模。 Instant 是UTC 时间线上的一个时刻。 ZonedDateTime 是将ZoneId 应用于Instant 的结果。

示例代码:

ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
ZoneId z = now.getZone();
ZoneRules zoneRules = z.getRules();
Boolean isDst = zoneRules.isDaylightSavings( now.toInstant() );

请注意,在最后一行中,我们必须通过简单调用 toInstantZonedDateTime 对象中提取 Instant 对象。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

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

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 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 (ThreeTenABP 项目适应 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

以上是关于确定夏令时 (DST) 在 Java 中是不是在指定日期处于活动状态的主要内容,如果未能解决你的问题,请参考以下文章

确定 DST 是不是对给定 time_t 的指定时区有效

检查夏令时是不是生效

当时间需要在本地时间保持不变时,在 Java 中使用 OffsetDateTime 处理夏令时,而不管 DST

您如何确定 VBA 中的夏令时?

Java 为啥 Calendar.get(Calendar.DST_OFFSET) 在夏令时给出 0?

有没有办法检查它是不是是 UTC 的 DST(夏令时)?