具有微秒或纳秒精度的Java数据解析
根据,具有微秒或纳秒精度的Java数据解析,java,simpledateformat,milliseconds,Java,Simpledateformat,Milliseconds,根据,Java在其日期模式中不支持超过毫秒的时间粒度 所以,像这样的日期字符串 2015-05-09 00:10:23.99975000//最后9位数字表示纳秒 当通过模式解析时 yyyy MM dd HH:MM:ss.SSSSS//9’S’符号 实际上,将符号后的整数解释为(近10亿!)毫秒,而不是纳秒,从而生成日期 2015-05-20 21:52:53 UTC i、 e.提前11天以上。令人惊讶的是,使用较少数量的S符号仍然会导致解析所有9位数字(而不是,比如说,.SSS的最左
Java
在其日期模式中不支持超过毫秒的时间粒度
所以,像这样的日期字符串
- 2015-05-09 00:10:23.99975000//最后9位数字表示纳秒
- yyyy MM dd HH:MM:ss.SSSSS//9’S’符号
符号后的整数解释为(近10亿!)毫秒,而不是纳秒,从而生成日期
- 2015-05-20 21:52:53 UTC
S
符号仍然会导致解析所有9位数字(而不是,比如说,.SSS
的最左边3位)
有两种方法可以正确处理此问题:
- 使用字符串预处理
- 使用自定义SimpleDataFormat实现
SimpleDateFormat
实现提供一个模式,而不进行任何其他代码修改或字符串操作,是否还有其他方法可以获得正确的解决方案?tl;博士
不
不,不能使用SimpleDataFormat来处理
但是你的前提是
Java在其日期模式中不支持上述时间粒度
…对于内置的java.time类,在9、10及更高版本中不再适用。对于Java6和Java7也不是这样,因为大多数Java.time都是这样
java.time
SimpleDataFormat
,以及相关的java.util.Date
/.Calendar
类现在已经被java 8()中的新包过时了
新的java.time类支持解析。这种支持包括解析和生成九位小数秒。例如,当您使用java.time.format
DateTimeFormatter
API时,S
模式字母表示“秒的分数”而不是“毫秒”,它可以处理纳秒值
Instant
作为一个例子,这个类代表了一个时刻。它的toString
方法使用标准格式生成String
对象。末尾的Z
表示UTC,发音为“Zulu”
instant.toString() // Generate a `String` representing this moment, using standard ISO 8601 format.
2013-08-20T12:34:56.123456789Z
请注意,在Java8中捕获当前时刻的分辨率仅限于毫秒。time类可以以纳秒为单位保存值,但只能以毫秒为单位确定当前时间。此限制是由于实现了时钟
。在Java 9和更高版本中,一个新的时钟实现可以以更高的分辨率抓住当前时刻,这取决于主机硬件和操作系统的限制,通常是我的经验
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
对象进行排序。首先,用“<代码> t>代码>替换中间的空间,以符合ISO 8601格式,在解析/生成字符串时默认使用。因此,无需指定格式化模式
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.time类中完成工作。从JDBC 4.2及更高版本开始,不再需要再次使用时间戳
myPreparedStatement.setObject( … , instant ) ;
和检索
Instant instant = myResultSet.getObject( … , Instant.class ) ;
OffsetDateTime
JDBC规范没有强制要求支持即时
,但是OffsetDateTime
是。因此,如果上述代码在JDBC驱动程序中失败,请使用以下代码
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
和检索
Instant instant = myResultSet.getObject( … , OffsetDateTime.class ).toInstant() ;
如果使用较旧的4.2版本之前的JDBC驱动程序,则可以使用和方法在java.sql.Timestamp
和java.time之间来回切换。这些新的转换方法被添加到旧的遗留类中
关于java.time
该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&
该项目现已启动,建议迁移到类
要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是
您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要java.sql.*
类
从哪里获得java.time类
- 然后
- 内置的李>
- 标准JavaAPI的一部分,带有捆绑实现
- Java9添加了一些次要功能和修复
- 及
- 大部分java.time功能都在中向后移植到Java6和Java7
-
- 更高版本的Android捆绑包实现了java.time类
- 对于早期的Android(我发现覆盖多种日期-时间格式非常好,如下所示:
final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
…只向标准的SimpleDataFormat
实现提供一个模式,而不进行任何其他代码修改或字符串操作?显然不是。是的,尽管由于相应的用例,要求使用SimpleDataFormat
解决方案。@OleV.V.完成。谢谢你的建议。有人想解析dat吗有时区的时间字符串,可以使用instant.Parse(“datetimestring”)@PrashantSaraswat不,对于时区,可以使用ZonedDateTime
,而不是instant
。请参见我回答中的表格图形。@BasilBourque感谢您指出这一点。这两种方法都有效。我使用instant是因为javadoc for LocalDateTime建议使用instant。
final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);