# 期间和期限

> 原文： [https://docs.oracle.com/javase/tutorial/datetime/iso/period.html](https://docs.oracle.com/javase/tutorial/datetime/iso/period.html)

当您编写指定时间的代码时，请使用最符合您需求的类或方法： [`持续时间`](https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html) 类， [`期间`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html) 类，或 [`ChronoUnit.between`](https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoUnit.html#between-java.time.temporal.Temporal-java.time.temporal.Temporal-)方法。 `持续时间`使用基于时间的值（秒，纳秒）测量时间量。 `期间`使用基于日期的值（年，月，日）。

* * *

**Note:** A `Duration` of one day is _exactly_ 24 hours long. A `Period` of one day, when added to a `ZonedDateTime`, may vary according to the time zone. For example, if it occurs on the first or last day of daylight saving time.

* * *

## 持续时间

`持续时间`最适合测量基于机器的时间的情况，例如使用 `Instant` 对象的代码。 `持续时间`对象以秒或纳秒为单位测量，并且不使用基于日期的构造，例如年，月和日，尽管该类提供了转换为天，小时和分钟的方法。如果使用在起点之前发生的终点创建`持续时间`，则其可以具有负值。

以下代码以纳秒为单位计算两个时刻之间的持续时间：

```
Instant t1, t2;
...
long ns = Duration.between(t1, t2).toNanos();

```

以下代码为 `Instant` 增加 10 秒：

```
Instant start;
...
Duration gap = Duration.ofSeconds(10);
Instant later = start.plus(gap);

```

`持续时间`未连接到时间线，因为它不跟踪时区或夏令时。将相当于 1 天的`持续时间`添加到 `ZonedDateTime` 会导致正好 24 小时的添加，无论夏令时或其他可能导致的时间差异如何。

## ChronoUnit

在 [The Temporal Package](temporal.html) 中讨论的 `ChronoUnit` 枚举定义了用于测量时间的单位。 `ChronoUnit.between` 方法在您想要仅在一个单位时间内测量时间量时非常有用，例如天或秒。 方法之间的`适用于所有基于时间的对象，但它仅返回单个单元中的数量。以下代码计算两个时间戳之间的间隔（以毫秒为单位）：`

```
import java.time.Instant;
import java.time.temporal.Temporal;
import java.time.temporal.ChronoUnit;

Instant previous, current, gap;
...
current = Instant.now();
if (previous != null) {
    gap = ChronoUnit.MILLIS.between(previous,current);
}
...

```

## 期

要使用基于日期的值（年，月，日）定义时间量，请使用 [`Period`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html)类。 `Period` 类提供各种 `get` 方法，如 [`getMonths`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html#getMonths--)， [`getDays`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html#getDays--)，和 [`getYears`](https://docs.oracle.com/javase/8/docs/api/java/time/Period.html#getYears--)，这样就可以从句点中提取出来的时间量。

总时间段由所有三个单元一起表示：月，日和年。要显示在单个时间单位（例如天）中测量的时间量，您可以使用`方法之间的 `ChronoUnit。``

假设您出生于 1960 年 1 月 1 日，以下代码将报告您的年龄。`期间`类用于确定年，月和日的时间。使用 `ChronoUnit.` 方法确定同一时期（总天数），并显示在括号中：

```
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);

Period p = Period.between(birthday, today);
long p2 = ChronoUnit.DAYS.between(birthday, today);
System.out.println("You are " + p.getYears() + " years, " + p.getMonths() +
                   " months, and " + p.getDays() +
                   " days old. (" + p2 + " days total)");

```

代码生成类似于以下内容的输出：

```
You are 53 years, 4 months, and 29 days old. (19508 days total)

```

要计算到下一个生日的时间，您可以使用 [``生日``](examples/Birthday.java)示例中的以下代码。 `Period` 类用于确定以月和日为单位的值。 `ChronoUnit.between` 方法返回总天数值，并显示在括号中。

```
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);

LocalDate nextBDay = birthday.withYear(today.getYear());

//If your birthday has occurred this year already, add 1 to the year.
if (nextBDay.isBefore(today) || nextBDay.isEqual(today)) {
    nextBDay = nextBDay.plusYears(1);
}

Period p = Period.between(today, nextBDay);
long p2 = ChronoUnit.DAYS.between(today, nextBDay);
System.out.println("There are " + p.getMonths() + " months, and " +
                   p.getDays() + " days until your next birthday. (" +
                   p2 + " total)");

```

代码生成类似于以下内容的输出：

```
There are 7 months, and 2 days until your next birthday. (216 total)

```

这些计算不考虑时区差异。例如，如果您出生在澳大利亚，但目前住在班加罗尔，这会略微影响您确切年龄的计算。在这种情况下，将 `Period` 与 `ZonedDateTime` 类一起使用。将 `Period` 添加到 `ZonedDateTime` 时，会观察到时差。