如何在java中检查LocalDateTime实例是本地还是UTC?

sar*_*mar 3 java utc java-time localdate

我想查找我的LocalDateTime实例是否包含本地日期和时间或UTC日期和时间(如DateTime.KindC#中的属性)

LocalDateTime date1=LocalDateTime.now(); // it is local

LocalDateTime date2=LocalDateTime.now(ZoneId.of("UTC")); // it is UTC
Run Code Online (Sandbox Code Playgroud)

(date1.getKind() == Kind.UTC || date1.getKind() == Kind.Local)在Java中有类似的东西吗?

小智 5

LocalDateTime对象本身不存储时区信息-它只有日期和时间相关的字段:日,月,年; 小时,分钟,秒和纳秒.但该now方法使用时区或偏移量来获取这些字段的正确值.

这是因为对"今天是星期几?"这一问题的回答."现在几点?" 并不像我们想象的那么简单.

通常认为答案就像查看我们的日历/手机/任何内容并查看当前日期/时间一样简单.但技术上正确的答案是:"这取决于".

这基本上取决于你所处的位置.此时,世界上每个地方都有自己的当地日期和时间.例如,在7月5 ,2017年:虽然它是在圣保罗14H(或14:00),这是下午6点在伦敦和下午5点在UTC,但在东京那是凌晨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);
Run Code Online (Sandbox Code Playgroud)

这段代码的作用是:"以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.

因此,使用a LocalDateTime可以获取值,但是您无法知道这些值来自哪个时区,因为它不会保留此信息.

如果您需要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
Run Code Online (Sandbox Code Playgroud)

但是,如果你使用等价物ZoneId.of("UTC"),equals方法返回false.所以你也可以检查是否z.getZone().getId()等于ZUTC.有OffsetDateTime,它是类似的:

OffsetDateTime odt = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(odt.getOffset().equals(ZoneOffset.UTC)); // true
Run Code Online (Sandbox Code Playgroud)

随着Instant你不需要检查,因为它总是在UTC.

您可以在Oracle的日期/时间教程中检查所有可用类型.


二者ZonedDateTimeOffsetDateTime可以转换到一个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();
Run Code Online (Sandbox Code Playgroud)

这样,dt变量将具有与UTC中当前日期/时间对应的所有日期和时间字段(日/月/年,小时/分钟/秒/纳秒).但它不会保留任何时区/偏移信息,因此LocalDateTime对象本身无法知道这些值来自哪个时区.