Java8 LocalDateTime 和 NANO_OF_SECOND 奇怪的格式

Java8 LocalDateTime and NANO_OF_SECOND strange formatting

我试试这个代码:

import java.time.*; 
...
   LocalDateTime now = LocalDateTime.now();
   DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
                                    "dd-MMM-yyyy  HH:mm:ss.n");
   System.out.format("Now = %s %n", now.format(formatter));

为了获得亚秒级信息的输出 Now = 12-Apr-2018 14:47:38.039578300

不幸的是,在每秒的前 100 毫秒内,亚秒信息的前导零被省略,我得到一个非常误导的输出 Now = 12-Apr-2018 14:47:38.39578300 ,很容易将其误解为大约 38.4 秒,或 396毫秒后整秒,而不是真正的 38.04 秒。

我找到的唯一解决方法是 ss.nnnnnnnnn 的格式,正好有 9 n,以获得我想要的输出。

编辑:

有更好的东西,我在发布这个问题时在这方面错过了。

我对纳秒不是很感兴趣,但秒的小数部分(大约 ms 分辨率)才是我真正想要的。

那这个更合适

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

大写的S表示亚秒数,当然包括前导零。

我认为没有比nnnnnnnnn更好的了。由于 per DateTimeFormatter docs 对于 n 模式,如果使用少于 9 个模式字母,前导零将被截断:

Fraction: Outputs the nano-of-second field as a fraction-of-second. The nano-of-second value has nine digits, thus the count of pattern letters is from 1 to 9. If it is less than 9, then the nano-of-second value is truncated, with only the most significant digits being output.

nN 是 DateTimeFormatter 唯一支持的纳米字段。

如果你只想要 ms 分辨率,你可以使用 S 而不是 n:

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("dd-MMM-yyyy  HH:mm:ss.SSS", Locale.US);

这将只打印前 3 个小数位(这是 ms 分辨率):

12-Apr-2018 14:47:38.039

请注意,我使用了 java.util.Locale 来定义要用于月份名称的语言。那是因为 JVM 可能并不总是设置为英语,结果可能不是您所期望的。例如:我的 JVM 设置为葡萄牙语,月份名称为“abr”。设置特定的语言环境可以消除这个问题。


要打印所有 9 位数字,使用 nnnnnnnnnSSSSSSSSS 都可以。


当我们 check the javadoc 时,我们可以看到为什么它会这样。 Sn 有不同的介绍:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
S       fraction-of-second          fraction          978
n       nano-of-second              number            987654321

S 分数 ,而 n 数字 。文档告诉你区别:

Number: If the count of letters is one, then the value is output using the minimum number of digits and without padding.

Fraction: Outputs the nano-of-second field as a fraction-of-second. The nano-of-second value has nine digits, thus the count of pattern letters is from 1 to 9. If it is less than 9, then the nano-of-second value is truncated, with only the most significant digits being output.

所以,只有 1 n 会打印没有填充的值(开头没有 0),导致你得到错误的输出,而 SSS 会给你正确的输出。

要更好地控制分数,您可以使用生成器,而不仅仅是模式字母。具体来说 appendFraction.

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
  .appendPattern("dd-MMM-yyyy  HH:mm:ss")
  .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
  .toFormatter();

模式字母"n"很少是你想要的。