2

编辑:好的。不幸的是,我不得不承认我对 Java 时间的理解存在严重缺陷,使得这个问题变得毫无意义。我一直认为 System.currentTimeMillis() 返回的是当地时间。为什么?因为当您使用它创建日期时,它只包含该日期,并且没有对时区的引用,但在传递给 System.out.println() 时仍会打印出本地时间。我从来没有想过是 toString()将(UTC)时间转换为当地时区。:(

我想用 Java 创建一个客户端-服务器应用程序。时间起着重要的作用。因此,我决定暂时将 GMT/UTC 标准化。我还从经验中知道,许多用户的 PC 的时间和/或时区完全错误。最后,我想有比毫秒更精确的时间。

所以我创建了一个类,它在开始时连接到 Internet,并计算到 UTC 的偏移量,与本地时间和时区无关。换句话说,我有一个静态 Java 方法,它以纳秒为单位返回 UTC 时间,并且可以在任何 PC 上独立于本地时间设置工作。

现在,我的问题是我想使用 JSR 310 来操纵时间(实际上是 Java 7 反向端口),我看不到如何定义一个不基于本地时间的时钟。

在我看来,Clock.millis() 和 Clock.instant() 方法必须使用本地时间才能正常工作[编辑:因为这些方法盲目地返回 System.currentTimeMillis(),与设置的时区属性无关]。所以我基本上必须将我的 UTC 时间转换为本地时间,以创建一个 Instant,这样我就可以创建一个 UTC ZonedDateTime,它将本地时间再次转换回 UTC。这简直是​​疯了。如果我在 Clock.millis() 和 Clock.instant() 中使用 UTC 时间,然后创建一个 UTC ZonedDateTime ,我不想与之有任何关系的本地时间偏移会被应用两次

从 UTC 转换到本地然后再转换回来是很昂贵的,所以我真的很希望能够使用纯粹的 UTC。我正在开发一个实时游戏,而不是一个网络应用程序,这样小的延迟将毫无意义。

我可以只返回 UTC 时间,并“假装”时区是“本地”以获得正确的数字,但是事情可能会在 DST 边界处中断,并且会使将时间转换为其他时区变得更加复杂。

这是我的时钟课

4

2 回答 2

2

在我看来,方法 Clock.millis() 和 Clock.instant() 必须使用本地时间才能正常工作。

绝对不。Instant与时区无关,并millis记录在:

这将返回基于毫秒的瞬间,从 1970-01-01T00:00 UTC 开始测量。这相当于 System.currentTimeMillis() 的定义。

再说一次,这不是当地时间。它使用本地系统时钟,但这与说它是正常意义上的本地时间不同。

目前还不清楚您真正想要做什么,但我至少会尝试根据Instant,而不是ZonedDateTime. 关键Instant是它只是时间线上的一个点;它没有时区,甚至没有日历系统。只要您使用的所有东西(跨所有系统)使用相同的概念时间线和相同的时期(例如,如果您在任何地方都使用 JSR-310),那么您应该没问题。Instant使用与 Java 相同的时代 - UTC 的 1970 年初。

当然,您可能仍然希望拥有自己的时间来源,但显然您需要考虑网络延迟等。考虑使用标准化的 NTP 或类似的东西,而不是尝试构建自己的系统。然后,您可能希望对其进行调整以实现您Clock自己的子类。如果其他一切都只是Clock.

于 2013-04-14T16:32:18.827 回答
0

解决方案是:您可以更改时区:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

因此,要在时钟中使用 UTC,但仍然能够在本地用户时区显示时间值,您必须首先获取并保存默认时区,然后如上所述仅将其替换为 UTC。

然后,JVM 会认为您的本地时区是 UTC,因此如果 Clock 实际上返回 UTC 毫秒和即时,那么一切都会一起工作。然后,当您想要显示时间值时,您将获取原始默认时区,并使用该时区创建另一个时钟实例,但 millis 和 Instant 方法保持不变,因此它们仍然返回 UTC 时间。

主要好处是现在任何地方都不需要时区转换,除非在本地时间显示给用户。

[编辑再想一想,这价值有限,因为其他一切仍将使用 System.currentTimeMillis() (包括通过 java.util.Date 和 Calendar 间接使用)。所以一个人可能永远无法解决所有与时间相关的问题。]

于 2013-04-14T17:23:34.040 回答