首页 > 解决方案 > 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());
     }
}

标签: javajava-timedatetimeformatteroffsetdatetime

解决方案


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

即使对于小于或等于的单个n或任意数量的s,您也会得到相同的结果。但是,如果您超过,您将收到类似的异常n77

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模式中的数量,如果它小于或等于 之后的位数.,它将使用附加n来补偿,但如果ns 的数量超过位数,则不会有任何线索额外n的 s 是什么。

它不仅适用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", Locale.ENGLISH);
        System.out.println(LocalDate.parse(strDate2, 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

该符号n代表纳秒,纳秒等于99666670.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

S代表秒的分数,并被.9966667解析为0.9966667秒。

实施说明OffsetDateTime#toString

以最接近的倍数(即毫、微米和纳米)对秒OffsetDateTime#toString的小数位数进行分组,例如3

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

以下是摘录自OffsetDateTime#toString

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

  • uuuu-MM-dd'T'HH:mmXXXXXX
  • uuuu-MM-dd'T'HH:mm:ssXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSXXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXXXXX
  • uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX

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

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)));
    }
}

输出:

2021-06-30T23:59:59.009966667Z
2021-06-30T23:59:59.996666700Z

推荐阅读