我使用的是<code>java.sql。Date将日期字段存储在我的一个域对象中。此字段映射到MySQL<code>DATE</code>列。当我试图通过Jackson将该字段序列化为JSON时,Jackson似乎没有考虑夏时制。
下面是我的域对象中的字段:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "EST")
private Date date;
如您所见,杰克逊已被指示将时区解释为EST。我的MySQL数据库也使用EST时区:
SHOW VARIABLES LIKE '%zone';
Output:
system_time_zone | EST
time_zone | SYSTEM
我的问题是,对于夏令时开始和结束之间的日期,Jackson返回的日期比存储在html" target="_blank">数据库中的日期少一天。我假设这是因为Jackson没有考虑夏令时。
我通过尝试在 Java 字段中将日期的格式从 yyyy-MM-dd 更改为 yyyy-MM-dd HH:mm:ss
得出了这个结论。我注意到服务器返回了
类似 2017-03-13
00:00:00 的内容,但 Jackson 将其序列化为 2017-03-12 23:00:00
(少一小时,这是夏令时对 EST 时间的影响)。
有什么办法克服这个问题吗?还有<code>java.sql。日期考虑到它没有对应的时间,是否使用正确的类型?我一直在考虑使用<code>java.time。改为LocalDate</code>,但我还不知道它是否会成功。
提前感谢!
例子:
LocalDate.parse( "2019-01-23" )
我不确定问题到底是什么,但我怀疑这是由于您使用了糟糕的java.sql.Date
类,因此没有意义。
java.sql.Date
类假装表示仅日期值,没有时间和时区。然而,由于一些难以想象的糟糕设计决策,该类扩展了java.util.Date
。java.util.Date
类确实有一天中的时间,并且是UTC。更令人困惑的是,java.util.Date
在其源代码中隐藏了一个没有getter的时区
引用<code>java.sql的JavaDoc。日期类别:
毫秒值周围的一个薄薄的包装,允许JDBC将它识别为SQL日期值。毫秒值表示自1970年1月1日00:00:00.000 GMT以来经过的毫秒数。
为了符合SQLDATE的定义,必须通过在实例关联的特定时区中将小时、分钟、秒和毫秒设置为零来“规范化”java.sql.Date实例包装的毫秒值。
顺便说一下,< code>java.sql.Timestamp也一样糟糕。它也笨拙地继承了< code>java.util.Date,为纳秒增加了一秒。也要避免这个类,现在用< code>java.time.Instant或< code > Java . time . offsetdatetime 代替。类似地,< code>java.sql.Time被替换为< code>java.time.LocalTime。
随着JSR 310和JDBC 4.2的采用,您可以使用现代业界领先的java.time类。到现在为止,Jackson可能已经更新到使用java.time了,如果没有,请参见这个问题,获取在Jackson中处理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 ) ;
LocalDate
类表示一个只包含日期的值,没有一天中的时间,也没有时区或与UTC的偏移量。
时区对确定日期至关重要。在任何特定时刻,日期在全球各地因地区而异。例如,法国巴黎午夜过后几分钟是新的一天,而魁北克蒙特利尔仍然是“昨天”。
如果没有指定时区,JVM将隐式应用其当前的默认时区。该默认值可能会在运行时的任何时刻发生变化。),因此您的结果可能会有所不同。最好将您想要/预期的时区明确指定为一个参数。如果非常重要,请与您的用户确认该区域。
以大陆/地区格式指定正确的时区名称,例如美洲/蒙特利尔
、非洲/卡萨布兰卡
或太平洋/奥克兰
。切勿使用 2-4 个字母的缩写,例如
EST
或 IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
如果您想使用JVM的当前默认时区,请询问它并作为参数传递。如果省略,代码将变得模棱两可,因为我们无法确定您是否打算使用默认值,或者您是否像许多程序员一样不知道这个问题。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
或指定日期。你可以用一个数字来设定月份,其中1-12是一月到十二月的数字。
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
或者,更好的是使用预定义的 Month
枚举对象,一年中的每个月一个。提示: 在整个代码库中使用这些 Month
对象,而不仅仅是整数,以使代码更具自我文档性、确保有效值并提供类型安全性。同上 年份
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
java.time框架内置于Java8及更高版本中,这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
、日历
、
要了解更多信息,请参阅Oracle教程。并搜索堆栈溢出以获得许多示例和解释。规范为JSR 310。
现在处于维护模式的JodaTime项目建议迁移到java。时间课程。
你可以交换java。时间对象直接与数据库关联。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要<code>java.sql* 类。
从哪里获得java.time类?
ThreeTen-Extra项目用额外的类扩展了java.time。这个项目是java.time未来可能增加的内容的试验场。您可能会在这里找到一些有用的类,如< code>Interval 、< code>YearWeek 、< code>YearQuarter等等。
轻触方格启用设定,即可将夏令时反映于时间显示中。
问题内容: 中欧夏令时开始于三月的最后一个星期日。我们将时钟设置为02:00到03:00。如果我在数据库请求中进行时间戳计算会发生什么?比方说,在01:59? 结果是03:00还是02:00? 如果我们将时钟设置为03:00到02:00,那结束了呢? 时间从03:00更改为02:00之后…在02:00会发生什么?是02:59还是01:59? 应该如何处理?最佳实践以及Oracle Database
问题内容: 我正在编写一个处理很多时区并跨越时区的程序。我最常处理的两件事是从“ now”创建一个datetime对象,然后本地化一个朴素的datetime对象。 要从现在开始在太平洋时区创建datetime对象,我目前正在执行此操作(python 2.7.2+) 关于DST,这是否正确?如果没有,我想应该这样做: 我的问题是为什么?谁能告诉我第一个错误而第二个秒正确的情况? 至于我的秒数问题,假
我正在尝试使用Jackson将ISO8601格式的日期反序列化为Java8。我向ObjectMapper注册了JavaTimeModule,并关闭了设置。 但是,如果试图反序列化将不起作用,因为JavaTimeModule似乎只会反序列化使用UTC时区偏移量格式化的日期时间(例如)。然后我尝试使用注释,如下所示: 就像这样: 然而,这两种方法都不起作用,我得到了一个例外: 这意味着timezone
问题内容: 我想知道用Java最简单的方法来获取将来的夏令时将改变的日期列表。 一种相当灵活的方法是简单地迭代一整年的时间,然后对它们进行TimeZone.inDaylightTime()测试。这将起作用,并且我不担心效率,因为这仅在我的应用每次启动时都需要运行,但是我想知道是否有更简单的方法。 如果您想知道为什么要这样做,那是因为我有一个javascript应用程序,该应用程序需要处理包含UTC
问题内容: 如何检查夏令时是否有效? 问题答案: 您可以使用并查看返回值中的标志。 使用,您可以在任意时间问相同的问题,以了解DST在当前时区是否有效。