Java Instant Datetime 如何获取仅带时区偏移的日期时间?没有区域信息

Java Instant Datetime how to get the Datetime with timezone offset only? without the region information

我正在使用 Java Instant 来获取当前日期时间信息,但是 returns 对我来说 Z[Europe/Berlin]。如何获得唯一的 Datetime 时区偏移信息?

以下是我的代码:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;


public class Test {
    public static void main(String[] args) {
        Instant instant = Instant.now();

        System.out.println("Current Time : " + instant);

        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println("LocalDateTime : " + localDateTime);

        ZonedDateTime zonedDateTime1 = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println("ZonedDateTime1: " + zonedDateTime1);
    }
}

以下是我的输出:

Current Time : 2022-04-13T08:22:35.362644Z
LocalDateTime : 2022-04-13T10:22:35.362644
ZonedDateTime1: 2022-04-13T10:22:35.362644+02:00[Europe/Berlin]

我的预期输出是:

expected output: 2022-04-13T10:22:35.362644+02:00

如何使用 Instant 获得预期输出 2022-04-13T10:22:35.362644+02:00?我知道我可以执行 substring(),但我不想那样做。我正在寻找一些直接的方法来实现这一目标。请提供一些建议。

此外,我不希望传递区域信息,因为应用程序可以跨多个区域访问,所以不希望在代码中对区域进行硬编码。

我不明白你为什么需要 Instant。下面的代码给出了你想要的输出:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Test {

    public static void main(String[] args) {
        System.out.println(ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
    }
}

当我运行上面的代码时,我得到以下输出:

2022-04-13T12:25:31.1157466+03:00

我的本地时区比 UTC 早三个小时。

tl;博士

How do I get the only Datetime information with timezone offset?

OffsetDateTime
.now() 
.toString()

2022-04-13T22:47:58.123793+02:00

或者,明确说明您的 desired/expected 时区,而不是隐式依赖 JVM 当前的默认时区。

OffsetDateTime
.now(
    ZoneId.of( "Europe/Berlin" )
) 
.toString()

OffsetDateTime

您问的是:

How do I get the only Datetime information with timezone offset?

要表示一个 time-of-day 的日期,如从 UTC 子午线偏移 hours-minutes-seconds 的某个数字中所见,请使用 OffsetDateTime class.

呼叫 OffsetDateTime.now() implicitly applies the offset of your JVM’s current default time zone.

OffsetDateTime odt = OffsetDateTime.now() ;  // Uses current offset.

看到 code run live at IdeOne.com.

2022-04-13T20:47:58.059193Z

末尾的Z表示与UTC的偏移量为零,发音为“Zulu”。

IdeOne.com 站点碰巧使用 UTC 本身的默认时区 a.k.a。 “祖鲁时间”。因此,让我们指定一个时区以查看不同的偏移量。

OffsetDateTime odt2 = OffsetDateTime.now( ZoneId.of( "Europe/Berlin" ) ) ;  // Use the offset currently in effect for this particular time zone.

2022-04-13T22:47:58.123793+02:00

ZonedDateTime

通常最好使用完整的时区而不是仅仅偏移。时区是特定地区人民使用的偏移量的过去、现在和未来变化的命名历史,由他们的政治家决定。

ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "Europe/Berlin" ) ) ;

2022-04-13T22:47:58.126001+02:00[Europe/Berlin]

但有时我们需要处理偏移量而不是区域。 SQL 使用数据库是一个重要的例子,因为 SQL 标准只是为偏移而不是时区编写的。

Instant

您问的是:

How can I get my expected output 2022-04-13T10:22:35.362644+02:00 using Instant?

你不能。

Instant class 表示从 UTC 子午线偏移为零 hours-minutes-seconds 的时刻。根据定义,Instant 对象始终“采用 UTC”,即偏移量为零。

如果您手头有 Instant,您可以调整到时区或时差。与其假设您知道正确的偏移量,我建议您通过时区让 java.time 查找当前有效的偏移量。

ZoneId z = ZoneId.of( "Europe/Berlin" ) ;
ZonedDateTime zdt = myInstant.atZone( z ) ;
OffsetDateTime odt = zdt.toOffsetDateTime() ;

提示:请注意,政治家会以惊人的频率和令人不安的小预警来更改时区规则,从而更改时差。如果您感兴趣的任何区域发生变化,请务必使 tzdata 保持最新。您会在 (a) 您的 JVM,(b) 您的主机操作系统,以及 (c) 可能在数据库服务器等辅助系统中找到 tzdata 文件。

LocalDateTime

永远不要使用 LocalDateTime class 跟踪时刻,时间轴上的特定点。 class 故意缺少时区或 offset-from-UTC 的上下文。 LocalDateTime 的对象仅携带 日期和 time-of-day,仅此而已。

我无法想象在任何情况下调用 LocalDateTime#nowLocalDateTime.ofInstant 都是正确的做法。这样做时,您会故意丢弃重要信息(时区或偏移量)。