我有一个类,其日期字段表示一段数据的"有效起始日期".它的定义如下:
@Temporal( TemporalType.DATE )
private Date validFrom;
Run Code Online (Sandbox Code Playgroud)
在我从数据库中提取日期并显示它之前,似乎一切正常.如果我在前端选择2003年9月18日的日期,那么当我在数据库中检查确定的日期是保存的日期时保存它(数据库是MySQL 5.5.9列类型是DATE).然而,当我拿出一份清单时,显示的日期是2003年9月17日 - 前一天.
如果我选择在2003年3月26日或2003年12月25日之前或之后的一个日期,一切都很好,所以我猜这是与夏令时有关但错误在哪里蔓延?由于数据库似乎保持正确的日期,我猜测它必须在JPA转换回java.util.Date时 - java.util.Date是用于日期的最佳类吗?我已经看过一些人们使用Calendar的例子,但这看起来非常重,我不确定它能用于基于JSF的前端.
Dar*_*gue 26
很抱歉,到目前为止所有答案通常都是不正确的.答案很简单,但要求我们将五点分开:
简介:在服务器上,数据库中,在Java对象中使用UTC(GMT + 0).
DATE和TIMESTAMP仅与数据库视角不同,因为TIMESTAMP携带额外的秒数.两者都使用GMT + 0(隐含).JodaTime是一个首选的日历框架来处理所有这些,但不会解决不匹配的JVM与数据库时区设置的问题.
如果从JVM到数据库的应用程序设计不使用GMT,由于夏令时,时钟调整以及在世界本地时钟中播放的各种其他区域游戏......交易时间和其他一切将永远扭曲,非参考,不一致等
关于数据类型的另一个很好的相关答案:java.util.Date vs java.sql.Date
另请注意,Java 8具有更好的日期/时间处理(最终),但这并不能解决JVM运行的服务器时钟是在一个时区中而数据库在另一个时区中.此时总会发生翻译.在我使用的每个大型(智能)客户端中,由于这个原因,数据库和JVM服务器时区设置为UTC,即使它们的操作主要发生在某些其他时区.
经过多次实验和搜索,我很确定我找到了问题的原因.日期保存在java.util.Date中,该日期包含所有时间和时区的行李.似乎JPA正在从数据库中读取2003年9月18日的日期,然后像这样填写日期:"Thu Sep 18 00:00:00 BST 2003" - 注意时区已经设置为BST可能因为它不是由数据库显式设置.无论如何,如果你只想看到这样的日期,有必要格式化JSF页面中的输出:
<h:outputText value="#{t.validFrom}">
<f:convertDateTime pattern="dd MMM yyyy"/>
</h:outputText>
Run Code Online (Sandbox Code Playgroud)
但是,这假设时区是机器上当前有效的任何时区.在我的情况下,时区目前是格林尼治标准时间(因为它是冬天),所以当提交日期"星期四9月18日00:00:00 BST 2003"时,它将它转换为GMT,减去一个小时,显示器显示2003年9月17日.