开发工具分享
  • 首页
  • 计算科学
  • 文化旅游
  • 项目和网站
    • OSSEZ 计算技术
    • USRealEstate 社区
    • 地区文化
    • CWIKI.US
    • BUG.OSSEZ.COM
    • RSS.OSSEZ.COM
CWIKIUS.CN
一个有独立思考和温度的清新站
  1. Home
  2. Computer Science
  3. This article

Java 中的 Period 和 Duration

2025年01月18日 477Browse 0Like 0Comments

在本文中让我们来看看在 Java 8 中引入的 2 个新的类: Period 和 Duration.

上面 2 个类可以被用来替换在 determine 和 time 中大量使用用来计算 2 个时间不同的 API。

针对上面 2 个类最主要的不同就是 Period 被用来计算日期的不同,Duration 则是被用来计算时间的不同。

Period 类

Period 使用的单位是 年,月,日来表达 2 个日期之间的不同。

我们可以通过 2 个时期之间不同的 between() 方法来获得 Period 对象。

LocalDate startDate = LocalDate.of(2015, 2, 20);
LocalDate endDate = LocalDate.of(2017, 1, 15);

Period period = Period.between(startDate, endDate);

当我们获得 Period 对象后,我们可以用 Period 对象中的 *getYears(), getMonths(), getDays() 方法来获得具体的值。

        logger.info(String.format("Years:%d months:%d days:%d", period.getYears(), period.getMonths(), period.getDays()));

 

2025-01-17_06-47-08

 

isNegative() 也是 Period 中的一个方法,可以通过这个方法来判断 2 个比较时间的大小关系。

当这个方法返回 True 的时候,表明结束时间要大于起始时间。

assertFalse(period.isNegative());

相反的 isNegative() 如果返回的为 false,那么表明 startDate* 要早入 endDate 的值。

另外一个可以创建 Period 对象的方法就是使用数字,Period 中提供了一个 of 方法,我们可以用这个方法来构造一个 Period 对象:

Period fromUnits = Period.of(3, 10, 10);
Period fromDays = Period.ofDays(50);
Period fromMonths = Period.ofMonths(5);
Period fromYears = Period.ofYears(10);
Period fromWeeks = Period.ofWeeks(40);

assertEquals(280, fromWeeks.getDays());

如果 of 方法中只有一个输入参数的话,那么默认调用的是 ofDays() 方法,等于用输入的数字初始化日这个单位。,

基于上面的设计, ofWeeks() 方法使用的是乘以 7 的方式,因为不管一年有多少天,但一周 7 天这个肯定是不会变的。

通过看 JDK 的源代码:

    public static Period ofWeeks(int weeks) {
        return create(0, 0, Math.multiplyExact(weeks, 7));
    }

 

2025-01-17_06-53-42

 

上面的构造方法就能说明这个问题了。

同时,还可以使用字符串来创建 Period 对象,这个字符串使用的序列为 “PnYnMnD”:

Period fromCharYears = Period.parse("P2Y");
assertEquals(2, fromCharYears.getYears());

Period fromCharUnits = Period.parse("P2Y3M5D");
assertEquals(5, fromCharUnits.getDays());

当 period 对象创建成功后,可以使用 plusX() 和 minusX() 方法来对创建的 period 对象中的值进行调整:

assertEquals(56, period.plusDays(50).getDays());
assertEquals(9, period.minusMonths(2).getMonths());

Duration 类

和 Period 相对,Duration 类是对时间进行操作的。

具体操作的单位为秒(seconds )和纳秒(nanoseconds )。

因可以直接对纳秒进行操作,所以 Duration 能比较精确的对时间进行计算。

另外,要获得 Duration 对象,我们需要从 instants 来进行比较,使用 between() 方法来比较 instants 。

Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
Instant end = Instant.parse("2017-10-03T10:16:30.00Z");
        
Duration duration = Duration.between(start, end);

上面的方法能够构造一个 Duration 对象,然后从 Duration 对象中使用 getSeconds() 或者getNanoseconds() 方法来获得具体的单位值:

assertEquals(60, duration.getSeconds());

可选的,因为是对时间进行计算机,那么你还可以从 LocalDateTime 实例中来比较构造一个 Duration 对象:

LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2023-01-01T12:00:00");

Duration.between(start, end).getSeconds();

基于起始时间的不同,Duration 可能会有下面的 3 中情况:

  • Negative: start < end
  • Zero: start = end
  • Positive: start > end

同时,标准的时间 Time API 也提供了转发方法来检查 Duration 是否为 0 或者负数:

LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
assertFalse(Duration.between(start, end).isNegative());
assertTrue(Duration.between(end, start).isNegative());

