很长一段时间以来,我一直面临这个日期问题。尝试过很多东西但是徒劳无功。问题是这样的:
用户输入的日期为“2009-08-12”。它会正确存储在数据库中。
在GMT + 530时区中,日期也会正确显示。但是当我将时区更改为GMT + 1时,日期显示为“2009-08-11”,即它显示日期为1天。
任何帮助或输入或建议都会有很大帮助。
由于
NAIT
答案 0 :(得分:5)
日期可能存储为DATETIME
或TIMESTAMP
,2009-08-12 00:00:00 +0530
转换为GMT+1
后,它会为您提供2009-08-11 19:30:00 +0100
MySQL
的{{1}}不会将时区与时间戳一起存储,因此如果您的类型为DATETIME
,则可能是您的数据库访问层转换日期。
DATETIME
的{{1}}类型会将时间存储在MySQL
中,并在查询时将其转换回客户端的时区。
答案 1 :(得分:3)
这个问题非常广泛。例如,以下是Martin Fowler的一些评论。
潜在的问题是Java的日期类将日期/时间视为物理中的数量 - 特定的,不可变的瞬间的表示。
问题在于,这与大多数人对时间的随意思考方式不符。在典型的话语中,人们认为'2009-08-01 18:00'是固定的想法。问题是这种表述没有时区;因此,它实际上并不代表特定的瞬间。
这是许多应用程序中持续混淆的原因。虽然Java总是使用时区(隐式或显式),但数据库通常不会存储时区信息以及日期/时间。因此,Java必须在创建Date对象时添加假定的时区。这将由JDBC驱动程序在将值转换为Date对象时完成。如果此类代码在服务器上运行,则假定的时区通常与客户端/最终用户使用的时区不匹配。
唯一的答案是确保您的Java代码使用“标准”时区。
答案 2 :(得分:1)
@Quassnoi已经解释了为什么会发生这种情况,但解决问题的方法是使用java.sql.PreparedStatement
和java.sql.ResultSet
上采用日历参数的各种方法 - java.sql.PreparedStatement.setDate(int, Date, Calendar)
之类的方法, java.sql.ResultSet.getDate(int, Calendar)
等等。
我的建议是选择一个标准时区,用于表示数据库中的日期,通常为UTC,然后使用我上面提到的方法执行任何转换。
当然,如果您可以在与更好的数据库相同的时区上标准化您的客户端,并且它允许您在不考虑时区的情况下执行数据比较,那么您只需在显示日期时执行任何转换。
答案 3 :(得分:0)
我在使用cron表达式处理石英时出现了类似的问题,计划的作业以错误的小时值保存,我只是将我的应用程序托管的服务器时区调整为我的本地时区值,问题已修复。