【问题标题】:How to print a date using DateTimeFormatter.ISO_LOCAL_DATE?如何使用 DateTimeFormatter.ISO_LOCAL_DATE 打印日期?
【发布时间】:2017-10-18 08:04:22
【问题描述】:

我想使用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$1.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)

【问题讨论】:

  • 这对我有用
  • 在 Java 1.8 中工作正常
  • 我的错,更新了问题,它正在打印,而不是解析

标签: java date java-8 date-formatting java-time


【解决方案1】:

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

在格式化程序like you did 中设置特定区域,将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();

这返回与your formatter 相同的内容。当然对于其他格式,你应该使用格式化程序,但对于 ISO8601,你可以使用toString() 方法。


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

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

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

【讨论】:

    【解决方案2】:

    这就是它的工作原理:

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

    【讨论】:

    • 代替ZoneId.of("UTC"),你也可以使用内置常量ZoneOffset.UTC。根据javadoc,它们是等价的:"如果区域 ID 等于 'GMT'、'UTC' 或 'UT',则结果是具有相同 ID 和规则的 ZoneId 等效于 ZoneOffset.UTC"
    猜你喜欢
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 2014-08-01
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多