我有一个远在过去的约会。
我发现了这个日期和现在之间的持续时间。
现在我想知道 - 多年来这有多少?
我使用Java8 API提出了这个解决方案。
这是一个非常糟糕的解决方案,因为我必须首先手动将持续时间转换为天数,因为否则会有UnsupportedTemporalTypeException
- LocalDate.plus(SECONDS)
因任何原因都不受支持。
即使编译器允许这个调用。
将Duration
转换为年份的可能性是否较低?
LocalDate dateOne = LocalDate.of(1415, Month.JULY, 6);
Duration durationSinceGuss1 = Duration.between(LocalDateTime.of(dateOne, LocalTime.MIDNIGHT),LocalDateTime.now());
long yearsSinceGuss = ChronoUnit.YEARS.between(LocalDate.now(),
LocalDate.now().plus(
TimeUnit.SECONDS.toDays(
durationSinceGuss1.getSeconds()),
ChronoUnit.DAYS) );
/*
* ERROR -
* LocalDate.now().plus(durationSinceGuss1) causes an Exception.
* Seconds are not Supported for LocalDate.plus()!!!
* WHY OR WHY CAN'T JAVA DO WHAT COMPILER ALLOWS ME TO DO?
*/
//long yearsSinceGuss = ChronoUnit.YEARS.between(LocalDate.now(), LocalDate.now().plus(durationSinceGuss) );
/*
* ERROR -
* Still an exception!
* Even on explicitly converting duration to seconds.
* Everything like above. Seconds are just not allowed. Have to convert them manually first e.g. to Days?!
* WHY OR WHY CAN'T YOU CONVERT SECONDS TO DAYS OR SOMETHING AUTOMATICALLY, JAVA?
*/
//long yearsSinceGuss = ChronoUnit.YEARS.between(LocalDate.now(), LocalDate.now().plus(durationSinceGuss.getSeconds(), ChronoUnit.SECONDS) );
答案 0 :(得分:6)
您是否尝试过使用LocalDateTime
或DateTime
代替LocalDate
?按照设计,后者不支持小时/分钟/秒/等,因此当您尝试向其添加秒时UnsupportedTemporalTypeException
。
例如,这有效:
LocalDateTime dateOne = LocalDateTime.of(1415, Month.JULY, 6, 0, 0);
Duration durationSinceGuss1 = Duration.between(dateOne, LocalDateTime.now());
long yearsSinceGuss = ChronoUnit.YEARS.between(LocalDateTime.now(), LocalDateTime.now().plus(durationSinceGuss1) );
System.out.println(yearsSinceGuss); // prints 600
答案 1 :(得分:3)
使用a b
c d
e f
获取两个Period
个对象之间的年数:
LocalDate
答案 2 :(得分:3)
虽然@Matt Ball接受的答案试图巧妙地使用Java-8-API,但我会提出以下异议:
您的要求并不准确,因为无法将秒数准确转换为年。
原因是:
也许是对您的代码最重要的反对意见:
我无法想象1415年的日期供应商有意将这样的日期解释为格里高利日期。
我理解从几秒到几年的转换的愿望,但只能是一个近似值,无论您选择什么作为解决方案。因此,如果您有像1415这样的年份,我建议遵循非常简单的近似值:
Duration d = ...;
int approximateYears = (int) (d.toDays() / 365.2425);
对我来说,只要我们真的想在这样一个用例中使用第二个持续时间,就足以满足历史背景。您似乎无法更改从外部来源获得的输入(否则最好联系持续时间供应商并询问是否可以提供天数)。无论如何,你必须问自己想要应用什么样的年份定义。
旁注:
您的投诉"为什么能够让JAVA做出让我做的事情?"与新的java.time-API的字符不匹配。
您希望API是类型安全的,但 java.time
(JSR-310)并非设计为类型安全且严重依赖于运行时异常。编译器不会帮助您使用此API。相反,如果任何给定的时间单位适用于任何给定的时间类型,您必须查阅文档。您可以在Temporal.isSupported(TemporalUnit)的任何具体实现的文档中找到这样的答案。无论如何,编译安全的愿望是可以理解的(我自己也尽力将我自己的时间库Time4J实现为类型安全)但JSR-310的设计已经完成了。
如果您在java.time.Duration
或LocalDateTime
上应用Instant
,也存在一个微妙的陷阱,因为结果不完全可比(第一种类型的秒数在本地时间轴上定义,而秒Instant
的定义在全球时间轴上定义。因此,即使没有像@Matt Ball所接受的回答中那样的运行时异常,我们也必须仔细考虑这种计算的结果是否合理且值得信赖。