为了账号安全,请及时绑定邮箱和手机立即绑定

通过 Jackson 序列化 java.sql.Date,同时考虑夏令时

通过 Jackson 序列化 java.sql.Date,同时考虑夏令时

慕的地6264312 2022-07-20 10:54:19
我正在使用 ajava.sql.Date将日期字段存储在我的一个域对象中。此字段映射到 MySQLDATE列。当我尝试通过杰克逊将此字段序列化为 JSON 时,杰克逊似乎没有考虑夏令时。这是我的域对象中该字段的样子:@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "EST")private Date date;如您所见,Jackson 已被指示将时区解释为 EST。我的 MySQL 数据库也使用 EST 时区:SHOW VARIABLES LIKE '%zone';Output:system_time_zone | ESTtime_zone        | SYSTEM我的麻烦是,对于夏令时开始和结束之间的日期,杰克逊返回的日期比数据库中存储的日期少一天。我假设这是因为杰克逊没有考虑夏令时。我通过尝试将Java 字段中的日期格式从yyyy-MM-dd更改为 来得出这个结论。yyyy-MM-dd HH:mm:ss我注意到服务器返回了类似的2017-03-13 00:00:00内容,但杰克逊将其序列化为2017-03-12 23:00:00(少一小时,这是夏令时影响的 EST 时间)。有没有办法克服这个问题?另外,java.sql.Date考虑到它没有时间对应物,使用正确的类型吗?我一直在考虑java.time.LocalDate改用,但我还没有看到它是否会成功。
查看完整描述

1 回答

?
浮云间

TA贡献1829条经验 获得超4个赞

博士

  • 永远不要使用java.sql.Date也不java.util.Date
    仅使用java.time类。

  • 对于仅日期值,请使用LocalDate.
    您只会看到稳定的值,不受夏令时 (DST) 的影响。

例子:

LocalDate.parse( "2019-01-23" )

java.sql.Date不是日期_

我不确定到底是什么问题,但我怀疑这是由于您使用了可怕的java.sql.Date课程,因此没有实际意义。

该类假装java.sql.Date代表一个仅限日期的值,没有时间和时区。然而,由于一些难以想象的糟糕设计决策,该类扩展了. 该课程确实有一个时间,并且是 UTC。更令人困惑的是,在它的源代码中隐藏了一个时区,没有 getter 和 setter,所以它似乎还没有影响像. 因此,尽管它的名称和目的是仅保存日期,但实际上确实将时间设置为 UTC。所以java.util.Datejava.util.Datejava.util.Dateequalsjava.sql.Datejava.sql.Date在调整一天中的时间方面有一些技巧,这可能是您遇到的问题。这些传统的日期时间课程是一大堆热气腾腾的……燕麦片。你永远不应该使用它们。

引用该类的JavaDocjava.sql.Date

一个围绕毫秒值的瘦包装器,允许 JDBC 将其识别为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00.000 GMT 以来经过的毫秒数。

为了符合 SQL DATE 的定义,由 java.sql.Date 实例包装的毫秒值必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“规范化” .

顺便说一句,java.sql.Timestamp同样糟糕的是一团糟。它也笨拙地继承自,为纳秒java.util.Date添加了第二个小数秒。也避免使用此类,现在由java.time.Instantor代替java.time.OffsetDateTime。同样,java.sql.Time替换为java.time.LocalTime

java.time.LocalDate真的是约会

随着 JSR 310 和 JDBC 4.2 的采用,您可以使用现代行业领先的java.time类。到目前为止,Jackson 可能已更新为使用java.time。如果没有,请参阅此问题以获取指向杰克逊中处理java.time的数据类型模块的链接。

看起来您的输入字符串采用标准ISO 8601格式,YYYY-MM-DD。java.time类在解析/生成表示日期时间值的字符串时默认使用标准格式对于仅日期使用,LocalDate真正是没有时间的日期的类,并且没有区域/偏移量。您将看到不受夏令时 (DST)影响的稳定日期值。

解析。

LocalDate ld = LocalDate.parse( "2019-01-23" ) ;

店铺。

myPreparedStatement.setObject( … , ld ) ;

取回。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;


查看完整回答
反对 回复 2022-07-20
  • 1 回答
  • 0 关注
  • 307 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号