Java日期解析具有微秒或纳秒精度 [英] Java date parsing with microsecond or nanosecond accuracy
问题描述
根据 SimpleDateFormat类文档, Java
在日期模式中不支持超过毫秒的时间粒度。
According to the SimpleDateFormat class documentation, Java
does not support time granularity above milliseconds in its date patterns.
所以,日期字符串
- 2015-05-09 00:10:23.999750900 //最后9位数字表示纳秒数
通过模式解析时
- yyyy-MM-dd HH:mm :ss.SSSSSSSSS // 9''符号
实际上解释之后的整数。
符号为(近10亿!)毫秒而不是纳秒,导致日期
actually interprets the whole number after the .
symbol as (nearly 1 billion!) milliseconds and not as nanoseconds, resulting in the date
- 2015-05-20 21:52:53 UTC
ie超过11天。令人惊讶的是,使用较少数量的 S
符号仍然会导致所有9位数被解析(而不是,例如, .SSS最左边的3位数
)。
i.e. over 11 days ahead. Surprisingly, using a smaller number of S
symbols still results in all 9 digits being parsed (instead of, say, the leftmost 3 for .SSS
).
有两种方法可以正确处理此问题:
There are 2 ways to handle this issue correctly:
- 使用字符串预处理
- 使用自定义SimpleDateFormat实现
是否有任何通过向标准 SimpleDateFormat
实现提供模式来获得正确解决方案的其他方法,无需任何其他代码修改或字符串操作?
Would there be any other way for getting a correct solution by just supplying a pattern to the standard SimpleDateFormat
implementation, without any other code modifications or string manipulation?
推荐答案
tl; dr
tl;dr
LocalDateTime.parse( // With resolution of nanoseconds, represent the idea of a date and time somewhere, unspecified. Does *not* represent a moment, is *not* a point on the timeline. To determine an actual moment, place this date+time into context of a time zone (apply a `ZoneId` to get a `ZonedDateTime`).
"2015-05-09 00:10:23.999750900" // A `String` nearly in standard ISO 8601 format.
.replace( " " , "T" ) // Replace SPACE in middle with `T` to comply with ISO 8601 standard format.
) // Returns a `LocalDateTime` object.
Nope
不,你不能使用SimpleDateFormat可以处理纳秒。
但是你的前提是......
But your premise that…
Java不支持时间粒度毫秒
...从 Java 8 ,9,10及更高版本 java.time 类内置。并不是Java 6和Java 7也是如此,因为大多数 java.time 功能已反向移植。
…is no longer true as of Java 8, 9, 10 and later with java.time classes built-in. And not really true of Java 6 and Java 7 either, as most of the java.time functionality is back-ported.
SimpleDateFormat
,以及相关的 java.util.Date
/ .Calendar
类现已过时找到新的 java.time 包在Java 8中(教程)。
SimpleDateFormat
, and the related java.util.Date
/.Calendar
classes are now outmoded by the new java.time package found in Java 8 (Tutorial).
新的java.time类支持纳秒决议。该支持包括解析和生成九位数的小数秒。例如,当您使用 java.time.format
DateTimeFormatter
API时, S
模式字母表示秒的一小部分而不是毫秒,它可以处理纳秒值。
The new java.time classes support nanosecond resolution. That support includes parsing and generating nine digits of fractional second. For example, when you use the java.time.format
DateTimeFormatter
API, the S
pattern letter denotes a "fraction of the second" rather than "milliseconds", and it can cope with nanosecond values.
例如, Instant
类代表 UTC 。它的 toString
方法使用标准 String 对象/ wiki / ISO_8601rel =noreferrer> ISO 8601 格式。结尾的 Z
表示UTC,发音为Zulu。
As an example, the Instant
class represents a moment in UTC. Its toString
method generates a String
object using the standard ISO 8601 format. The Z
on the end means UTC, pronounced "Zulu".
instant.toString() // Generate a `String` representing this moment, using standard ISO 8601 format.
2013-08-20T12:34:56.123456789Z
2013-08-20T12:34:56.123456789Z
请注意,捕获Java 8中的当前时刻仅限于毫秒分辨率。 java.time 类可以保持一个以纳秒为单位的值,但只能用毫秒来确定当前时间。此限制是由于 Clock
的实现。在Java 9及更高版本中,新的 Clock
实现可以以更精细的分辨率获取当前时刻,具体取决于主机硬件和操作系统的限制,通常微秒。
Note that capturing the current moment in Java 8 is limited to millisecond resolution. The java.time classes can hold a value in nanoseconds, but can only determine the current time with milliseconds. This limitation is due to the implementation of Clock
. In Java 9 and later, a new Clock
implementation can grab the current moment in finer resolution, depending on the limits of your host hardware and operating system, usually microseconds in my experience.
Instant instant = Instant.now() ; // Capture the current moment. May be in milliseconds or microseconds rather than the maximum resolution of nanoseconds.
LocalDateTime
您的示例输入字符串 2015-05-09 00:10:23.999750900
缺少时区指示符或UTC的偏移量。这意味着它不代表片刻,不时间轴上的一个点。相反,它代表潜在时刻,范围约为26-27小时,即全球时区范围。
LocalDateTime
Your example input string of 2015-05-09 00:10:23.999750900
lacks an indicator of time zone or offset-from-UTC. That means it does not represent a moment, is not a point on the timeline. Instead, it represents potential moments along a range of about 26-27 hours, the range of time zones around the globe.
Pares输入为 LocalDateTime
对象。首先,用 T
替换中间的SPACE,以符合ISO 8601格式,在解析/生成字符串时默认使用。所以不需要指定格式化模式。
Pares such an input as a LocalDateTime
object. First, replace the SPACE in the middle with a T
to comply with ISO 8601 format, used by default when parsing/generating strings. So no need to specify a formatting pattern.
LocalDateTime ldt =
LocalDateTime.parse(
"2015-05-09 00:10:23.999750900".replace( " " , "T" ) // Replace SPACE in middle with `T` to comply with ISO 8601 standard format.
)
;
java.sql.Timestamp
java.sql.Timestamp
类也处理纳秒分辨率,但是处于一种尴尬的方式。通常最好在java.time类中完成你的工作。从JDBC 4.2及更高版本开始,无需再次使用 Timestamp
。
myPreparedStatement.setObject( … , instant ) ;
并且检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
如果使用较旧的4.2之前的JDBC驱动程序,则可以使用 toInstant
和 来自
方法在java.sql.Timestamp和java.time之间来回传递。
If using an older pre-4.2 JDBC driver, you can use toInstant
and from
methods to go back and forth between java.sql.Timestamp and java.time.
java.time 框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如 java.util.Date
, 日历
,& SimpleDateFormat
。
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
Joda-Time 项目,现在位于维护模式,建议迁移到 java.time 课程。
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
要了解更多信息,请参阅 Oracle教程 。并搜索Stack Overflow以获取许多示例和解释。规范是 JSR 310 。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
您可以直接与数据库交换 java.time 对象。使用符合 JDBC驱动程序 jeps / 170rel =noreferrer> JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql。*
类。
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
从哪里获取java.time班?
Where to obtain the java.time classes?
- Java SE 8 , Java SE 9 , Java SE 10 以及稍后
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9添加了一些小功能和修复。
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- 大部分java.time功能都被反向移植到Java 6& 7 ThreeTen-Backport 。
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- java.time 类的Android更高版本捆绑包实现。
- 对于早期的Android(< 26), ThreeTenABP 项目适应 ThreeTen-Backport (如上所述)。请参阅 如何使用ThreeTenABP ...... 。
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
ThreeTen-Extra 项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。您可以在这里找到一些有用的课程,例如
间隔
,YearWeek
,YearQuarter
,更多。这篇关于Java日期解析具有微秒或纳秒精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!