pet*_*bal 6 java mysql timezone date jdbc
我有时区相关的问题。
我在 JAVA 和 MySql 数据库中有一个程序。我不使用任何 ORM,但我有使用 mysql 连接器 java v 6.0.4 的自定义 jdbc 库
我将设置作为连接字符串的一部分发送为:
serverTimezone - America/Chicago
useTimezone - true
useJDBCCompliantTimezoneShift - false
useLegacyDatetimeCode - false
Run Code Online (Sandbox Code Playgroud)
我尝试从 db eg 中选择一个日期2019-02-13。
数据库位于美国/东部时区,运行java程序的服务器位于美国/芝加哥时区。
无法更改任何服务器的位置/时区。
在 Java 中,我一天倒退了一个日期 ( 2019-02-12)。问题是由时间戳引起的 -
1550034000是2019-02-13 00:00:00在美国/东部
但
1550034000是2019-02-12 23:00:00在美国/芝加哥
因此,我的java.sql.Date对象带有 date 2019-02-12。添加时区偏移没有帮助,因为时间信息是从日期截断的。
你能提出一些关于如何在没有时区偏移的情况下获得正确日期的解决方案吗?
编辑:我正在使用serverTimezone设置,但我不确定值是否应该是数据库正在使用的时区,或者它只是覆盖运行应用程序的 JVM/服务器的时区。
首先,我已经读到你不能在你的情况下,但对于其他读者,我想说明一般建议是在 UTC 中运行所有内容,至少当你跨越多个时区时。所以这将是您问题的最佳解决方案。
其次,正如我和戈德汤普森在评论中提到的那样,第二个最好的解决方案是将日期处理为LocalDate,而不是java.sql.Date。虽然后者只是假装没有时间,但它确实存在设计问题,很难解决您的问题。ALocalDate确实是一个没有时间和时区的日期,所以应该是一个更安全的赌注(除了LocalDate听说过错误地相互转换的数据库驱动程序;我保持手指交叉;再次运行所有内容UTC 也会消除这些错误)。编辑:假设您可以修改自定义 JDBC 库,以下是LocalDate从 a获取 a的方法ResultSet:
LocalDate correctDateDirectlyFromDatabase
= yourResultSet.getObject("yourDateColumn", LocalDate.class);
Run Code Online (Sandbox Code Playgroud)
它至少需要 JDBC 4.2,你可能已经有了。
如果以上都不对您可用,这里有一种方法可以修复Date您从数据库中获得的错误信息。这有点黑客,但会起作用。
import java.sql.Date;
// …
// Modern ID of the time zone previously known as US/Eastern
ZoneId datebaseTimeZone = ZoneId.of("America/New_York");
Date dateFromDatabase = new Date(TimeUnit.SECONDS.toMillis(1_550_034_000));
System.out.println("Date as retrieved from database (or pretending): " + dateFromDatabase);
long epochMillis = dateFromDatabase.getTime();
ZonedDateTime dateTime = Instant.ofEpochMilli(epochMillis)
.atZone(datebaseTimeZone);
LocalDate realDate = dateTime.toLocalDate();
// Sanity check
if (! realDate.atStartOfDay(datebaseTimeZone).equals(dateTime)) {
throw new IllegalStateException("Failed to convert date correctly from " + datebaseTimeZone + " time zone");
}
System.out.println("Date is " + realDate);
Run Code Online (Sandbox Code Playgroud)
当我在美国/芝加哥时区运行它时,它打印出:
Run Code Online (Sandbox Code Playgroud)Date as retrieved from database (or pretending): 2019-02-12 Date is 2019-02-13
我试过在其他时区运行它。在某些时区打印第一行2019-02-12,在其他时区打印2019-02-13。最后一行打印2019-02-13在我尝试过的所有时区。
现在我给了你一个LocalDate. 很好,这是您在进一步处理中应该使用的。如果您需要java.sql.Date另一个您不想更改的旧 API,请通过以下方式转换回正确的 API java.sql.Date:
Date oldfashionedJavaSqlDate = Date.valueOf(realDate);
System.out.println("Date converted back to " + oldfashionedJavaSqlDate);
Run Code Online (Sandbox Code Playgroud)
日期转换回 2019-02-13
当我说正确时,它要求没有人篡改 JVM 的默认时区,这对于在 JVM 中运行的任何程序来说都很容易。
链接: Oracle 教程:解释如何使用 java.time 的日期时间。
| 归档时间: |
|
| 查看次数: |
2372 次 |
| 最近记录: |