Java OffsetDateTime.parse() 向时间添加额外的零

问题描述

以下代码返回一个 OffsetDateTime,如 2021-06-30T23:59:59.009966667Z,并添加了 2 个额外的零。我在格式化程序中有 7 个 n,但它仍然返回 9 位数字。为什么?

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class HelloWorld{

     public static void main(String []args){
         DateTimeFormatter MAIN_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnn XXX");
         String dbData = "2021-06-30 23:59:59.9966667 +00:00";
         OffsetDateTime time = OffsetDateTime.parse(dbData,MAIN_FORMATTER);
         System.out.println(time.toString());
     }
}

解决方法

以下代码返回这样的 OffsetDateTime 2021-06-30T23:59:59.009966667Z,添加了 2 个额外的零。我有 7 个 在格式化程序中,但它仍然返回 9 位数字。为什么?

即使对于单个 n 或小于或等于 n 的任意数量的 7,您也将获得相同的结果。然而,如果你超过 7,你会得到一个类似

的异常
Exception in thread "main" java.time.format.DateTimeParseException:
               Text '2021-06-30 23:59:59.9966667 +00:00' could not be parsed at index 20

这样做的原因是DateTimeFormatter计算模式中n的个数,如果小于或等于.后的位数,将使用额外的{ {1}} 来弥补这一点,但如果 n 的数量超过位数,它就不会知道额外的 n 是做什么用的。

它不仅适用于 n,而且适用于大多数(如果不是全部)符号。你可以从下面的例子中理解:

n

输出:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDate1 = "2020/2/2";
        String strDate2 = "2020/02/02";

        // Notice the single M and d
        DateTimeFormatter dtfCorrectForBothDateStrings = DateTimeFormatter.ofPattern("uuuu/M/d",Locale.ENGLISH);
        System.out.println(LocalDate.parse(strDate2,dtfCorrectForBothDateStrings));
        System.out.println(LocalDate.parse(strDate1,dtfCorrectForBothDateStrings));

        // Notice the two M's and d's
        DateTimeFormatter dtfCorrectOnlyForSecondDateString = DateTimeFormatter.ofPattern("uuuu/MM/dd",dtfCorrectOnlyForSecondDateString));
        System.out.println(LocalDate.parse(strDate1,dtfCorrectOnlyForSecondDateString));
    }
}

为什么它给我 2020-02-02 2020-02-02 2020-02-02 Exception in thread "main" java.time.format.DateTimeParseException: Text '2020/2/2' could not be parsed at index 5 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2051) at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1953) at java.base/java.time.LocalDate.parse(LocalDate.java:429) at Main.main(Main.java:16) 而不是 .009966667

符号 .9966667 代表 nano-of-secondn 纳秒等于 9966667 秒。

0.009966667

输出:

public class Main {
    public static void main(String[] args) {
        int nanos = 9966667;
        System.out.println(nanos + " nanoseconds = " + ((double) nanos / 1_000_000_000) + " second");
    }
}

它如何与 9966667 nanoseconds = 0.009966667 second 配合使用?

S 代表 fraction-of-secondS 被解析为 .9966667 秒。

关于 0.9966667 实现的说明:

OffsetDateTime#toStringfraction-of-second 的数字分组为最接近的 OffsetDateTime#toString 倍数(即毫、微和纳米),例如

  • 对于 3,输出将为 .99,并且
  • 对于 .990,输出将为 .996,并且
  • 对于 .996,输出将为 .9966,并且
  • 对于 .996600,输出将为.9966667

以下是.996666700的摘录:

输出将是以下 ISO-8601 格式之一:

  • uuuu-MM-dd'T'HH:mmXXXXX
  • uuuu-MM-dd'T'HH:mm:ssXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX

最终演示(包含上面讨论的所有内容):

OffsetDateTime#toString

输出:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2021-06-30 23:59:59.9966667 +00:00";

        System.out.println(OffsetDateTime.parse(strDateTime,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnn XXX",Locale.ENGLISH)));

        System.out.println(OffsetDateTime.parse(strDateTime,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS XXX",Locale.ENGLISH)));
    }
}