如何使用 DateTimeFormatter.ISO_LOCAL_DATE 打印日期?

How to print a date using DateTimeFormatter.ISO_LOCAL_DATE?

我想使用 DateTimeFormatter.ISO_LOCAL_DATE 来打印和解析日期。这就是我正在做的打印工作:

Date date;
String text = DateTimeFormatter.ISO_LOCAL_DATE.format(
  date.toInstant()
);

这就是我得到的:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
  at java.time.Instant.getLong(Instant.java:603)
  at java.time.format.DateTimePrintContext.getLong(DateTimePrintContext.java:205)
  at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
  at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543)
  at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
  at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1744)
  at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1718)

这是它的工作原理:

String text = DateTimeFormatter.ISO_LOCAL_DATE
  .withZone(ZoneId.of("UTC"))
  .format(date.toInstant());

发生这种情况是因为 Instant class 代表时间轴中的一个点:自 unix 纪元 (1970-01-01T00:00Z) 以来的纳秒数,没有任何时区概念 - 所以它不没有特定的 date/time(day/month/year、hours/minutes/seconds),因为它可以代表不同时区的不同日期和时间。

在格式化程序中设置特定区域,,将 Instant 转换为该区域(因此自纪元以来的纳秒数可以转换为特定日期和时间),使其成为可以格式化。

对于这种特定情况,您只需要 ISO8601 format 中的日期部分(日、月和年),因此一种替代方法是将 Instant 转换为 LocalDate 并且调用 toString() 方法。当您在格式化程序中设置 UTC 时,我使用相同的格式来转换它:

String text = date.toInstant()
    // convert to UTC
    .atZone(ZoneOffset.UTC)
    // get the date part
    .toLocalDate()
    // toString() returns the date in ISO8601 format
    .toString();

这 return 与 相同。当然对于其他格式,你应该使用格式化程序,但具体对于 ISO8601,你可以使用 toString() 方法。


您还可以将 Instant 转换为您想要的时区(在本例中为 UTC)并将其直接传递给格式化程序:

String text = DateTimeFormatter.ISO_LOCAL_DATE.format(
    date.toInstant().atZone(ZoneOffset.UTC)
);

唯一的区别是,当您在格式化程序中设置区域时,格式化时会将日期转换为该区域(当您不设置时,日期不转换)。