LocalDate 不一致

LocalDate inconsistency

我正在尝试从 LocalDate 对象 (java.time.LocalDate) 生成一个 Date 对象 (java.util.Date),其中我有以下条件:

为了满足这个标准,我创建了一个测试程序,但是当我修改 LocalDate 的某个 属性 时,我得到了有趣的结果。请参阅下面的代码:

  public static void main (String args[]) {
    Long processingDaysInPast = 0L;
    LocalDate createdDate1 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    LocalDate createdDate2 = LocalDate.now(Clock.systemUTC()).minusDays(processingDaysInPast);
    System.out.println(createdDate1);
    System.out.println(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC));
    System.out.println(Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)));
    System.out.println((createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
    System.out.println(Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
}

输出:

 2017-08-14
 2017-08-14T00:00:00Z
 Sun Aug 13 19:00:00 CDT 2017
 2017-08-14
 2017-08-14T05:00:00Z
 Mon Aug 14 00:00:00 CDT 2017

当我添加值 Date.from(createdDate1.atStartOfDay().toInstant(ZoneOffset.UTC)) 时,我得到了日期的预期输出,带有 00:00:00 时间字段。但是,如果我不加这个参数,比如:Date.from(createdDate2.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())我得到的结果是前一天,在19:00:00这是为什么?

我的主要目标是能够捕获一个 Date 对象,使用当前 UTC 日期,并将时间清零 (StartOfDay)。

当你这样做时:

createdDate2.atStartOfDay().atZone(ZoneId.systemDefault())

首先,createdDate2.atStartOfDay()returns一个LocalDateTime,相当于2017-08-14午夜。 LocalDateTime 不支持时区。

当您调用 atZone(ZoneId.systemDefault()) 时,它会在 系统的默认时区ZoneId.systemDefault())。在你的情况下,默认时区不是 UTC(它是 "CDT",所以它在 CDT 午夜 - 只需执行 System.out.println(ZoneId.systemDefault()) 来检查你的默认时区是什么)。

要获取 UTC 午夜的日期,您可以将默认时区 (ZoneId.systemDefault()) 替换为 UTC (ZoneOffset.UTC):

Date.from(createdDate2.atStartOfDay().atZone(ZoneOffset.UTC).toInstant())

或(更短的版本):

Date.from(createdDate2.atStartOfDay(ZoneOffset.UTC).toInstant())

当然你也可以像 createdDate1:

Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))

它们都是等价的,结果是 UTC 午夜。


快速说明:像 CDTPST 这样的短时区名称不是真正的时区。
API 使用 IANA timezones names(格式总是 Region/City,如 America/ChicagoEurope/Berlin)。 避免使用 3 个字母的缩写(如 CDTPST),因为它们是 ambiguous and not standard.

lots of different timezones可以用CDT作为缩写。发生这种情况是因为时区是一个区域在历史期间拥有、拥有和将拥有的所有不同偏移量的集合。仅仅因为今天很多地方使用CDT,并不意味着它们在过去的同一时期都使用过,也不意味着将来会被所有人使用。由于历史不同,为每个地区创建了一个时区。