Java LocalDate不一致

Java LocalDate不一致,java,date,time,java-time,localdate,Java,Date,Time,Java Time,Localdate,我正试图从LocalDate对象(java.time.LocalDate)中生成一个Date对象(java.util.Date),其中我有以下条件: 允许使用一个参数,该参数可以从Date对象中减去特定天数 日期和时间是否为UTC当前的日期和时间 将时间放在一天的开始,即00:00:00 时区标记(即CDT或UTC)是不相关的,因为我从字符串 为了满足这个标准,我创建了一个测试程序,但是当我修改LocalDate的某个属性时,我得到了有趣的结果。见下面的代码: public static

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

  • 允许使用一个参数,该参数可以从
    Date
    对象中减去特定天数
  • 日期和时间是否为UTC当前的日期和时间
  • 将时间放在一天的开始,即
    00:00:00
  • 时区标记(即CDT或UTC)是不相关的,因为我从
    字符串
为了满足这个标准,我创建了一个测试程序,但是当我修改
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()
返回一个
LocalDateTime
,该值相当于2017-08-14午夜的
LocalDateTime
不支持时区

调用
atZone(ZoneId.systemDefault())
时,它会创建一个
ZonedDateTime
,其中包含系统默认时区中的相应日期(2017-08-14)和时间(午夜)(
ZoneId.systemDefault()
)。在您的情况下,默认时区不是UTC(它是“CDT”,所以CDT是午夜-只需执行
System.out.println(ZoneId.systemDefault())
检查默认时区即可

要获取UTC中午夜的日期,可以使用UTC(
ZoneOffset.UTC
)替换默认区域(
ZoneId.systemDefault()
):

或(较短版本):

当然,您也可以使用与
createdData1
相同的方法:

Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))
它们都是等效的,将导致UTC午夜时分


请注意:像
CDT
PST
这样的短时区名称不是真正的时区。
API使用的格式(始终为
地区/城市
,如
美国/芝加哥
欧洲/柏林
)。 避免使用三个字母的缩写(如
CDT
PST
),因为它们是


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

主要是因为时区并不无关-UTC和CDT中的相同日期时间等于不同的
瞬间(即从历元开始的秒数)。当前时区中的一天开始时间与UTC中的一天开始时间不同。这就是你所看到的。
Date.from(createdDate2.atStartOfDay(ZoneOffset.UTC).toInstant())
Date.from(createdDate2.atStartOfDay().toInstant(ZoneOffset.UTC))