如何使用Java 8库将UTC日期时间转换为另一个时区?

时间:2019-01-09 10:48:32

标签: java datetime java-8

final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
    Instant.ofEpochMilli(rawDateTime.getTime()), zoneId); 
// here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]

final ZonedDateTime zonedDateTime1 = 
ZonedDateTime.of(rawDateTime.toLocalDateTime(), zoneId);
// here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]

但是我想将转换后的日期时间设为2031-04-26 00:00:00 + 5:30,因为我的时间戳记值位于UTC时区。

请帮助。

3 个答案:

答案 0 :(得分:7)

首先,您不应该使用Timestamp。您可以使用DateTimeFormatter解析为LocalDateTime

然后您将LocalDateTime划分为UTC,然后再使用ZonedDateTime.withZoneSameInstant转换为加尔各答区域。

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .appendLiteral(' ')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter();

LocalDateTime localDateTime = LocalDateTime.parse("2031-04-25 18:30:00", formatter);
ZoneId calcuttaZone = ZoneId.of("Asia/Calcutta");
ZonedDateTime calcuttaZonedDateTime = localDateTime.atZone(ZoneOffset.UTC)
    .withZoneSameInstant(calcuttaZone);

答案 1 :(得分:2)

请使用OffsetDateTime,而不是ZonedDateTime命名的区域具有(超时)国家标准(例如,夏令时)。

OffsetDateTime utc = OffsetDateTime.parse("2031-04-25T18:30:00Z");
OffsetDateTime asia = utc.withOffsetSameInstant(ZoneOffset.ofHoursMinutes(5, 30));

默认解析是针对ISO格式的。

  • Z表示零,UTC,+ 0:00。
  • 最终的默认格式为2031-04-26T00:00+05:30

在Ole V.V.评论后

如果涉及夏季时间,则上述情况尤其容易出错,例如中欧时间的偏移+1:00和+2:00。

Instant raw = Instant.parse("2031-04-25T18:30:00Z");
ZonedDateTime zoned = raw.atZone(ZoneId.of("Asia/Calcutta"));
OffsetDateTime offset = OffsetDateTime.from(zoned);

答案 2 :(得分:1)

使用DateTimeFormatter格式化ZonedDateTime:

    final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
    final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
    final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
            Instant.ofEpochMilli(rawDateTime.getTime()), zoneId);
    // here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[XXX]");
    System.out.println(formatter.format(zonedDateTime));

    final ZonedDateTime zonedDateTime1 =
            ZonedDateTime.of(rawDateTime.toLocalDateTime(), zoneId);
    // here we are getting output as 2031-04-25T18:30+05:30[Asia/Calcutta]
    System.out.println(formatter.format(zonedDateTime1));

输出:

2031-04-25 23:00:00+05:30
2031-04-25 18:30:00+05:30

已编辑:根据@Ole V.V.的评论-在采用以下格式之前,必须将本地日期时间转换为zonedatetime:

 final Timestamp rawDateTime = Timestamp.valueOf("2031-04-25 18:30:00");
        LocalDateTime ldt = rawDateTime.toLocalDateTime();
        final ZoneId zoneId = ZoneId.of("Asia/Calcutta");
        ZonedDateTime zdt = ldt.atZone(ZoneId.of("UTC"))
                .withZoneSameInstant(zoneId);


        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[XXX]");
        System.out.println(formatter.format(zdt));

这将给出输出:

2031-04-26 00:00:00+5:30