Joda-Time DateTime - 如何将一秒的分数设置为大于999的值?

时间:2014-03-27 13:59:14

标签: datetime jodatime

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

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

2 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:3)

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粒度,则任何生成的日期时间值将只有六位小数秒,后三位数为零。

enter image description here

解析示例

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

请注意,在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 | localDateTime:2013-06-08T12:46:44.412340 | zdt:2013-06-08T12:46:44.412340-04:00 [美国/蒙特利尔]