使用Java 8 Time将时间从一个时区转换为另一个时区

时间:2015-04-30 08:31:21

标签: java timezone

我正在尝试使用java GMT +5:30将日期转换为ESTZonedDateTime

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 EST 1 PM IST= 3:30AM EST。我错过了什么?

2 个答案:

答案 0 :(得分:3)

在您指定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和其他人在评论中已经说过上述大部分内容。我认为它应该得到一个答案,所以很清楚地看到问题已得到解答。

答案 1 :(得分:0)

尽管这个问题很旧,但我想我可以在接受的答案中添加更多内容。

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月1日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不会更改任何区域的区域偏移。

相关问题