【问题标题】:JOOQ date as is, ignore timezoneJOOQ 日期原样,忽略时区
【发布时间】:2020-05-03 20:52:29
【问题描述】:

我在使用 Jooq 的前 1 天从 SQL 中的日期列中得到 2019-09-01。我认为这是因为我的应用程序(操作系统级别和 Java 前端)使用US/Eastern,但数据库使用 UTC。请参阅下面的 SQL:

select kpisd1, convert_tz( kpisd1, 'US/Eastern', @@session.time_zone), convert_tz( kpisd1, @@session.time_zone, 'US/Eastern' ), @@session.time_zone from kpi where kpiprc = '00006330263815' and kpikpi = 'TURN' and kpists = 'HIST';
+---------------------+--------------------------------------------------------+---------------------------------------------------------+---------------------+
| kpisd1              | convert_tz( kpisd1, 'US/Eastern', @@session.time_zone) | convert_tz( kpisd1, @@session.time_zone, 'US/Eastern' ) | @@session.time_zone |
+---------------------+--------------------------------------------------------+---------------------------------------------------------+---------------------+
| 2019-09-01 00:00:00 | 2019-09-01 04:00:00                                    | 2019-08-31 20:00:00                                     | UTC                 |
+---------------------+--------------------------------------------------------+---------------------------------------------------------+---------------------+
1 row in set (0.00 sec)

实际上,我的 C 程序,即更新数据库的程序,在将其添加到数据库之前并没有真正进行任何时区转换。它根据操作系统时区获取日期,然后使用该日期。因此,如果它增加了 2019 年 9 月 1 日,我预计会在 2019 年 9 月 1 日回来。我试过select date( kpisd1 ),但也没有用。即使我打印出原始的 java.sql.Date,它也与数据库不匹配,这意味着它可能正在 JDBC 内部进行转换,我猜。有什么想法吗?

我唯一的其他选择是将数据库时区从 UTC 转换为“美国/东部”(以匹配我的应用程序服务器上的时区),但我需要研究其后果,所以我尽量不要急于如此激烈的一步(这是生产环境)。

【问题讨论】:

  • 您是否在 MySQL 中使用datetime 来存储不需要时间的日期?为什么?您可能还想create a Minimal, Reproducible Example,以便我们确切地看到您正在尝试什么。
  • jOOQ 在 JDBC 之上没有做任何额外的时区转换魔法,所以这更像是你的 JDBC 驱动程序的工作方式。有很多方法可以解决这个问题,理想情况下不是基于每个查询,而是通过将所有时区设置为 UTC...
  • @OleV.V. datetime 使用而不是简单的 date 是我们使用的其他数据库系统的保留,我预计。老实说,这无关紧要,因为我们的 C 代码不在乎,只是照原样处理。无论如何,关键是在一个时区(不是 UTC)中运行的应用程序与 UTC 中的数据库相对应。
  • @LukasEder 我不能在任何地方都使用 UTC,现在不能。也许我们应该从一开始就这样做,但使用我们当地的时区总是更容易,所以这就是我们所做的。我只是错过了设置此数据库时的影响,没有意识到在数据库级别不将时区从 UTC 更改为我们的本地时区的后果。所以,我真的需要在每个查询的基础上执行此操作,除非这些方法或非常糟糕的想法。您能否指出正确的方向,以便我评估其中的一些想法,看看是否适合我的用例?
  • MySQL 的 JDBC 驱动程序有 很多 的 JDBC URL 属性,用于控制时区的行为。我建议您查看dev.mysql.com/doc/connector-j/5.1/en/… 并测试一些属性,例如useTimezonenoTimezoneConversionForDateType

标签: mysql jdbc jooq


【解决方案1】:

根据@knutwannheden 的建议,我改变了:

                databaseUrl = "jdbc:mysql://" + host.trim() + ":3306/" + db.trim();

                Calendar now = Calendar.getInstance();
                databaseUrl = "jdbc:mysql://" + host.trim() + ":3306/" + db.trim() +
                        "?serverTimezone=" + now.getTimeZone().getID(); 

我根据上面引用的文档选择了serverTimezone

服务器时区

覆盖时区的检测/映射。时区从 服务器没有映射到 Java 时区

自版本:3.0.2

是的,在我的情况下,这实际上是不正确的——我的 MySql 服务器设置为 UTC,它确实映射到客户端,但是因为我不希望它映射,所以我尝试了这个并且它有效。我没有尝试其他时区参数,因为这个参数可以立即使用,但是noTimezoneConversionForDateType 或其他时区参数之一很有可能会起作用。

如果有人对此解决方案有疑虑,请提出。我想我有点作弊,但我现在想不出任何真正危险的副作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 2017-11-22
    • 2012-10-30
    • 1970-01-01
    • 2017-12-07
    • 2012-05-02
    相关资源
    最近更新 更多