LocalDateTime theTime = LocalDateTime.parse("2023-09-09T08:00:00");
assertTrue(Duration.between(theTime,theTime).isZero());
assertFalse(Duration.between(theTime,theTime).isNegative());
// Java version 18+ required
LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
assertTrue(Duration.between(start, end).isPositive());
assertFalse(Duration.between(end, start).isPositive());

当然,我们也可以使用单位来构造一个 Duration 对象,这个和 Period 的构造方法基本相同。

可以使用的方法有: ofDays(), ofHours(), ofMillis(), ofMinutes(), ofNanos(), ofSeconds():

Duration fromDays = Duration.ofDays(1);
assertEquals(86400, fromDays.getSeconds());
       
Duration fromMinutes = Duration.ofMinutes(60);

我们还可以使用字符串的方法来构造 Duration ,表达方式为:PnDTnHnMn.nS:

Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
Duration fromChar2 = Duration.parse("PT10M");

duration 对象也可以实现其他单位的转换,使用的方法为:toDays(), toHours(), toMillis(), toMinutes():

assertEquals(1, fromMinutes.toHours());

针对时间的增加和减少,我们可以使用 plusX() 方法 minusX(), X 根据具体的单位不同而使用不同的字符来表达,具体的可以参考 JDK API 的手册。

下面我们只简单的列了几个可以使用的方法:

assertEquals(120, duration.plusSeconds(60).getSeconds());     
assertEquals(30, duration.minusSeconds(30).getSeconds());

为了避免书写上面的问题,我们还可以在 plus() 和 minus() 方法中使用 ChronoUnit 来制定添加或者减少的单位:

assertEquals(120, duration.plus(60, ChronoUnit.SECONDS).getSeconds());     
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS).getSeconds());

结论

让我为你总结一下这两个类的主要区别和用法:

Period 和 Duration 的主要区别

  1. Period
    • 使用基于日期的值(date-based values)
    • 主要用于处理年、月、日的时间段
    • 适用于较长时间段的计算
  2. Duration
    • 使用基于时间的值(time-based values)
    • 主要用于处理秒和纳秒级别的时间
    • 适用于更短、更精确的时间间隔

Period 的主要用法

  1. 创建 Period 对象:
// 通过两个日期之间的差值创建
LocalDate startDate = LocalDate.of(2015, 2, 20);
LocalDate endDate = LocalDate.of(2017, 1, 15);
Period period = Period.between(startDate, endDate);

// 直接创建特定时间段
Period fromUnits = Period.of(3, 10, 10);  // 年、月、日
Period fromDays = Period.ofDays(50);
Period fromMonths = Period.ofMonths(5);
Period fromYears = Period.ofYears(10);
Period fromWeeks = Period.ofWeeks(40);
  1. 解析字符串创建 Period:
Period fromCharYears = Period.parse("P2Y");        // 2年
Period fromCharUnits = Period.parse("P2Y3M5D");    // 2年3月5日

Duration 的主要用法

  1. 创建 Duration 对象:
// 通过两个时间点之间的差值创建
Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
Instant end = Instant.parse("2017-10-03T10:16:30.00Z");
Duration duration = Duration.between(start, end);

// 直接创建特定时长
Duration fromDays = Duration.ofDays(1);
Duration fromMinutes = Duration.ofMinutes(60);
  1. Duration 的其他操作:
// 检查 Duration 的性质
duration.isNegative();
duration.isZero();
duration.isPositive();  // Java 18+

// 转换到其他时间单位
duration.toDays();
duration.toHours();
duration.toMillis();
duration.toMinutes();

// 增加或减少时长
duration.plusSeconds(60);
duration.minusSeconds(30);

使用建议

  1. 如果你需要处理年、月、日级别的时间段,使用 Period
  2. 如果你需要更精确的时间计算(包括小时、分钟、秒、纳秒),使用 Duration
  3. Period 可能会损失精度,而 Duration 则保持高精度

这两个类都是在 Java 8 中引入的,属于新的日期时间 API 的一部分,它们提供了更清晰和更易用的时间间隔处理方式。

 

https://www.isharkfly.com/t/java-period-duration/16809

Tags: None
Last updated:2025年01月18日

HoneyMoose

有温度的人文和独立的思考

Like
< Previous
Next >

Comments

Cancel reply

Archives
  • May 2026
  • April 2026
  • March 2026
  • February 2026
  • January 2026
  • December 2025
  • November 2025
  • October 2025
  • September 2025
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
Categories
  • Computer Science (2,362)
    • Confluence (663)
    • Gradle (12)
  • U.S. (482)
  • 文化旅游 (145)

COPYRIGHT © 2020 CWIKIUS. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

湘ICP备2020018253号-1