【问题标题】:Convert Time from one time zone to another using Java 8 Time使用 Java 8 Time 将时间从一个时区转换为另一个时区
【发布时间】:2015-04-30 08:31:20
【问题描述】:

我正在尝试将带有 GMT +5:30 的日期转换为带有 java 8 ZonedDateTimeEST

String inputDate = "2015/04/30 13:00";
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm", Locale.US);
LocalDateTime local = LocalDateTime.parse(inputDate, sourceFormatter);
// local : 2015-04-30T13:00
//Combining this local date-time with a time-zone to create a ZonedDateTime. 
ZonedDateTime zoned = local.atZone(TimeZone.getTimeZone("GMT+5:30").toZoneId());
// zoned : 2015-04-30T13:00+05:30[GMT+05:30]
ZonedDateTime zonedUS = zoned.withZoneSameInstant(TimeZone.getTimeZone("GMT-5:00").toZoneId());
// zonedUS : 2015-04-30T02:30-05:00[GMT-05:00]

我期待3:30 AM EST,但我得到的是2:30 AM EST1 PM IST= 3:30AM EST。我错过了什么?

【问题讨论】:

  • 嗯,这对我来说是正确的。 13:00+05:30 = 07:30 UTC = 02:30-05:00。您在 +05:30 和 -05:00 之间有 10:30 的差异,而 13:00-10:30 是 02:30... 为什么您会期待凌晨 03:30?请注意,东部时间目前是 UTC-4,因为它是美国东部时间而不是美国东部标准时间......所以当时纽约的时间例如是 03:30。
  • @JonSkeet 当我用谷歌搜索 time EST 时,它显示我在美国东部标准时间上午 3:30 下午 1:00 IST。是因为夏令时吗?
  • 如果您显示的内容实际上声称它是美国东部标准时间凌晨 3:30,那么您展示的内容就是不准确的。这可能意味着东部时间凌晨 3:30,而不是东部时间(实际上这就是谷歌搜索向我显示的内容)......东部时间始终是 UTC-5,而东部时间在东部时间 (UTC-5) 和东部时间 (UTC-4) 之间变化.如果您想要东部时间,您应该使用“America/New_York”的区域 ID。 (我通常建议使用基于位置的区域 ID,而不是一般的偏移 ID...)
  • @JonSkeet。感谢您对此question 的回答得到了解决方案
  • @Zeeshan 经验教训:避免使用那些 3-4 个字母的代码。使用proper time zone names。示例:America/New_YorkAmerica/Montreal

标签: java timezone


【解决方案1】:

在您指定 EST(东部标准时间)时,您发现的任何服务似乎都有助于解释您的意思和假定北美东部夏令时间 (EDT)。大多数(并非所有)使用 EST 作为标准时间的地方都在使用夏令时,因此在您使用的日期(2015 年 4 月 30 日)是 EDT 或偏移 UTC-04:00。

如果在您的情况下有意义,您应该始终喜欢以地区/城市格式提供时区,例如 Asia/Kolkata 和 America/New_York。如果您打算使用纽约或蒙特利尔的东部时间,可能会说您的“时区”GMT-5:00 是错误的,并且是导致意外结果的原因。

所以你的代码变成了例如:

    String inputDate = "2015/04/30 13:00";
    DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm", Locale.US);
    LocalDateTime local = LocalDateTime.parse(inputDate, sourceFormatter);
    // local : 2015-04-30T13:00
    //Combining this local date-time with a time-zone to create a ZonedDateTime. 
    ZonedDateTime zoned = local.atZone(ZoneId.of("Asia/Kolkata"));
    // zoned : 2015-04-30T13:00+05:30[Asia/Kolkata]
    ZonedDateTime zonedUS = zoned.withZoneSameInstant(ZoneId.of("America/Montreal"));
    // zonedUS : 2015-04-30T03:30-04:00[America/Montreal]

我做了另一项更改:当使用来自java.time 的现代类时,也使用过时的TimeZone 类是没有意义的,所以我把它去掉了。代码稍微简单一些,更重要的是,ZoneId.of(String) 包含对您的时区字符串的验证,因此您会发现时区名称中的任何拼写错误(就像我碰巧输入了 ( 而不是 /在亚洲/加尔各答——这种情况一直都在发生)。

Jon Skeet 和其他人已经在 cmets 中说过以上大部分内容。我认为它应该得到一个答案,所以很明显这个问题已经得到了回答。

【讨论】:

    【解决方案2】:

    虽然问题很老,但我觉得我可以在已接受的答案中添加更多内容。

    ZonedDateTimeOffsetDateTime 不同。

    我更喜欢使用ZonedDateTime 来获取特定地点的时间,例如“亚洲/加尔各答”、“亚洲/上海”、“美国/太平洋”(此时区会根据日期而有所不同由于夏令时而获得年度最佳)。

    举个例子来说明

    var pacific = ZonedDateTime.of(2020,11,01,1,59,0,0,ZoneId.of("US/Pacific"))
    var afterAnHour = pacific.plusHours(1)
    

    这会给我一个时间

    2020 年 11 月 1 日 01:59:00.000 AM -07:00[美国/太平洋]

    如果我增加一个小时,它会给我一个时间

    2020-11-01 01:59:00.000 AM -08:00[美国/太平洋]

    即使在时间上增加了一个小时,您也可以看到小时部分是相同的。这是因为夏令时开始,时区从 -07:00 转移到 -08:00

    现在如果我使用OffsetDateTime 看看会发生什么。

    var offsetNow = OffsetDateTime.of(2020,11,01,1,59,0,0,ZoneOffset.of("-07:00"))
    var offsetAfterAnHour = offsetNow.plusHours(1)
    

    offsetNow 将是,

    2020 年 11 月 1 日 01:59:00.000 -07:00

    再加上一个小时,

    2020 年 11 月 1 日 02:59:00.000 -07:00

    你可以看到小时分量在增加一个小时后变成了2

    关键是ZonedDateTime 使用ZoneRules 来计算夏令时等重要属性,以便它可以相应地调整时区。

    虽然OffsetDateTime 不会更改任何区域的偏移量。

    【讨论】:

      猜你喜欢
      • 2014-02-11
      • 2019-06-19
      • 2012-01-30
      • 2015-05-06
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      相关资源
      最近更新 更多