在Java中处理MySQL日期时间和时间戳

Jam*_* P. 57 java mysql timestamp date jdbc

在Java应用程序中,使用日期时间和时间戳的混合在MySQL数据库中提取和输入日期信息方面会有什么好处?

Bal*_*usC 106

在Java方面,日期通常由(设计不佳,但旁边)表示java.util.Date.它基本上是由支持大纪元时间中的味道long,也称为时间戳.它包含有关日期和时间部分的信息.在Java中,精度以毫秒为单位.

在SQL方面,有几个标准的日期和时间类型,DATE,TIMETIMESTAMP(在一些DB的也称为DATETIME),这是代表在JDBC为java.sql.Date,java.sql.Timejava.sql.Timestamp所有子类java.util.Date.精度取决于数据库,通常以毫秒为单位,如Java,但也可以在几秒钟内完成.

相反java.util.Date,java.sql.Date仅包含有关日期部分(年,月,日)的信息.它Time仅包含有关时间部分(小时,分钟,秒)的Timestamp信息,并包含有关这两个部分的信息,如同java.util.Date.

在DB中存储时间戳的常规做法(因此,java.util.Date在Java端和java.sql.TimestampJDBC端)是使用的PreparedStatement#setTimestamp().

java.util.Date date = getItSomehow();
Timestamp timestamp = new Timestamp(date.getTime());
preparedStatement = connection.prepareStatement("SELECT * FROM tbl WHERE ts > ?");
preparedStatement.setTimestamp(1, timestamp);
Run Code Online (Sandbox Code Playgroud)

从DB获取时间戳的常规做法是使用ResultSet#getTimestamp().

Timestamp timestamp = resultSet.getTimestamp("ts");
java.util.Date date = timestamp; // You can just upcast.
Run Code Online (Sandbox Code Playgroud)

  • @cherouvim:是的.该模型不应该知道任何JDBC细节.仅用它来设置时间戳.`preparedStatement.setTimestamp(new Timestamp(date.getTime()));`.得到它很容易,因为它已经是`java.util.Date`的子类. (9认同)
  • 你认为在模型中使用java.sql.Timestamp(Java层)是不是很糟糕? (6认同)
  • 如果您的所有计算机和用户位于同一时区,这将正常工作.否则,请注意MySQL JDBC驱动程序对时区转换的处理非常复杂和错误.例如,请参阅http://stackoverflow.com/questions/40670532/what-are-jdbc-mysql-driver-settings-for-sane-handling-of-datetime-and-timestamp/40681941#40681941 (3认同)

Gar*_*ett 8

MySQL 文档包含有关将MySQL类型映射到Java类型的信息.通常,对于MySQL日期时间和时间戳,您应该使用java.sql.Timestamp.一些资源包括:

http://dev.mysql.com/doc/refman/5.1/en/datetime.html

http://www.coderanch.com/t/304851/JDBC/java/Java-date-MySQL-date-conversion

如何将Java Date存储到Mysql datetime ......?

http://www.velocityreviews.com/forums/t599436-the-best-practice-to-deal-with-datetime-in-mysql-using-jdbc.html

编辑:

正如其他人所指出的那样,使用字符串的建议可能会导致问题.

  • 不要按照绳子向前和向后按摩.这是可移植性和可维护性问题的秘诀. (6认同)

小智 5

BalusC 对问题进行了很好的描述,但它缺乏用户可以自行挑选和测试的良好端到端代码。

最佳做法是始终在 DB 中以 UTC 时区存储日期时间。Sql 时间戳类型没有时区信息。

将日期时间值写入 sql db 时

    //Convert the time into UTC and build Timestamp object.
    Timestamp ts = Timestamp.valueOf(LocalDateTime.now(ZoneId.of("UTC")));
    //use setTimestamp on preparedstatement
    preparedStatement.setTimestamp(1, ts);
Run Code Online (Sandbox Code Playgroud)

当将值从 DB 读回 java 时,

  1. 以 java.sql.Timestamp 类型读取它。
  2. 使用 LocalDateTime 类中的 atZone 方法将 DateTime 值装饰为 UTC 时区中的时间。
  3. 然后,将其更改为您想要的时区。在这里,我将其更改为多伦多时区。

    ResultSet resultSet = preparedStatement.executeQuery();
    resultSet.next();
    Timestamp timestamp = resultSet.getTimestamp(1);
    ZonedDateTime timeInUTC = timestamp.toLocalDateTime().atZone(ZoneId.of("UTC"));
    LocalDateTime timeInToronto = LocalDateTime.ofInstant(timeInUTC.toInstant(), ZoneId.of("America/Toronto"));
    
    Run Code Online (Sandbox Code Playgroud)