Java和MySQL中的时间戳和时区转换
我正在开发一个Java应用程序,在一个与我所在时区不同的服务器上使用MySQL数据库,我正在尝试在数据库上使用DATETIME还是时间戳 在阅读了诸如和之类的问题后,我认为时间戳对我来说更合适,因为它将值转换为UTC进行存储,并返回到当前时区进行检索 此外,正如用户Jesper在thread中解释的那样,java.util.Date对象在内部只是一个UTC时间戳(即自历元起的毫秒数),当您执行toString()时,它将根据当前时区显示 对我来说,这看起来是一个很好的做法:将日期时间存储为UTC时间戳,然后根据当前时区显示它们 我本来打算这样做的,但后来我从准备好的声明中发现了这一点,我感到非常困惑: void setTimestamp(int参数索引, 时间戳x, 日历(校准) 抛出SQLException 将指定参数设置为给定的java.sql.Timestamp值, 使用给定的日历对象。驱动程序使用日历对象 构造SQL时间戳值,然后驱动程序将其发送到 数据库。使用日历对象,驱动程序可以计算 考虑自定义时区的时间戳。如果没有日历对象 指定时,驱动程序使用默认时区,即 运行应用程序的虚拟机 在此之前,我认为按照惯例,时间戳总是使用UTC。究竟为什么有人想要一个本地化的时间戳而不是它的本地化表示?这对每个人来说不是都很困惑吗 这些转换是如何工作的?如果Java获取UTC时间戳并将其转换为任意时区,它如何告诉MySQL它位于哪个时区Java和MySQL中的时间戳和时区转换,java,mysql,timestamp,Java,Mysql,Timestamp,我正在开发一个Java应用程序,在一个与我所在时区不同的服务器上使用MySQL数据库,我正在尝试在数据库上使用DATETIME还是时间戳 在阅读了诸如和之类的问题后,我认为时间戳对我来说更合适,因为它将值转换为UTC进行存储,并返回到当前时区进行检索 此外,正如用户Jesper在thread中解释的那样,java.util.Date对象在内部只是一个UTC时间戳(即自历元起的毫秒数),当您执行toString()时,它将根据当前时区显示 对我来说,这看起来是一个很好的做法:将日期时间存储为UTC
MySQL不会假设这个时间戳是UTC格式的,然后检索到一个不正确的本地化值吗?您的问题正好是一个我认为这些天非常严重的问题。DB(通过SQL)和服务器端本身(通过Java等编程语言)都提供了处理日期和时间的方法概要。我认为现状是高度非标准化的,有点混乱(个人观点:) 我的回答是片面的,但我会解释原因 没错,Java的日期(和日历)将时间存储为自Unix纪元以来的毫秒(这很好)。它不仅在Java中发生,在其他编程语言中也会发生。在我看来,完美的计时体系结构自然而然地由此产生:Unix时代是1970年1月1日UTC午夜。因此,如果您选择自Unix纪元以来以毫秒为单位存储时间,则有很多好处:
- 架构清晰:服务器端使用UTC,客户端通过其本地时区显示时间
- 数据库简单性:存储的是数字(毫秒),而不是复杂的数据结构(如DateTimes)
- 编程效率:在大多数编程语言中,当构建日期/时间对象时,它能够从Epoch开始以毫秒为单位(正如您所说,它允许自动转换到客户端时区)
- 人类无法读取
数字并将其解码为日期时间。因此,验证数据和调试变得复杂,至少可以这么说长的
- 你会用什么“计数”?被和被使用的?数据库、MySQL和其他数据库使用的?Java 8中的新用户使用了什么
- 你会用哪一种?1970年初的UTC标准是常见的,但远不是单一的。几乎已经被各种计算机系统使用
String sql = "SELECT now();";
…
java.sql.Timestamp now = myResultSet.getTimestamp( 1 );
DateTime dateTimeUtc = new DateTime( now , DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
myPreparedStatement.setObject( … , Instant.now() ) ;
Instant instant = myResultSet.getObject( … , Instant.class ) ;
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;