Java 8 LocalDateTime 和 ZonedDateTime 的转换

Java 8 LocalDateTime and ZonedDateTime conversion

给定区域名称和 outputDtf,这是使用 Java 8 LocalDateTime 和 ZonedDateTime 的最佳方式吗?我想尽可能简化。

String zoneName = "America/Los_Angeles";
DateTimeFormatter outputDtf = DateTimeFormatter
        .ofPattern("yyyy-MM-dd'T'HH:mm:ssZ")
        .withZone(ZoneId.of(zoneName));

// timestamp in UTC. convert to zone America/Los_Angeles
DateTimeFormatter timestampDtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
String timestamp = "20180722060602";
LocalDateTime ldt = LocalDateTime.parse(timestamp, timestampDtf);
Instant tsInstant = ldt.atZone(ZoneId.of("UTC")).toInstant();
System.out.println(outputDtf.format(tsInstant));
// 2018-07-21T23:06:02-0700

// date in zone America/Los_Angeles. add start of day and zone
DateTimeFormatter dateDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String date = "2018-07-18";
ZonedDateTime zdt = LocalDate.parse(date, dateDtf).atStartOfDay().atZone(ZoneId.of(zoneName));
System.out.println(outputDtf.format(zdt));
// 2018-07-18T00:00:00-0700

除了去掉第一个例子中的toInstant(),没有什么可以简化的了。

您必须解析输入的字符串,必须指定时区,对于仅限日期的日期,您必须说是午夜。

这些是您正在执行的步骤,无法简化,但您可以让 DateTimeFormatter 完成工作。

String zoneName = "America/Los_Angeles";
DateTimeFormatter outputDtf = DateTimeFormatter
        .ofPattern("yyyy-MM-dd'T'HH:mm:ssZ")
        .withZone(ZoneId.of(zoneName));

// timestamp in UTC. convert to zone America/Los_Angeles
DateTimeFormatter timestampDtf = DateTimeFormatter
        .ofPattern("yyyyMMddHHmmss")
        .withZone(ZoneOffset.UTC);
String timestamp = "20180722060602";
ZonedDateTime zdt1 = ZonedDateTime.parse(timestamp, timestampDtf);
System.out.println(outputDtf.format(zdt1)); // 2018-07-21T23:06:02-0700

// date in zone America/Los_Angeles. add start of day and zone
DateTimeFormatter dateDtf = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd")
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .toFormatter()
        .withZone(ZoneId.of(zoneName));
String date = "2018-07-18";
ZonedDateTime zdt2 = ZonedDateTime.parse(date, dateDtf);
System.out.println(outputDtf.format(zdt2)); // 2018-07-18T00:00:00-0700

可以看到,如果把DateTimeFormatter设置一次再使用,代码using就更简单了,但是总体来说代码并不简单.

您的代码总体上还不错,您可以做得更好。

在第一个片段中我会使用 OffsetDateTime 而不是 Instant:

    OffsetDateTime tsOffsetDateTime = ldt.atOffset(ZoneOffset.UTC);
    System.out.println(outputDtf.format(tsOffsetDateTime));

您不需要第二个代码段中的格式化程序,因为您的字符串 2018-07-18LocalDate(又名 ISO 8601)的默认格式:

    ZonedDateTime zdt = LocalDate.parse(date).atStartOfDay().atZone(zone);

Link: Wikipedia article: ISO 8601