Java date pattern for SQL date (ISO 9075)
我试图解析SQL日期字符串(ISO 9075)并使用微秒(!)而不是毫秒,例如
1 | 2010-11-22 08:08:08.123456 |
但是,SimpleDateFormat拒绝识别像"yyyy-MM-dd HH:mm:ss.SSSSSS"这样的模式,而"yyyy-MM-dd HH:mm:ss.SSS"也不起作用。
我使用的代码看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | String dateString ="2010-11-22 08:08:08.123456"; String pattern ="yyyy-MM-dd HH:mm:ss.SSSSSS"; try { format = new SimpleDateFormat(pattern); format.setLenient(false); position.setIndex(0); Date date1 = format.parse(dateString, position); System.out.println("Date 1:" + date1); Date date2 = format.parse(dateString); System.out.println("Date 2:" + date1); } catch (Exception e) // Should not happen { e.printStackTrace(); } |
无论我使用哪两种模式("。SSS"或".SSSSSS"),date1都是打印机为
TL;博士
插入/更新。
1 2 3 4 | myPreparedStatement.setObject( … , Instant.parse("2010-11-22 08:08:08.123456".replace("" ,"T" ) +"Z" ) ) ; |
恢复。
1 2 | LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ; String output = ldt.toString().replace("T" ,"" ) ; // Remove the standard ISO 8601 format’s use of `T` in the middle with the SQL-style SPACE. |
java.time
Java 8带来了新的java.time包,以取代臭名昭着的旧java.util.Date,.Calendar和SimpleDateFormat类。那些旧的遗留类限制为毫秒分辨率,而输入字符串具有微秒。您不能将六位小数填充到限制为三的数据类型中。
java.time中的日期时间值具有纳秒分辨率,足以支持您的微秒。这意味着小数秒的最多九位小数。
使用JDBC 4.2及更高版本,直接使用
解析输入字符串。要符合java.time类中默认使用的ISO 8601格式,请使用
1 2 | String input ="2010-11-22 08:08:08.123456".replace("" ,"T" ) ; LocalDateTime ldt = LocalDateTime.parse( input ) ; |
如果此输入是UTC时刻,请附加
1 2 | String input ="2010-11-22 08:08:08.123456".replace("" ,"T" ) +"Z" ; Instant instant = Instant.parse( input ) ; |
发送到您的数据库。
1 | myPreparedStatement.setObject( … , instant ) ; |
…和…
1 | Instant instant = myResultSet.getObject( … , Instant.class ) ; |
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要
从哪里获取java.time类?
-
Java SE 8,Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小功能和修复。
-
Java SE 6和Java SE 7
- 许多java.time功能都被反向移植到Java 6& 7在ThreeTen-Backport。
-
Android的
- 更高版本的Android捆绑java.time类的实现。
- 对于早期的Android,ThreeTenABP项目采用ThreeTen-Backport(如上所述)。请参见如何使用ThreeTenABP ....
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的类,例如
更新:Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。将此部分保留为历史记录。
乔达时间
如上所述,您应该避免使用java.util.Date,.Calendar和SimpleDateFormat类。从Java 8开始,您可以选择使用java.time或Joda-Time或两者,因为它们各有优缺点。 Joda-Time也适用于早期版本的Java。
您可以使用Joda-Time解析该字符串。
或者,如果您可以访问生成字符串的java.sql.Timestamp,则只需将Timestamp对象传递给DateTime的构造函数即可。我建议也传递一个时区,因为DateTime对象知道他们自己指定的时区。
1 | DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.UTC ); |
要么
1 | DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.forID("Europe/Paris" ) ); |
Joda-Time的分辨率为毫秒。因此,无论采用哪种方式生成DateTime(解析或传递),您都将丢失第二个更精细的部分(忽略/截断,而不是舍入)。
在解析日期之前,可能会从dateString中删除剩余的小数部分?我有以下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | String dateString ="2010-11-22 08:08:08.123456"; String fraction = dateString.substring(dateString.length() - 3); String formatString = dateString.substring(0, dateString.length() - 3); String pattern ="yyyy-MM-dd HH:mm:ss.SSS"; ParsePosition position = new ParsePosition(0); try { SimpleDateFormat format = new SimpleDateFormat(pattern); format.setLenient(false); position.setIndex(0); Date date1 = format.parse(formatString, position); System.out.println("Date 1:" + date1); System.out.println("Date 1 fraction:" + fraction); Date date2 = format.parse(formatString); System.out.println("Date 2:" + date2); System.out.println("Date 2 fraction:" + fraction); } catch (Exception e) // Should not happen { e.printStackTrace(); } |
这允许日期解析到毫秒级精度,同时仍然保留微小部分。
你可能想调用DateFormat解析,因为我认为它会切断字符串。尝试:
1 |
另外,请勿使用"SSSSS"。根据规格,只有"SSS"对dateformat有效。
除此之外,我同意在SQL中删除它或解析它。
另外,你有setLenient为false,所以它是严格的。所以字符串越长就会导致它失败。也许这就是它返回null的原因。不确定,将不得不测试。
您可能希望查看DATE4J,它专门尝试处理数据库日期,达到纳秒级精度。
嗯。鉴于
如果您可以控制作为java代码输入的SQL日期,您可以尝试以一种可行的格式从SQL中检索日期("yyyy-MM-dd HH:mm:ss.SSS")。