2017-04-21 135 views
2

使用LocalDate,我得到了在Period实例中表达的差异。例如:Period中两个ZonedDateTime之间的差异

LocalDate born = LocalDate.of(1990, Month.SEPTEMBER, 30); 
Period myAge = Period.between(born, LocalDate.now()); 
System.out.println("My age is: "+myAge.getYears()+" years "+myAge.getMonths()+" months "+myAge.getDays()+" days."); 

输出:

我的年龄:26年6个月23天

所以,我用期间得到年,月,日的年龄。

我想使用两个时区(美国/太平洋和澳大利亚/墨尔本)与ZoneDateTime一样。例如:

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

我想获得与LocalDate相同的输出。我该怎么办?是否有意义?

预期输出:

我的年龄:26年6个月24天

+2

问题是您需要决定诸如将小时舍入到几天以及在哪个时区进行计数等事情;由于DST规则不同,这两个区域的计数可能不一致。 –

回答

1

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

然后你可以打印你的变量秒。

+0

@JodaStephen这就是为什么我在检查后立即用plusYears和plusMonths重新分配天生变量。 –

3

而不是使用ZonedDateTime出生日期,我建议存储LocalDateZoneId(即在单独的字段/列)。

从两个LocalDate实例获取Period的简单答案是在两者上调用toLocalDate()。您会意识到,存在这样的问题:那些ZonedDateTime实例可能位于不同的时区,这可能需要进行规范化处理。但是,我要强调的是,这个数据的更好存储是两个字段 - LocalDateZoneId

Period p = Period.between(born.toLocalDate(), now.toLocalDate()); 
// warning! the above ignores time-zones, assuming both are the same 

如果您需要两个PeriodDuration(对于剩余秒数)之间的区别,您可以使用此:

Period p = Period.between(born.toLocalDate(), now.toLocalDate()); 
Duration d = Duration.between(born.with(now.toLocalDate()), now); 

最后的选择是使用ThreeTen-Extra。即将发布的v1.1将包含类PeriodDuration,该类将PeriodDuration组合起来,并允许存储两个LocalDateTime实例之间的时间量。

0

主要原因,你应该使用LocalDate表示生日是因为每个人都遵守自己的生日相同的方式,或者换一种说法,每个人都根据他们目前在哪里使用时钟生日观察。如果你出生在法国,而现在居住在美国,而这个时区有不同的时区偏移,那么你不会通过观察法国的当前日期来庆祝你的生日,而是会检查你当前的日期,即本地给你。具有时区支持的时间类应该用于跨地区的事件,例如航班到达和离开跟踪软件。所以使用ZonedDateTime来描述生日没有错,它在语义上是不正确的。

另外,Period实现了TemporalAmount,这明显表示一段时间。所以用它来表示生日(再次)没有错,但它使你的意图不太清楚。生日是时间线上的确切时刻,而不是持续时间,因此总而言之,LocalDate是最佳选择