【问题标题】:How to change the timezone offset in Java for a Date object? [duplicate]如何更改 Java 中 Date 对象的时区偏移量? [复制]
【发布时间】:2020-01-23 23:45:37
【问题描述】:

我有一个 Date 对象,它从数据库中获取日期,该日期已经是 UTC,但时区偏移量会根据应用程序运行的位置进行转换。

因此,如果数据库有日期:2019-09-06 00:00:00.000,并且应用程序在洛杉矶运行,则 Date 对象的偏移量将为 7,输出将如下所示 2019-09-06T07:00Z。由于日期已经是 UTC,我希望它看起来像 2019-09-06T00:00Z,无论它在哪里运行。

Date 类没有setTimeZone() 方法,首先想到的是将其转换为字符串并在最后硬编码00:00Z,这并不干净。有什么想法吗?

更多信息:该列的类型为 DATETIME。数据库:SQL Server。

【问题讨论】:

  • 仅供参考,诸如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 等非常麻烦的日期时间类现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.
  • 指定您的数据库、它的版本以及列的确切数据类型。
  • Date 类不仅设计不佳而且早已过时。 Date 也不能有时区。你问的是不可能的事。

标签: java datetime


【解决方案1】:

我有一个 Date 对象,它从数据库中获取日期,该日期已经是 UTC,

不要。

可怕的Date 类在几年前被现代的java.time 类所取代。

您应该使用OffsetDateTimeTIMESTAMP WITH TIME ZONE 类型的数据库列中检索时刻。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

该值很可能是 UTC。如果您想查看调整到时区的那一刻,请应用ZoneId 以获取ZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

但时区偏移量会根据应用程序运行的位置进行转换。

请注意,虽然 java.util.Date 实际上是 UTC 中的一个时刻,但它的 toString 方法会撒谎。该方法在生成其文本时动态应用 JVM 的当前默认时区。虽然出于善意,但此反功能会造成Date 内存在时区的错觉。

如果您只使用 java.time 类,则不会出现此类问题。无需再次使用java.util.Datejava.sql.DateCalendarGregorianCalendarSimpleDateFormatDateFormat 或其他此类遗留类。

因此,如果数据库的日期为:2019-09-06 00:00:00.000,并且应用程序在洛杉矶运行,则 Date 对象的偏移量将为 7,输出将如下所示 2019-09-06T07: 00Z

这部分对我来说毫无意义。

您的数据库中有正确的数据类型吗? TIMESTAMP WITHOUT TIME ZONE 将是跟踪时刻的错误 类型。此类型只有日期和时间,但缺少与 UTC 或时区偏移的上下文。此类型不能代表时间轴上的特定点。

编辑您的问题以指定准确您的列是什么数据库和什么数据类型。

至少尝试使用 java.time 来消除Date::toString 注入不适当时区的混淆。

Date 类没有 setTimeZone() 方法

java.util.Date 始终采用 UTC,距离 1970 年 1970 年第一刻 UTC 1970-01-01T00:00:00Z 的毫秒数。而已。 (实际上还有更多,一个深埋的时区,没有 getter 方法,会影响 equals 等的行为,但与我们在这里的讨论无关。这个类是一个糟糕的设计。)

首先想到的是将其转换为字符串并在最后硬编码 00:00Z,这不干净。有什么想法吗?

不,你绝对不应该玩这样的游戏。你只会陷入更深的麻烦。直接在数据库中获取您的数据类型,仅使用 Java 中的 java.time 类,您的问题将得到解决。

由于您没有提供足够的详细信息,我无法提供进一步的帮助。搜索堆栈溢出以了解更多信息。这个话题已经讨论过很多次了。

【讨论】:

    【解决方案2】:

    Date 是一个固定的时间点。它可以使用不同的时区显示,但它本身没有时区。

    不过,DateFormatSimpleDateFormat 一样,可以设置为使用特定时区。将日期格式设置为使用TimeZone.getTimeZone("GMT"),您将获得所需的输出。

    顺便说一句,从 Java 8 开始,有一个更新、改进的日期/时间 API:https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

    【讨论】:

      猜你喜欢
      • 2013-07-19
      • 2014-12-28
      • 2012-04-18
      • 1970-01-01
      • 2014-12-10
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      相关资源
      最近更新 更多