【问题标题】: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 中的时区名称是否是跨平台的,但我希望如此!
  • 另一个对这个问题有用的答案stackoverflow.com/a/1449510/311525

标签: java dst datetimeoffset


【解决方案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

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

    示例代码:

    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 类?

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

    【讨论】:

      猜你喜欢
      • 2011-10-29
      • 2013-11-20
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 2013-05-25
      • 2015-04-13
      • 1970-01-01
      相关资源
      最近更新 更多