【问题标题】:Joda-Time DateTime - How to set fraction of a second to value bigger than 999?Joda-Time DateTime - 如何将秒的分数设置为大于 999 的值?
【发布时间】:2014-03-27 13:59:14
【问题描述】:

是否有可能正确设置秒的分数,而不是毫秒。

我尝试使用模式 yyyy.MM.dd H:mm:ss.SSSSS 解析日期 2013.06.08 12:46:44.41234 ,输出为: 2013.June.08 12:46:44:41200 :下午。

【问题讨论】:

    标签: datetime jodatime


    【解决方案1】:

    Joda-Time 仅将日期/时间值存储到毫秒 - 就像 java.util.Datejava.util.Calendar。所以不,你不可能在第二秒内精确地表示 412340 微秒(这是你的文本表示所显示的)。

    Java 8 中的 java.time 包具有 nanosecond 粒度 - 如果您可以改用它,应该没问题。

    【讨论】:

      【解决方案2】:

      tl;博士

      LocalDateTime ldt = 
          LocalDateTime.parse( "2013.06.08 12:46:44.123456789".replace( " " , "T" ) ) ;
      

      java.time

      正如 Jon Skeet 的 correct accepted Answer 所说,Java 8 及更高版本中的新 java.time 框架支持分辨率高达 nanosecond 的日期时间值。这意味着最多九位小数秒。

      警告:在 Java 8 中,Clock 接口的默认实现与旧日期时间类中使用的旧当前时间代码相同。旧的实现仅限于millisecond 分辨率。因此,在 java.time 中,您可以存储以纳秒为单位的日期时间值,但您只能获取以毫秒为单位的当前时刻。

      Java 9 中的新时钟

      Java 9 有一个新的默认 Clock 实现,具有更精细的粒度。请参阅 OpenJDK 问题,Increase the precision of the implementation of java.time.Clock.systemUTC()

      该问题已标记为已修复并已解决。也许新的默认 Clock 实现可能在 Java 9 OpenJDK 的早期预发行版中处于活动状态。

      硬件时钟

      请记住,即使使用新的更精细的Clock 实现,您的结果也可能因计算机而异。 Java 依靠底层计算机硬件的时钟来了解当前时刻。这种硬件时钟的分辨率和精度差别很大。例如,如果特定计算机的硬件时钟仅支持 microseconds 粒度,则任何生成的日期时间值都将只有六位小数秒,最后三位为零。

      解析示例

      让我们解析问题中给出的字符串。

      请注意,在 java.time 中,格式化程序编码的解析模式字符串不适用于可变数量的小数秒位数。请参阅此问题,JSR-310 - parsing seconds fraction with variable length 进行讨论。

      解决方案是使用DateTimeFormatterBuilder 对象来表示我们期望小数秒内有任意数量的零、一位或多位数字(最多九位)。

      String input = "2013.06.08 12:46:44.41234";
      DateTimeFormatter formatter = new DateTimeFormatterBuilder ()
              .appendPattern ( "yyyy.MM.dd HH:mm:ss" )
              .appendFraction ( ChronoField.NANO_OF_SECOND , 0 , 9 , true ) // Nanoseconds = 0-9 digits of fractional second.
              .toFormatter ();
      

      我们的输入字符串既没有offset-from-UTC 也没有time zone。所以我们必须将其解析为LocalDateTime,这意味着任何(或没有特定的)位置。

          LocalDateTime localDateTime = LocalDateTime.parse ( input , formatter );
      

      LocalDateTime 没有实际意义。这不是时间线上的确切时刻。这是一个关于的想法。要将其确定为确切的时刻,我们必须应用时区。我们必须应用生成该输入字符串的人预期的时区。在这个问题的情况下,意图没有说明。所以我随意选择蒙特利尔作为例子。

          ZoneId zoneId = ZoneId.of ( "America/Montreal" );
          ZonedDateTime zdt = localDateTime.atZone ( zoneId );
      

      转储到控制台。

      System.out.println ( "input: " + input + " | localDateTime: " + localDateTime + " | zdt: " + zdt );
      

      输入:2013.06.08 12:46:44.41234 |本地日期时间:2013-06-08T12:46:44.412340 | zdt: 2013-06-08T12:46:44.412340-04:00[美国/蒙特利尔]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 2013-02-26
        • 2023-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多