LocalDateTime
对象本身不存储时区信息——它只有日期和时间相关字段:日、月和年;小时、分钟、秒和纳秒。但是该now
方法使用时区或偏移量来获取这些字段的正确值。
这是因为“今天是星期几?”这些问题的答案。“现在几点了?” 并不像我们想象的那么简单。
通常认为答案就像查看我们的日历/手机/其他任何东西并查看当前日期/时间一样简单。但技术上正确的答案是:“视情况而定”。
这基本上取决于你在哪里。此时此刻,世界上每个地方都有自己的本地日期和时间。例如,2017年7 月 5日:圣保罗是 14 小时(或下午 2 点),伦敦是下午 6 点,UTC 是下午 5 点,但东京是第二天凌晨 2 点(7 月 6日) ) .
世界上每个地区都有特定的规则来确定他们在历史上的当地时间,当然这会影响他们的当地日期。将国家/城市/地区映射到这些规则的概念是时区。
这就是该now
方法需要时区的原因。该ZoneId
对象加载所有时区数据以检查该区域中的当前日期和时间,并相应地调整日/月/年/小时/分钟/秒/纳秒值。不接收参数 ( LocalDateTime.now()
) 的版本将使用系统默认时区,因此 API 最终总是使用某个时区。
时区(或偏移量ZoneOffset.UTC
,例如LocalDateTime
- 丢弃。
因此,这个概念可能与您的想法有些不同。如果我做:
// ZoneOffset.UTC is equivalent to ZoneId.of("UTC")
LocalDateTime date = LocalDateTime.now(ZoneOffset.UTC);
这段代码的作用是:“以 UTC 格式获取当前日期和时间,只获取日期和时间字段,丢弃时区/偏移信息”。
当我运行此代码时,UTC 中的当前日期/时间为2017-09-25T12:15:43.570Z
,因此LocalDateTime
的值等于2017-09-25T12:15:43.570
(没有任何时区信息,只有日期和时间字段)。如果我now()
不带参数调用,它将使用 JVM 默认时区(在我的情况下,它是America/Sao_Paulo
),并且值将是2017-09-25T09:15:43.570
.
因此,LocalDateTime
您可以使用 a 获取值,但您无法知道这些值来自哪个时区,因为它不会保留此信息。
如果您想要 UTC 日期,则必须使用其他类,旨在保留此信息:
Instant.now()
- 这将始终获得当前的 UTC 时刻
OffsetDateTime.now(ZoneOffset.UTC)
- 使用它您可以查询日期和时间字段(例如getDayOfMonth()
或getHour()
)
ZonedDateTime.now(ZoneOffset.UTC)
- 对于 UTC,它与 相同OffsetDateTime
,但如果您使用不同的时区,它会处理所有时区特定数据,例如夏令时更改。
要检查此类对象是否为 UTC,一种方法是使用以下getZone()
方法:
ZonedDateTime z = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(z.getZone().equals(ZoneOffset.UTC)); // true
但是如果你使用等价物ZoneId.of("UTC")
,equals
方法返回false
。因此,您还可以检查是否z.getZone().getId()
等于Z
或UTC
。与OffsetDateTime
类似:
OffsetDateTime odt = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(odt.getOffset().equals(ZoneOffset.UTC)); // true
Instant
你不需要检查,因为它总是在UTC 。
您可以在Oracle 的日期/时间教程中查看所有可用的类型。
两者ZonedDateTime
和OffsetDateTime
都可以LocalDateTime
使用以下toLocalDateTime()
方法转换为:
// dt will have the current date and time in UTC
LocalDateTime dt = ZonedDateTime.now(ZoneOffset.UTC).toLocalDateTime();
// or
LocalDateTime dt = OffsetDateTime.now(ZoneOffset.UTC).toLocalDateTime();
这样,该dt
变量将具有与 UTC 中的当前日期/时间相对应的所有日期和时间字段(日/月/年、小时/分钟/秒/纳秒)。但它不会保留任何时区/偏移信息,因此LocalDateTime
对象本身无法知道这些值来自哪个时区。