【问题标题】:How to prevent Mysql Connector/J from converting DATE and TIME timezone?如何防止 Mysql Connector/J 转换 DATE 和 TIME 时区?
【发布时间】:2020-05-08 15:25:04
【问题描述】:

我正在使用以下 DSN 连接到 mysql 服务器:jdbc:mysql://localhost/my_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC

我遇到的问题是 java.sql.Date 实例正在将时区从我的本地时区转换为 UTC。我的应用程序将日期视为与时区无关,这会导致一些问题。

例如,我在 IST (UTC+05:30) 中,当我在代码中将某个日期字段设置为“2020-01-22”时,它会以“2020-01-21”的形式发送到服务器'。我已经从 mysql 常规日志中验证了这一点。

我尝试了useLegacyDatetimeCodeuseTimezonenoTimezoneConversionForDateType 的几种组合,但到目前为止我一直无法让 mysql 驱动程序跳过日期字段的转换。

如何让 mysql 驱动程序跳过日期和时间字段的转换?

我已经尝试过第 6 版和第 8 版的 Connector/J 驱动程序 mysql:mysql-connector-java:<version>。 另外,我正在使用 JOOQ 并使用一个简单的转换器在 LocalDatejava.sql.Date 之间进行转换。

【问题讨论】:

    标签: java mysql jooq mysql-connector


    【解决方案1】:

    如果你真的想要一个“时区不可知论”的日期,你必须在 Java 中使用 LocalDateLocalDate 很好地映射到 MySQL 的 DATE 类型。

    https://thoughts-on-java.org/hibernate-5-date-and-time/

    完全不涉及时区。

    【讨论】:

    • 我在自己的代码中使用 LocalDate。不幸的是,JOOQ 只知道 sql Date 类,而 mysql 驱动程序正在对其进行时区转换。
    • 想想两种选择。 MySQL DATE 或多或少是一个字符串。无需转换。 MySQL TIMESTAMP 是一个数字(Unix Timestamp)。这个秒数总是需要转换为相对于特定时区的特定日期。总会有时区转换。只要确保您的时间戳始终显示/解析为 UTC 日期时间,就可以了。将其存储为 UTC,然后对用户隐藏 UTC 时区。假设您的用户居住在 UTC 区域。
    • 您可以选择任何其他固定时区。但是,如果您选择本地时区,那么每当您需要将服务器移动到不同的时区时就会遇到麻烦。
    • @Trinopoty: 1) java.sql.Datejava.time.LocalDate 实现完全相同的语义,并且可以相互转换。 2) jOOQ 两者都支持。
    【解决方案2】:

    我自己也遇到了同样的问题,现在我用这个转换器解决了它:

    public final class DateConverter implements Converter<Date, LocalDate> {
        @Override
        public final LocalDate from(final Date value) {
            if(null == value) {
                return null;
            } else {
                return value.toLocalDate();
            }
        }
    
        @Override
        public final Date to(final LocalDate value) {
            if(null == value) {
                return null;
            } else {
                return new Date(value.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());
            }
        }
    
        @Override
        public final Class<Date> fromType() {
            return Date.class;
        }
    
        @Override
        public final Class<LocalDate> toType() {
            return LocalDate.class;
        }
    }
    

    我必须承认我还没有考虑过这种行为,如果这个转换器用于不同的时区......

    【讨论】:

      猜你喜欢
      • 2019-02-03
      • 2010-09-20
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      相关资源
      最近更新 更多