繁体   English   中英

如何将ISO 8601格式的DateTime转换为Java中的另一个时区?

[英]How to convert ISO 8601 formatted DateTime to another time zone in Java?

我当前的日期:
日期UTC: 2018-06-06T16:30:00Z (UTC中的ISO 8601)
要么
日期ISO: 2018-06-06T11:30:00-05:00 (ISO 8601)
要么
日期时代: 1528302600000 (Epoch / Unix时间戳)

我希望将上面的DateTime转换为其他时区(例如GMT + 5:30)。 我不确定从上述三种时间中会收到哪种时间格式。 因此,我是否可以使用一个通用方法将上面的代码转换为另一个时区,并在Java 8中返回java.util.Date?

我做了这样的事情,但是没有成功

public Date convertDateToLocalTZ(Date iso8601, ZoneId toZoneId) {
    Date dateTime = null;
    if (iso8601 != null && toZoneId != null) {
        Instant instant = iso8601.toInstant();
        LocalDateTime localDateTime = instant.atZone(toZoneId).toLocalDateTime();
        dateTime = Date.from(localDateTime.atZone(toZoneId).toInstant());
        return dateTime;
    }
    return dateTime;
}

由于问题被标记为java-8使用java.time API。


更新 :对于问题的第4版,其中添加了2018-06-06T11:30:00-05:00

要解析1528302600000 ,您可以将其解析为long ,然后使用Instant.ofEpochMilli()

要解析类似2018-06-06T11:30:00-05:00的格式,可以使用OffsetDateTimeZonedDateTime 两者都可以解析2018-06-06T16:30:00Z

要将时区专门更改为特定的偏移量(例如GMT+5:30 ZoneOffset ,请使用ZoneOffset (例如ZoneOffset.of("+05:30")ZoneId (例如ZoneId.of("GMT+05:30") ZoneOffset.of("+05:30") ZoneId.of("GMT+05:30")
注意1: GMT+5:30无效。
注意2:要更改区域的时区并遵守夏令时,请使用例如ZoneId.of("Asia/Kolkata")

要解析所有3种输入格式,甚至支持扩展格式,如2018-06-06T11:30-05:00[America/Chicago] ,请使用ZonedDateTime ,并对历元数进行特殊处理。

public static ZonedDateTime parseToZone(String text, ZoneId zone) {
    if (text.indexOf('-') == -1)
        return Instant.ofEpochMilli(Long.parseLong(text)).atZone(zone);
    return ZonedDateTime.parse(text).withZoneSameInstant(zone);
}

然后,调用者可以使用toOffsetDateTime()将其转换为OffsetDateTime ,从而决定是否仅使用偏移量而不是整个时区。

测试

ZoneId india = ZoneId.of("Asia/Kolkata");

System.out.println(parseToZone("2018-06-06T16:30:00Z", india));
System.out.println(parseToZone("2018-06-06T11:30:00-05:00", india));
System.out.println(parseToZone("1528302600000", india));

System.out.println(parseToZone("1528302600000", india).toOffsetDateTime());

输出量

2018-06-06T22:00+05:30[Asia/Kolkata]
2018-06-06T22:00+05:30[Asia/Kolkata]
2018-06-06T22:00+05:30[Asia/Kolkata]
2018-06-06T22:00+05:30

原始答案

2018-06-06T16:30:00Z使用parse()方法。
使用带有1528302600000ofEpochMilli()方法。
然后使用atZone()转换为所需的时区。

演示版

Instant instant1 = Instant.parse("2018-06-06T16:30:00Z");
Instant instant2 = Instant.ofEpochMilli(1528302600000L);

ZoneId india = ZoneId.of("Asia/Kolkata");
ZonedDateTime date1 = instant1.atZone(india);
ZonedDateTime date2 = instant2.atZone(india);

System.out.println(instant1);
System.out.println(instant2);
System.out.println(date1);
System.out.println(date2);

输出量

2018-06-06T16:30:00Z
2018-06-06T16:30:00Z
2018-06-06T22:00+05:30[Asia/Kolkata]
2018-06-06T22:00+05:30[Asia/Kolkata]

要以人工格式打印结果,请使用DateTimeFormatter

DateTimeFormatter indiaFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                                    .withLocale(Locale.forLanguageTag("en-IN"));
DateTimeFormatter hindiFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
                                                    .withLocale(Locale.forLanguageTag("hi-IN"));
System.out.println(date1.format(indiaFormatter));
System.out.println(date1.format(hindiFormatter));

输出量

6 June 2018 at 10:00:00 PM IST
6 जून 2018 को 10:00:00 अपराह्न IST

在Java 8+中,应该使用新的java.time API。

您的初始UTC时间必须建模为“即时”。 如果需要,可以使用DateTimeFormatter从类似2018-06-07T22:21:00Z的字符串中进行解析,或者使用Instant.now获取当前的Instant。

然后,您可以使用Instant.atZone或Instant.withOffset转换为ZonedDateTime响应。 具有所需时移的OffsetDateTime。 ZonedDateTime可以帮助您获取给定地区/国家/地区的日期/时间,而OffsetDateTime可以进行纯粹的数字时移,而与位置和夏令时无关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM