我正在尝试从Date
对象(java.util.Date
)生成LocalDate
对象(java.time.LocalDate
),其中我有以下条件:
Date
对象00:00:00
String
为了满足这个标准,我创建了一个测试程序,但是当我修改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
前一天得到结果,为什么会这样?
我的主要目标是能够使用当前的UTC日期捕获Date
对象,并将时间清零(StartOfDay
)。
答案 0 :(得分:2)
当你这样做时:
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(ZoneId.systemDefault()
)替换默认区域(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 的午夜产生。
快速说明:CDT
或PST
这样的短时区名称不是真正的时区。
API使用IANA timezones names(始终采用Region/City
格式,如America/Chicago
或Europe/Berlin
)。
避免使用3个字母的缩写(例如CDT
或PST
),因为它们是ambiguous and not standard。
有lots of different timezones可以使用CDT
作为缩写。发生这种情况是因为时区是区域在历史记录中具有,拥有和将具有的所有不同偏移的集合。仅仅因为许多地方今天使用CDT
,并不意味着它们在过去的同一时期都被使用过,也不会被所有人在未来使用。由于历史不同,会为每个区域创建一个时区。