我从 Postgres 数据库中得到一个 6 位微秒(实际上是 ),例如2014-11-10 04:05:06.999999
现在,当我应用“yyyy-MM-dd HH:mm:ss.SSS”日期格式时,它会将 999999 转换为相应的秒/分钟,从而导致日期不正确。请参阅下面的代码片段
String dt = "2014-11-10 04:05:06.999999";
String timeseriesFormat = "yyyy-MM-dd HH:mm:ss.SSS";
SimpleDateFormat dateFormat = new SimpleDateFormat(timeseriesFormat);
Date date = dateFormat.parse(dt);
System.out.println(dateFormat.format(date));
2014 年 11 月 10 日的结果 04:21:45.999
我想截断最后 3 位数字并保留 2014-11-10 04:05:06.999 的日期。 如何截断它?我不想使用任何框架,如 joda 等。
最佳答案
java.time
使用 Java 8 及更高版本中内置的 java.time 类。永远不要使用可怕的遗留日期时间类,例如 Date
、Calendar
、SimpleDateFormat
、GregorianCalendar
和 时间戳
。
从 JDBC 4.2 及更高版本开始,我们可以直接与数据库交换 java.time 对象。
String input = "2014-11-10 04:05:06.999999".replace( " " , "T" ) ; // Convert from SQL style to ISO 8601 standard format where `T` separates the year-month-day portion from hour-minute-second portion.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
一刻钟
请注意 LocalDateTime
不是一个时刻,不是时间轴上的一个点。您的输入缺少时区或与 UTC 的偏移量的上下文。因此,我们不知道您指的是日本东京 10 日凌晨 4 点、法国图卢兹凌晨 4 点,还是美国俄亥俄州托莱多的凌晨 4 点——三个截然不同的时刻,在时间轴上相隔几个小时。
因此,您会将 LocalDateTime
对象的值存储在 TIMESTAMP WITHOUT TIME ZONE
类型的 Postgres 数据库列中.
片刻
如果您的意图是代表一个时刻,即时间轴上的一个特定点,那么您肯定知道预期的时区。
假设您知道凌晨 4 点是日本东京时区。申请 ZoneId
到 LocalDateTime
得到 ZonedDateTime
对象。
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
不幸的是,JDBC 4.2 规范不要求支持两种最常用的类型,Instant
和 ZonedDateTime
.没关系,我们可以轻松转换为OffsetDateTime
,JDBC 规范要求支持。
OffsetDateTime odt = zdt.toOffsetDateTime() ;
这样一个值,时间轴上的一个特定点,应该被写入类型为TIMESTAMP WITH TIME ZONE
的数据库列中。 .
写入数据库。
myPreparedStatement.setObject( … , odt ) ;
和检索。
myResultSet.getObject( … , OffsetDateTime.class ) ;
java.sql.Timestamp
如果您不能迁移到 Java 8,那么您应该使用 JDBC 驱动程序来获取 java.sql.Timestamp
目的。该类(class)是一个黑客,但它有效。它是一个 java.util.Date 但跟踪小数秒到纳秒而不是毫秒的分辨率。因此它将保留 Postgres 使用的微秒数。
您可以将它用作 java.util.Date,但在其他情况下您将失去额外的分辨率。
但是,您现在真的在 2020 年就坚持使用 Java 6、7 或更早的版本吗?最好迁移到 Java 8 或 Java 11,这两个 LTS版本。
关于java.time
java.time框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧类 legacy日期时间类,例如 java.util.Date
, Calendar
, & SimpleDateFormat
.
要了解更多信息,请参阅 Oracle Tutorial .并在 Stack Overflow 中搜索许多示例和解释。规范为 JSR 310 .
Joda-Time项目,现在在maintenance mode , 建议迁移到 java.time类。
您可以直接与您的数据库交换java.time 对象。使用JDBC driver符合 JDBC 4.2或以后。不需要字符串,不需要 java.sql.*
类。 Hibernate 5 和 JPA 2.2 支持 java.time。
从哪里获取 java.time 类?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 , 以及后来的 - 标准 Java API 的一部分,带有捆绑实现。
- Java 9带来了一些次要功能和修复。
- Java SE 6和 Java SE 7
- 在 ThreeTen-Backport 中,大部分 java.time 功能都向后移植到 Java 6 和 7。 .
- Android
- 更高版本的 Android(26+)捆绑了 java.time 类的实现。
- 对于早期的 Android (<26),称为 API desugaring 的进程带来一个subset of the java.time Android 最初未内置的功能。
- 如果脱糖没有提供您需要的东西,ThreeTenABP项目改编ThreeTen-Backport (上面提到的)Android。参见 How to use ThreeTenABP… .
关于具有 6 位微秒/毫秒的 java 日期格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26899550/