java - 当我尝试在连接时设置它时,将 mysql 中的日期时间和时间戳从默认时区转换为 Java 中的 UTC 不起作用

标签 java mysql datetime timezone

我使用的 mysql 数据库是这样配置的:

mysql> SELECT @@global.time_zone, @@session.time_zone;
+--------------------+---------------------+
| @@global.time_zone | @@session.time_zone |
+--------------------+---------------------+
| SYSTEM             | SYSTEM              |
+--------------------+---------------------+

运行数据库的 centos 机器正在使用 PST。

我有一个包含不同时间对象的表,我想确保当我在我的程序中读取它们时它们是 UTC 时间。

描述我的表:

| start_date    | timestamp           | NO   | MUL | CURRENT_TIMESTAMP   |                     
| update_date   | datetime            | YES  | MUL | NULL                |           

select start_date, update_date from mytable limit 1;

+---------------------+---------------------+
| start_date          | update_date         |
+---------------------+---------------------+
| 2015-11-02 07:42:15 | 2015-11-02 07:48:40 |
+---------------------+---------------------+

以上时间均为太平洋标准时间。

在 Java 中,我这样连接到数据库:

    String dbStr = String.format("jdbc:mysql://%s:%d/%s", sqlHost, sqlPort, sqlDb);

    Properties connectionProps = new Properties();
    connectionProps.put("user", USER);
    connectionProps.put("password", PASSWORD);
    connectionProps.put("useLegacyDatetimeCode", "false");
    connectionProps.put("serverTimezone", "UTC");

但是,当我使用上面的查询读取日期时,它们仍然显示为 PST。当我提取列时,我可以稍后在 Java 中转换日期,但是有没有办法在连接时执行此操作。我在 Python 中通过修改游标时区来完成此操作,但是,在 Java 中,我什至必须使用 PrepareStatement 而不是 Statement 来实现此目的。

我正在使用 mysql-connector-java-5.1.36。过去,当我试图强制将编码从拉丁语更改为 UTF-8 时,我遇到过类似的问题,但我从未让它在连接级别工作。同样,在 Python 中我能够实现这一点,但在 Java 中却做不到。

我认为它可能与这种语法有关,因此我从

String.format("jdbc:mysql://%s:%d/%s?useLegacyDatetimeCode=false&serverTimezone=UTC", sqlHost, sqlPort, sqlDb)

使用属性。

我怀疑是问题所在,我找不到关于如何补救的证据告诉我的连接,嘿,服务器正在以 PDT 格式存储日期,但是当你给我我想要的信息时,它是 UTC 格式的。

谢谢...阿姆罗

事实证明问题的根本原因是 select 语句在查询中将日期对象转换为字符串:

SELECT date_format(start_date, '%Y-%m-%dT%H:%i:%s'), 
       date_format(update_date, '%Y-%m-%dT%H:%i:%s') from myTable;

如果删除 date_format 并保留日期对象,则会发生时区转换。然后,您可以根据需要将日期对象格式化为字符串。但是,请注意 JVM 运行的时区,因为转换会考虑到这一点。使用 TZ 设置与数据库的连接告诉您的程序数据库中的数据位于哪个 TZ 中。运行 JVM 的 TZ 将决定如何将日期/时间从数据库转换到您的程序中。您可以将参数传递给 JVM 或设置默认 TZ,以确保您的 JVM 不受其运行环境的影响。

最佳答案

事实证明问题的根本原因是 select 语句在查询中将日期对象转换为字符串:

SELECT date_format(start_date, '%Y-%m-%dT%H:%i:%s'), 
       date_format(update_date, '%Y-%m-%dT%H:%i:%s') from myTable;

如果删除 date_format 并保留日期对象,则会发生时区转换。然后,您可以根据需要将日期对象格式化为字符串。但是,请注意 JVM 运行的时区,因为转换会考虑到这一点。使用 TZ 设置与 DB 的连接告诉您的程序数据库中的数据位于哪个 TZ。您的 JVM 在其中运行的 TZ 将决定如何将日期/时间从 db 转换到您的程序中。您可以将参数传递给 JVM 或设置默认 TZ,以确保您的 JVM 不受其运行环境的影响。

关于java - 当我尝试在连接时设置它时,将 mysql 中的日期时间和时间戳从默认时区转换为 Java 中的 UTC 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33507471/

相关文章:

java - 在 JPA-/CrudRepository 中的自定义 @Query 中使用 SQL-IN 子句并将列表或设置为传递参数?

MySQL计算日期差异如果大于35天

php - 添加项目下拉列表

MYSQL 左连接在索引列上速度极慢

java - 为什么 Java SimpleDateFormat().parse() 打印出奇怪的甲酸盐?

c# - DateTime.Now.AddDays(-1) 将获得恰好 24 小时前的日期时间,但我如何在特定时间获得昨天的时间?

java - 来自 ExecutorService 的 CompletableFuture

java - Spring ORM JNDI Tomcat - 没有可用的实际事务的 EntityManager

java - 如何在 android 中动态添加多个水平 ListView ,如 android 中的 play store 应用程序

python - 如何将带有日期时间的 DataFrame 列拆分为两列 : one with dates and one with times of the day?