【问题标题】:Timezone issues with MySQL and clj-timeMySQL 和 clj-time 的时区问题
【发布时间】:2014-09-27 04:26:23
【问题描述】:

我在 MySQL 中有一个表。

create table demo ( theDate datetime );

我插入了两个日期,一个是夏令时,一个不是。

(require '[clj-time.core :as t])
(require '[clj-time.coerce :as coerce])
(require '[korma.core :as k])

(k/insert :demo (values {:theDate (coerce/to-sql-date (t/date-time 2014 01 01))}))
(k/insert :demo (values {:theDate (coerce/to-sql-date (t/date-time 2014 06 01))}))

从我的 MySQL 客户端看来,正确的值已输入:

mysql> select * from demo;
+---------------------+
| theDate             |
+---------------------+
| 2014-01-01 00:00:00 |
| 2014-06-01 00:00:00 |
+---------------------+

当我使用 Korma 进行选择时(我不认为 Korma 在 JDBC 之上做任何相关的事情),我在非夏令时日期中得到一个时区差异。

=> (k/select :demo)
[{:theDate #inst "2014-01-01T00:00:00.000000000-00:00"}
 {:theDate #inst "2014-05-31T23:00:00.000000000-00:00"}]

当我选择日期时:

(map #(-> % :theDate coerce/from-sql-date t/month) (k/select :demo))
(1 5)

而我本来希望得到(1 6)(我故意把日期放在一个月的边界上来说明)。当我使用date 而不是datetime MySQL 类型时,也会发生同样的事情。

我错过了什么?如何插入[(t/date-time 2014 01 01) (t/date-time 2014 06 01)]并返回(1 6)

【问题讨论】:

  • 您应该将时间戳存储为 UTC,并在需要显示时将其转换为本地。
  • 或存储unix时间戳

标签: mysql jdbc clojure timezone sqlkorma


【解决方案1】:

您获得的结果取决于 JVM 的默认时区。您可以通过主机操作系统为您提供的任何机制来解决此问题。但根据我的经验,通常最好将 JVM 明确强制为已知值。

这是通过命令行上的属性实现的,或者在 leiningen project.clj

:jvm-opts ["-Duser.timezone=UTC"]

【讨论】:

  • 非常感谢!
  • 添加一些谷歌关键字/反向链接:我的问题是我会将 UTC 存储在 MySQL 数据库中,我会在 clojure 中查询它,它会突然变成当地时间,再多的强制也不会将其解释为 UTC。我要求clj-time 维护者在他们的文档中的某处写下这一点:github.com/clj-time/clj-time/issues/233
【解决方案2】:

我们也遇到了这种情况,最终使用了 korma 的 exec-raw 并指定:

at time zone 'utc' as theData

真正返回正确的时区。

【讨论】:

  • 谢谢! sw1nn 的回答解决了这个问题,但我认为exec-raw 不适用于选择?当我(k/exec-raw "select * from demo") 时,我得到SQLException Can not issue executeUpdate() for SELECTs com.mysql.jdbc.SQLError.createSQLException (SQLError.java:1074)
猜你喜欢
  • 1970-01-01
  • 2011-09-08
  • 2013-09-03
  • 1970-01-01
  • 2019-01-12
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
相关资源
最近更新 更多