使用LocalDate,我得到了Period实例中表达的差异。例如:
ZonedDateTime now = ZonedDateTime.now(); // US/Pacific
LocalDate date = LocalDate.of(1990, Month.SEPTEMBER, 30);
LocalTime time = LocalTime.of(23, 55);
ZoneId zone = ZoneId.of("Australia/Melbourne");
ZonedDateTime born = ZonedDateTime.of(date, time, zone);
输出:
我的年龄是:26岁6个月23天
所以,我用时间来计算年,月,日的年龄。
我想使用两个时区(美国/太平洋和澳大利亚/墨尔本)对ZoneDateTime做同样的事情。例如:
{{1}}
我希望获得与LocalDate相同的输出。我该怎么办?它有意义吗?
预期产出:
我的年龄是:26岁6个月24天
答案 0 :(得分:3)
我建议不要将ZonedDateTime
用于出生日期,而是建议存储LocalDate
和ZoneId
(即在单独的字段/列中)。
从两个Period
实例获取LocalDate
的简单答案是在两者上调用toLocalDate()
。正如您将意识到的那样,存在这些ZonedDateTime
实例可能位于不同时区的问题,这可能需要工作才能进行规范化。但同样,我要强调的是,此数据的更好存储空间是两个字段 - LocalDate
和ZoneId
。
Period p = Period.between(born.toLocalDate(), now.toLocalDate());
// warning! the above ignores time-zones, assuming both are the same
如果您需要Period
加上Duration
的两者之间的差异(剩余的秒数),您可以使用:
Period p = Period.between(born.toLocalDate(), now.toLocalDate());
Duration d = Duration.between(born.with(now.toLocalDate()), now);
最后一个选项是使用ThreeTen-Extra。即将发布的v1.1将包含一个PeriodDuration
类,它结合了Period
和Duration
,并允许存储两个LocalDateTime
个实例之间的时间量。
答案 1 :(得分:2)
Period
文档的第一行声明它是基于日期的ISO-8601格式的时间量。它并不适用于XXXTime。
但是,ZonedDateTime
为您提供until
方法,该方法会返回给定ChronoUnit
的号码,直到另一个Temporal
(您的情况为now
)。
例如:
born.until(now, ChronoUnit.YEARS);
将返回26。
一个技巧是将检索到的差异添加到开始日期,然后处理下一个ChronoUnit
例如:
long years = born.until(now, ChronoUnit.YEARS);
born = born.plusYears(years);
long months = born.until(now, ChronoUnit.MONTHS);
born = born.plusMonths(months);
long days = born.until(now, ChronoUnit.DAYS);
然后你可以打印你的变量。
答案 2 :(得分:0)
你应该使用LocalDate
表示生日的主要原因是因为每个人都以同样的方式观察他们的生日,或换句话说,每个人都会根据他们在哪里观察他们的生日目前在。如果你出生在法国,现在住在美国有不同的时区偏移,你不会通过观察法国的当前日期来庆祝你的生日,你会检查你当前的日期本地给你。具有时区支持的时间类应该用于跨越区域的事件,例如,航班到达和离开跟踪软件。因此,使用ZonedDateTime
来描述生日并没有错,它在语义上是不正确的。
此外,Period
实现了TemporalAmount
,这显然代表了一段时间。所以用它来代表生日是(再次)没错,但它会让你的意图不那么清楚。生日是时间轴上的确切时刻,而不是持续时间,所以总而言之,LocalDate
是最佳选择