我有一个 Date 对象,它从数据库中获取日期,该日期已经是 UTC,
不要。
可怕的Date 类在几年前被现代的java.time 类所取代。
您应该使用OffsetDateTime 从TIMESTAMP 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.Date、java.sql.Date、Calendar、GregorianCalendar、SimpleDateFormat、DateFormat 或其他此类遗留类。
因此,如果数据库的日期为: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 类,您的问题将得到解决。
由于您没有提供足够的详细信息,我无法提供进一步的帮助。搜索堆栈溢出以了解更多信息。这个话题已经讨论过很多次了。