【问题标题】:Java8 LocalDateTime and NANO_OF_SECOND strange formattingJava8 LocalDateTime 和 NANO_OF_SECOND 奇怪的格式
【发布时间】:2018-04-12 13:32:16
【问题描述】:

我试试这个代码:

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,以获得我想要的输出。

编辑

有一些更好的东西,我在发布这个问题时错过了这个区域。

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

那么,这个更合适

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

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

【问题讨论】:

  • 好的,有什么问题?
  • 如果编辑回答了问题,您可以添加答案并回滚编辑。
  • Stackexchange 吓到我了:“你真的想回答你自己的问题吗?不如编辑问题怎么样?”所以剩下的问题是关于.n.S之间的区别@jonpebs已经提供了答案,所以我不需要自己再给它了。
  • 新用户有时会发布他们的 cmets 作为答案,这是不希望的。我想这就是为什么在那里给出警告信息的原因。欢迎回答自己的问题,这并不罕见。

标签: java datetime java-8 datetime-format java-time


【解决方案1】:

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

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

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

2018 年 4 月 12 日 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 是一个数字。文档告诉您区别:

数字:如果字母数为一个,则使用最小位数不输出该值填充

分数:将纳秒字段输出为秒的分数。纳秒值有九位,因此模式字母的计数是从 1 到 9。如果小于 9,则纳秒值被截断只输出最高有效数字

所以,只有 1 个n 将打印没有填充的值(开头没有0),导致您得到错误的输出,而SSS 将为您提供正确的输出。

【讨论】:

    【解决方案2】:

    为了更好地控制分数,您可以使用构建器,而不仅仅是模式字母。特别是appendFraction

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

    模式字母“n”很少是您想要的。

    【讨论】:

      【解决方案3】:

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

      分数:将纳秒字段输出为秒的分数。 纳秒值有九位数字,因此模式的计数 字母是从 1 到 9。如果小于 9,则纳秒 值被截断,只有最重要的数字是 输出。

      nN 是 DateTimeFormatter 支持的唯一 nano 字段。

      【讨论】:

      • 谢谢。但我注意到 .S 格式模式为时已晚。这可能是我所追求的:第二位数的分数。
      • 为了澄清,n 符号的表示是number(在文档中)。所以,你提到Fraction 的规则不适用于n
      最近更新 更多