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))