【问题标题】:Java & MySQL timezone issueJava & MySQL 时区问题
【发布时间】:2024-01-16 15:07:01
【问题描述】:

我正在尝试将 java 中的字符串日期值转换为日期并尝试将其存储在 mysql 表中。

下面的代码sn-p:

DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
String string = "07/24/2013 17:57:52 UTC";
Date a = dfm.parse(string);
System.out.println(a);

我的问题是上面的代码总是返回以下控制台输出: 2013 年 7 月 24 日星期三 17:57:52 PDT

我不知道为什么时区会改变,当我试图将其放入数据库时​​,它会以“2013-07-24 17:57:52”格式存储它。我不确定为什么上面的代码会在 PDT 中返回我的时区?

你们能解释一下吗?我的意图是存储一个 UTC 日期,该日期将作为输入并将其存储到 MySQL 时间戳字段中。

提前致谢。

【问题讨论】:

  • 请告诉我们您是如何将其存储在数据库中的。此外,您的输入是否 必须 结尾有“UTC”,还是可以删除? (我们不知道您的输入来自哪里。)其余大部分都很容易修复......
  • 什么是mysql的时区设置?使用它来检查:*.com/a/930914/791406
  • @JonSkeet 感谢您的回复。我可以以编程方式删除 UTC。但这将如何提供帮助。从 String 变量中删除 UTC 仍然显示与上面相同。我也在使用 JPA 来保存数据。 "testdate testobj = new testdate(); testobj.setAddDate(new Timestamp(a.getTime())); em.persist(testobj);"
  • @raffian 也感谢您的回复..我知道我可以在 mysql 中设置默认时区。但是有什么方法可以让我们跳过它并以编程方式做一些事情。
  • java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到modern Date-Time API。查看this answerthis answer 了解如何将java.time API 与JDBC 结合使用。

标签: java mysql date timezone timestamp


【解决方案1】:

是的,如果您可以将字符串修复为不包含时区,那就更简单了。首先,您需要了解Date 对象根本不包含时区——它只是一个时间点。

接下来,当我们尝试解析以 UTC 指定的日期/时间时,您应该在 SimpleDateFormat 中设置它:

DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
dfm.setTimeZone(TimeZone.getTimeZone("UTC"));

现在我希望 JPA 会做正确的事。您至少会正确的值传递给Timestamp 构造函数。

不过MySQL documentation的这一部分让我很紧张:

MySQL 将 TIMESTAMP 值从当前时区转换为 UTC 进行存储,然后从 UTC 转换回当前时区进行检索。 (这不会发生在其他类型,例如 DATETIME。)

听起来您可能想改用DATETIME 字段来停止此时区转换。将连接的时区设置为 UTC 将有助于存储它,但您仍然需要担心获取时会发生什么。 (当涉及到日期/时间类型时,数据库非常混乱,IMO。这只是另一个例子......)另一方面,如果你也用 Java 取回数据,我会 希望它可以透明地工作。至少值得尝试一下……

【讨论】:

    【解决方案2】:

    您的格式字符串中缺少时区部分。因此,“UTC”被忽略。 试试这个:

    DateFormat dfm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss z"); // added "z"
    // then the rest of your code as-is
    String string = "07/24/2013 17:57:52 UTC";
    Date a = dfm.parse(string);
    System.out.println(a); // prints "Wed Jul 24 19:57:52 CEST 2013" for me
    

    根据@JonSkeet 的警告,可以通过time_zone 会话变量检查或更改MySQL“当前时区”。

    要么确保您的会话设置为 UTC (SET time_zone = '+0:00'),要么改用 DATETIME 类型。

    【讨论】:

    • 我不想在本地时区转换它。我想按原样保留数据...我应该将此值转换为时间戳。
    • @SomnathGuha 如果您想(仅)在应用程序级别处理时区,那么不要使用TIMESTAMP 类型,而是使用DATETIME 类型。