【发布时间】: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 :下午。
【问题讨论】:
是否有可能正确设置秒的分数,而不是毫秒。
我尝试使用模式 yyyy.MM.dd H:mm:ss.SSSSS 解析日期 2013.06.08 12:46:44.41234 ,输出为: 2013.June.08 12:46:44:41200 :下午。
【问题讨论】:
Joda-Time 仅将日期/时间值存储到毫秒 - 就像 java.util.Date 和 java.util.Calendar。所以不,你不可能在第二秒内精确地表示 412340 微秒(这是你的文本表示所显示的)。
Java 8 中的 java.time 包具有 nanosecond 粒度 - 如果您可以改用它,应该没问题。
【讨论】:
LocalDateTime ldt =
LocalDateTime.parse( "2013.06.08 12:46:44.123456789".replace( " " , "T" ) ) ;
正如 Jon Skeet 的 correct accepted Answer 所说,Java 8 及更高版本中的新 java.time 框架支持分辨率高达 nanosecond 的日期时间值。这意味着最多九位小数秒。
警告:在 Java 8 中,Clock 接口的默认实现与旧日期时间类中使用的旧当前时间代码相同。旧的实现仅限于millisecond 分辨率。因此,在 java.time 中,您可以存储以纳秒为单位的日期时间值,但您只能获取以毫秒为单位的当前时刻。
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[美国/蒙特利尔]
【讨论】: