首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Java8日期API中将持续时间转换为年数?

在Java8日期API中将持续时间转换为年数?
EN

Stack Overflow用户
提问于 2016-02-04 00:05:13
回答 3查看 5.6K关注 0票数 4

我有个很久以前的约会。

我发现了从这个日期到现在的持续时间。

现在我想知道-这几年是多少钱?

我想出了这个使用Java8 API的解决方案。

这是一个可怕的解决方案,因为我必须首先手动将持续时间转换为天,因为否则就会有一个UnsupportedTemporalTypeException --无论出于什么原因,都不支持LocalDate.plus(SECONDS)

即使编译器允许此调用。

是否有较少冗长的可能性将Duration转换为年份?

代码语言:javascript
运行
复制
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) );
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-04 00:09:15

你试过使用LocalDateTimeDateTime而不是LocalDate吗?根据设计,后者不支持小时/分钟/秒/等,因此,当您尝试向其添加秒时,就会出现UnsupportedTemporalTypeException

例如,这起作用是:

代码语言:javascript
运行
复制
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
票数 7
EN

Stack Overflow用户

发布于 2016-02-04 00:11:28

使用Period获取两个LocalDate对象之间的年数:

代码语言:javascript
运行
复制
    LocalDate before    = LocalDate.of(1415, Month.JULY, 6);
    LocalDate now       = LocalDate.now();
    Period    period    = Period.between(before, now);

    int yearsPassed     = period.getYears();

    System.out.println(yearsPassed);
票数 3
EN

Stack Overflow用户

发布于 2016-02-04 10:38:21

虽然@Matt Ball的公认答案试图在使用Java-8-API方面变得聪明,但我还是会提出以下反对意见:

您的需求并不准确,因为无法将秒精确转换为年数。

原因如下:

  • 最重要的是:月份的天数不同(从28天到31天)。
  • 年有时也有闰日(2月29日),这对计算年三角洲也有影响。
  • 你从1415年的一年开始,这远远早于第一次公历改革,它取消了整整10天,在英国甚至11天,在俄罗斯更多。老朱利安历法中的年份有不同的闰年规则。
  • 历史日期没有定义到第二精度。例如,你能描述黑斯廷斯战役的瞬间/瞬间吗?我们甚至不知道确切的时间,只有一天。在一天开始的时候假设午夜已经是一个粗略的假设,而且可能是错误的。
  • 时区效应对一天的长度有影响(23h、24h、25h,甚至不同的其他长度)。
  • 闰秒(奇异)

也许对你的代码最重要的异议是:

我无法想象1415年这一日期的供应商打算把这样的日期解释为公历日期.

我理解从秒到年份的转换的愿望,但是无论您选择什么作为解决方案,只能是一个近似的。所以,如果你有1415年这样的时间,我建议你做一个非常简单的近似:

代码语言:javascript
运行
复制
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应用于LocalDateTimeInstant,也会有一个小缺陷,因为结果并不完全可比较(第一种类型的秒是在本地时间线上定义的,而Instant的秒是在全局时间线上定义的)。因此,即使没有运行时异常,如@Matt的公认答案,我们也必须仔细考虑这种计算的结果是否合理和可信。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35190184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档