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

时间:2018-06-07 19:32:36

标签: java date datetime java-8 utc

我目前的日期:
日期utc: 2018-06-06T16:30:00Z (ISO 8601 in UTC)
OR
日期iso: 2018-06-06T11:30:00-05:00 (ISO 8601)
OR
日期: 1528302600000 (大纪元/ Unix时间戳)

我希望将上述日期时间转换为其他时区(如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;
}

2 个答案:

答案 0 :(得分:4)

自问题被标记为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.of("+05:30")ZoneId,例如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方法与1528302600000一起使用 将parse()方法与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); 一起使用。
然后使用ofEpochMilli()转换为您想要的时区。

演示

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 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));

要以人格式打印结果,请使用atZone()

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

输出

unstash name: 'stash_name'

答案 1 :(得分:1)

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

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

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