有没有办法让 Java8 的持续时间为一年来计算闰年?

问题描述 投票:0回答:2

我需要一年中的天数,并且我想使用 Java8 的新时间 api。

但是,我不能这样做

Duration.ofDays(365)
,因为它没有考虑闰年。 并且
Duration.of(1, ChronoUnit.YEARS)
不会飞,因为
java.time.temporal.UnsupportedTemporalTypeException: Unit must not have an estimated duration

我研究了Period,但它似乎对于从几年到几天没有用。

我觉得我错过了什么? 如果年份是闰年,我可以写一些东西来添加一天,但看起来我应该能够开箱即用地处理这个问题。

java java-8 duration
2个回答
50
投票

简短回答

不可以,

Duration
是1天或更短时间,
Period
是你应该使用1天或更长时间。

长答案

根据使用新的 dateTime API 获取持续时间中的响应,您应该使用

Period p = Period.ofYears(1);

了解

Duration
(确切的纳秒数 < 1 day) and
Period
(变量 > 1 天)之间的区别非常重要。

例如,

Duration
不会考虑闰日、夏令时或闰秒,并且适用于少于一天、最多几天的持续时间。

所以你应该使用

Period
来代替。

因为不同的年份有不同的天数,如果你想找到一年中的天数,你需要指定你正在谈论的是哪一年。

如果您想要特定年份的天数,可以使用

Year.of(year).length()

如果您想要一年后的日期,您可以使用

LocalDate.now().plusYears(1)

LocalDate.now().plus(Period.ofYears(1))

如果您需要两个日期之间的天数,可以使用

ChronoUnit.DAYS.between(start, end)

因此,要查找从现在开始到一年后的日期的天数,您可以使用

LocalDate today = LocalDate.now();
long days = ChronoUnit.DAYS.between(today, today.plusYears(1));

如果您想查看一年的会员资格是否仍然有效,您可以使用

Period membershipLength = Period.ofYears(1);
LocalDate membershipStart = ...;
LocalDate membershipEnd = membershipStart.plus(membershipLength);

LocalDate today = LocalDate.now();
boolean memberShipEnded = today.isAfter(membershipEnd);
boolean membershipValid = !membershipEnded;

9
投票

很明显,您不需要持续时间(=两个日期之间),而是特定日期的年份长度。

LocalDate dateLeap = LocalDate.of(2004, Month.MARCH, 1);
System.out.println("leap year of " + dateLeap
    + " has days: " + dateLeap.lengthOfYear());

闰年 2004-03-01 有天数:366

Java 8 日期和时间的完整程度令人惊讶。


如果你的意思是,2004年1月5日到2005年1月5日=366,2004年3月2日到2005年3月2日=365

int lengthOfYear(LocalDate date) {
    return date.getMonthValue() <= 2
        ? date.lengthOfYear()               // Count Feb in this year
        : date.plusYears(1).lengthOfYear(); // Count Feb in next year
}

说明:基本上长度是365。但是如果日期>=三月,则计算下一年的二月,否则计算今年的二月。

请注意,

plusYears(1)
不会更改日或月。

也不考虑闰秒或 2 月 29 日的时/分。

© www.soinside.com 2019 - 2024. All rights reserved.