使用 Java 8 Time 将时间从一个时区转换为另一个时区
Convert Time from one time zone to another using Java 8 Time
我正在尝试将 GMT +5:30
的日期转换为 java 的 EST
8 ZonedDateTime
.
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
。我错过了什么?
您找到的任何服务似乎都对解释您的意思和在您指定 EST(东部标准时间)时假定的北美东部夏令时 (EDT) 有过度帮助。大多数(并非所有)使用 EST 作为标准时间的地方都使用夏令时,因此在您使用的日期(2015 年 4 月 30 日)处于 EDT 或偏移 UTC-04:00。
如果在您的情况下有意义,您应该始终更喜欢以 region/city 格式提供时区,如 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
的现代 classes 时,也没有必要同时使用过时的 TimeZone
class,所以我已经把它拿出来了。代码稍微简单一些,更重要的是,ZoneId.of(String)
包含对时区字符串的验证,因此您会发现时区名称中的任何拼写错误(就像我刚好输入 (
而不是Asia/Kolkata 中的 /
— 这种情况经常发生)。
以上大部分内容已在 Jon Skeet 和其他人的评论中提及。我认为它应该得到一个答案,所以很明显看到这个问题已经被回答了。
虽然这个问题很老,但我觉得我可以在接受的答案中添加更多内容。
ZonedDateTime
不同于 OffsetDateTime
。
我更愿意使用 ZonedDateTime
来获取特定位置的时间,例如“Asia/Kolkata”、“Asia/Shanghai”、“US/Pacific” (由于夏令时,这个时区会根据一年中的某一天发生变化)。
举例说明,
var pacific = ZonedDateTime.of(2020,11,01,1,59,0,0,ZoneId.of("US/Pacific"))
var afterAnHour = pacific.plusHours(1)
这将给我一个
的时间
2020-November-01 01:59:00.000 AM -07:00[US/Pacific]
如果我加一个小时,它会给我一个
的时间
2020-November-01 01:59:00.000 AM -08:00[US/Pacific]
你可以看到,即使在时间上加上一个小时,小时部分还是一样的。这是因为夏令时已经开始,时区从 -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-November-01 01:59:00.000 -07:00
再加上一个小时,
2020-November-01 02:59:00.000 -07:00
可以看到加了一个小时后,小时分量变成了2
关键点是 ZonedDateTime
使用 ZoneRules
计算夏令时等重要属性,以便它可以相应地调整时区。
虽然 OffsetDateTime
不会更改任何区域偏移量。
我正在尝试将 GMT +5:30
的日期转换为 java 的 EST
8 ZonedDateTime
.
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
。我错过了什么?
您找到的任何服务似乎都对解释您的意思和在您指定 EST(东部标准时间)时假定的北美东部夏令时 (EDT) 有过度帮助。大多数(并非所有)使用 EST 作为标准时间的地方都使用夏令时,因此在您使用的日期(2015 年 4 月 30 日)处于 EDT 或偏移 UTC-04:00。
如果在您的情况下有意义,您应该始终更喜欢以 region/city 格式提供时区,如 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
的现代 classes 时,也没有必要同时使用过时的 TimeZone
class,所以我已经把它拿出来了。代码稍微简单一些,更重要的是,ZoneId.of(String)
包含对时区字符串的验证,因此您会发现时区名称中的任何拼写错误(就像我刚好输入 (
而不是Asia/Kolkata 中的 /
— 这种情况经常发生)。
以上大部分内容已在 Jon Skeet 和其他人的评论中提及。我认为它应该得到一个答案,所以很明显看到这个问题已经被回答了。
虽然这个问题很老,但我觉得我可以在接受的答案中添加更多内容。
ZonedDateTime
不同于 OffsetDateTime
。
我更愿意使用 ZonedDateTime
来获取特定位置的时间,例如“Asia/Kolkata”、“Asia/Shanghai”、“US/Pacific” (由于夏令时,这个时区会根据一年中的某一天发生变化)。
举例说明,
var pacific = ZonedDateTime.of(2020,11,01,1,59,0,0,ZoneId.of("US/Pacific"))
var afterAnHour = pacific.plusHours(1)
这将给我一个
的时间2020-November-01 01:59:00.000 AM -07:00[US/Pacific]
如果我加一个小时,它会给我一个
的时间2020-November-01 01:59:00.000 AM -08:00[US/Pacific]
你可以看到,即使在时间上加上一个小时,小时部分还是一样的。这是因为夏令时已经开始,时区从 -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-November-01 01:59:00.000 -07:00
再加上一个小时,
2020-November-01 02:59:00.000 -07:00
可以看到加了一个小时后,小时分量变成了2
关键点是 ZonedDateTime
使用 ZoneRules
计算夏令时等重要属性,以便它可以相应地调整时区。
虽然 OffsetDateTime
不会更改任何区域偏移量。