SimpleDateFormat 不解析毫秒,MySql 正在舍入日期
Posted
技术标签:
【中文标题】SimpleDateFormat 不解析毫秒,MySql 正在舍入日期【英文标题】:SimpleDateFormat not parsing milliseconds and MySql is rounding Date 【发布时间】:2018-09-17 17:15:33 【问题描述】:我正在使用 SimpleDateFormat 将字符串解析为日期。 解析后,我将此日期加载到 mysql。问题是毫秒没有被解析为日期,当我在 Mysql 上插入对象时,它会被四舍五入。
myStringDate = "2018-02-02 23:59:59.700"
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss.SSS");
myObject.setDate(fmt.parse(myStringDate );
当我调试代码时,我可以看到日期为 Sun Feb 02 23:59:59 BRST 2018(它不存储毫秒)
数据在mysql上存储为'2017-02-03 00:00:00'
我的模型映射为:
import javax.persistence.*;
import java.util.Date;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date")
private Date date;
MySqls 上的列是 TYPE DATETIME。
【问题讨论】:
Spring 不支持现代的java.time
日期和时间类型吗?我会使用LocalDateTime
而不是Date
。该课程和SimpleDateFormat
早已过时。现代 API 更易于使用。
【参考方案1】:
我认为实际上是在解析毫秒,只是在显示用于调试目的的日期时没有使用默认格式看到它们。
使用此代码:
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String myStringDate = "2018-02-02 23:59:59.700";
Date date = fmt.parse(myStringDate);
System.out.println(date);
System.out.println(fmt.format(date));
我得到这个输出:
Fri Feb 02 23:59:59 EST 2018
2018-02-02 23:59:59.700
更新:请确保您在本月使用大写字母 MM
,而不是 mm
。
【讨论】:
注意小数部分是微秒(不是毫秒)。 “一个 DATETIME 或 TIMESTAMP 值可以包括一个尾随小数秒部分,精度高达微秒(6 位)...... DATETIME 值的范围是 '1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'"dev.mysql.com/doc/refman/8.0/en/datetime.html 虽然 MySQL 可能以微秒为单位处理,但 Java 的原始日期/时间 API(OP 正在使用)仅处理毫秒分辨率。 Java 8 引入的日期/时间 API 可以达到纳秒级分辨率(尽管实际上,对于来自系统时钟的当前时间,您可能只能获得毫秒级分辨率)。【参考方案2】:tl;博士
myPreparedStatement.setObject(
… ,
LocalDateTime.parse(
"2017-02-03 00:00:00".replace( " " , "T" )
)
)
智能类型,而不是哑字符串
数据在mysql上存储为'2017-02-03 00:00:00'
不,数据不是以这种方式存储的。你说:
MySqls 的列是 TYPE DATETIME。
这意味着日期时间不存储为文本,并且没有“格式”。
正如the documentation 所说:
DATETIME 类型用于同时包含日期和时间部分的值。 MySQL 以 'YYYY-MM-DD HH:MM:SS' 格式检索和显示 DATETIME 值。
关键词有:检索和展示。提取日期时间值后,构造一些文本来表示该值。 不要将日期时间值的文本表示与日期时间值混为一谈。 您的数据库和 Java 都有自己内部定义的日期时间存储方式,但都不使用纯文本.您的数据库和 Java 都可以根据需要生成文本以显示日期时间值。
未分区
我是Postgres 用户,而不是MySQL,但它的DATETIME
类型似乎类似于SQL 标准的TIMESTAMP WITHOUT TIME ZONE
类型。这意味着它确实不代表一个实际的时刻,不是时间线上的一个点。它代表了大约 26-27 小时范围内的潜在时刻。如果没有time zone 或offset-from-UTC 的上下文,它就没有真正的意义。
java.time 类
避免使用旧的日期时间类型。请仅使用 java.time 类。根据this Question,JPA 和 Hibernate 现在支持 java.time 类型。
如果您确实有输入文本,例如 2018-02-02 23:59:59.700
,则解析为 LocalDateTime
,因为缺少区域/偏移信息。与 MySQL 类型 DATETIME
和 SQL 类型 TIMESTAMP WITHOUT TIME ZONE
一样,此类缺少任何区域/偏移量的概念。要进行解析,请将中间带有 SPACE 的 SQL 样式转换为中间带有 T
的 ISO 8601 标准格式。
String input = "2018-02-02 23:59:59.700".replace( " " , "T" ) ;
java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要定义格式化模式。
LocalDateDate ldt = LocalDateTime.parse( input ) ;
与数据库通信时不需要字符串。从 JDBC 4.2 及更高版本开始,您可以直接交换 java.time 对象。 (或者让 JPA/Hibernate 在幕后进行。)
myPreparedStatement.setObject( … , ldt ) ;
和检索。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
仅供参考,如果您实际上是在尝试及时跟踪特定时刻,则说明您使用了错误的类型。您应该在 MySQL 中使用 TIMESTAMP
或在标准 SQL 中使用 TIMESTAMP WITH TIME ZONE
,在 Java 中使用 Instant
和 ZonedDateTime
。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
Java SE 8、Java SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
【参考方案3】:如果您使用 MySQL 的 5.6.4 版,您可以通过声明具有小数秒时间数据类型的列来看到这种情况。
This 文档显示了有关此功能的更多详细信息,并且就快速检查而言 - 您可以尝试 SELECT NOW(3)
应该以毫秒精度为您提供 MySQL 服务器操作系统的当前时间,而不是如果您出现错误,那么您没有使用正确的版本。
除此之外,非常建议从旧的 Connector/J 驱动程序迁移到 mysql-connector-java-5.1.26.jar
。
希望这有助于回答您的问题!
【讨论】:
【参考方案4】:一年中月份的模式应该是MM
(大写)而不是mm
(小写)SimpleDateFormat
。您的代码可能会将月份读取为分钟值。
【讨论】:
【参考方案5】:SQL 中的日期格式为 YY-MM-dd hh24:mi:ss:mmm,而 Java 中的日期格式为 YY-MM-dd HH:mm:ss.SSS
【讨论】:
【参考方案6】:我使用了 LocalDateTime:
@Column(name = "date", columnDefinition = "DATETIME(3)") 私有 LocalDateTime 日期;
【讨论】:
以上是关于SimpleDateFormat 不解析毫秒,MySql 正在舍入日期的主要内容,如果未能解决你的问题,请参考以下文章
SimpleDateFormat.format的简单使用小结
java===Date,DateFormat,SimpleDateFormat,Calendar类