如何将 java.time.Period 直接转换为 java.time.Duration?

3
我知道java.time.Period是一种“估算”的时间量,而java.time.Duration则是准确的。尽管如此,我仍然想将Period转换为Duration。或者至少声明一个周或更长时间的持续时间,而不使用技巧。

虽然这段代码可以编译,但它会抛出运行时异常,因为ChronoUnit.WEEKS和更大的时间单位返回true ChronoUnit.isDurationEstimated()
var d = Duration.of(2, ChronoUnit.WEEKS);

同样地,这段代码编译通过但会因为同样的原因抛出异常:
var d = Duration.from(Period.ofWeeks(2));

从ISO-8601字符串中进行往返转换是可行的,但不太妥当。
var p = Period.ofWeeks(2);
var d = Duration.parse(p.toString());

有更好的方法吗?


1
本来想给你的问题点个赞,但我又不想破坏你完美的声誉分数。今天特别给你在评论中加上一个+1。 - Eritrean
2
太晚了,我搞砸了。 - Gonen I
2个回答

5

由于需要将年和月转换为天、分钟、秒、毫秒或纳秒,因此不存在直接从 Period 转换为 Duration 的方法。但是,1年等于365或366天(闰年)吗?1个月等于28、29、30或31天吗?

但是,您可以进行估算。例如:

public static Duration ofPeriod(Period period) {

    long days = period.getDays() + Math.round((period.toTotalMonths() / 12d) * 365.2425d);

    return Duration.ofDays(days);
}

然后您可以执行以下操作:

Period period = Period.ofWeeks(2);

Duration duration = ofPeriod(period);

System.out.println(duration);

输出:

PT336H

5

问题

java.time.Period 是以年、月和日为单位的时间段。 java.time.Duration 是以小时、分钟、秒及秒的小数为单位的时间长度。它们不兼容,在一般情况下,将一个转换为另一个没有意义。

我假设您仍然有一个实际目的要尝试这样做。其他人已经提到,您需要确定您认为一年和一个月的持续时间是多长,因为它们的长度并不总是相同的。对于天数也是如此:一天的长度并不总是相同的。诚然,它往往是24小时,但也可能是23或25小时或其他长度。

此外,进一步的区别是,Period 保留年、月和日的单独字段。您可以拥有2年28个月和-3天的 Period。而 Duration 不保留单独的字段,并始终将60秒转换为1分钟,将60分钟转换为1小时。

Period 接受周数的计数,但将一周转换为7天。类似地,Duration 接受天数的计数,并将一天转换为24小时,而不考虑我刚才提到的事实,即一天并不总是24小时。

所有这些都意味着,如果您接受一天为24小时的假设,则可以将以天数和/或周数表示的 Period 转换为 Duration,例如使用字符串方法。 如果 Period 中有任何年份或月份,则该方法将引发异常。

无舍入解决方案

java.time包括用于估计年和月的持续时间。 这些可能适用于您的目的,也可能不适用。只有您才能决定。 我可以向您展示如何使用它们。

public static Duration ofPeriod(Period period) {
    Duration years = ChronoUnit.YEARS.getDuration().multipliedBy(period.getYears());
    Duration months = ChronoUnit.MONTHS.getDuration().multipliedBy(period.getMonths());
    Duration days = ChronoUnit.DAYS.getDuration().multipliedBy(period.getDays());
    return years.plus(months).plus(days);
}

在这个例子中,问题和其他答案给出了相同的结果:

PT336H

月份和年份被不同对待。让我们尝试一个1年1个月的时间段:
    Period period = Period.of(1, 1, 0);
    Duration duration = ofPeriod(period);
    System.out.println(duration);

PT9496H18M18S

表示为 9496 小时 18 分钟 18 秒。

ThreeTen Extra PeriodDuration

ThreeTen Extra 项目是在 java.time 的基础上开发的,包括一个 PeriodDuration 类,用于表示年、月、日、小时、分钟、秒和秒的分数的周期或持续时间。如其名称所示,它是 PeriodDuration 的组合。你可以查看它是否适合你的需求。

链接:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接