Time Conversions Using TimeUnit – 使用 TimeUnit 进行时间换算

最后修改: 2023年 11月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

When working with time and duration calculations in Java, the TimeUnit enum provides a convenient way to perform time conversions between different units.

在 Java 中进行时间和持续时间计算时,TimeUnitenum 提供了在不同单位之间执行时间转换的便捷方法。

Whether we want to convert seconds to minutes, milliseconds to hours, or perform any other time unit conversion, we can use TimeUnit to simplify the code, get accurate results, and make things more readable.

无论我们是要将秒转换为分,将毫秒转换为小时,还是要执行任何其他时间单位转换,我们都可以使用 TimeUnit 来简化代码,获得准确的结果,并使代码更加易读。

In this tutorial, we’ll look at using TimeUnit to convert time in Java.

在本教程中,我们将了解如何使用 TimeUnit 在 Java 中转换时间。

2. Understanding TimeUnit

2. 理解 TimeUnit.

TimeUnit is an enum, included in the java.util.concurrent package, that represents various units of time, ranging from nanoseconds to days. It provides a set of predefined constants, each corresponding to a specific unit of time, including:

TimeUnitenum 包含在 java.util.concurrent 包中,用于表示从纳秒到天的各种时间单位。它提供了一组预定义常量,每个常量对应一个特定的时间单位,包括

  • DAYS
  • HOURS
  • MINUTES
  • SECONDS
  • MILLISECONDS
  • MICROSECONDS
  • NANOSECONDS

These constants serve as the basis for time conversions.

这些常数是时间换算的基础。

3. Converting Time Using TimeUnit

3.使用 TimeUnit 转换时间

To perform a time conversion, we need to have a value representing the duration we want to convert and specify the target unit we wish to convert to. TimeUnit offers several methods for converting time between units, such as convert() or toXXX(), where XXX represents the target unit.

要执行时间转换,我们需要一个代表要转换的持续时间的值,并指定要转换的目标单位。TimeUnit提供了多种在单位间转换时间的方法,例如 convert()toXXX(),其中 XXX 代表目标单位。

3.1. Using the convert() Method

3.1.使用 <emconvert() 方法

First, let’s look at the convert(long sourceDuration, TimeUnit sourceUnit) method, which converts the given time duration in a given unit to the unit specified by the enum value.

首先,让我们来看看 convert(long sourceDuration, TimeUnit sourceUnit) 方法,它将给定单位中的给定时间长度转换为 enum 值指定的单位。

Let’s convert a simple integer to minutes:

让我们把一个简单的整数转换成分钟:

long minutes = TimeUnit.MINUTES.convert(60, TimeUnit.SECONDS);
assertThat(minutes).isEqualTo(1);

In this example, we start with a value of 60 seconds and then convert it to minutes. We specify the source time unit as the second argument. The output unit is always determined by the enum value.

在本例中,我们从 60 秒开始,然后将其转换为分钟。我们将源时间单位指定为第二个参数。输出单位始终由 enum 值决定。

Let’s check out another example, where we do the reverse conversion:

我们再来看一个反向转换的例子:

long seconds = TimeUnit.SECONDS.convert(1, TimeUnit.MINUTES); 
assertThat(seconds).isEqualTo(60);

As we see, the convert() method converts time between different units.

正如我们所看到的,convert() 方法在不同单位之间转换时间

3.2. Using the toXXX() Method

3.2.使用 toXXX() 方法

Let’s now explore the toXXX(long sourceDuration) methods. Here the XXX in the signature specifies the target unit.

现在让我们来探讨 toXXX(long sourceDuration) 方法。这里,签名中的 XXX 指定了目标单位。

We can choose units with toNanos()toMicros(), toMillis(), toSeconds(), toMinutes(), toHours(), and toDays().

我们可以使用toNanos()toMicros()toMillis()toSeconds()toMinutes()toHours()toDays()来选择单位。

Now let’s rewrite both previous snippets using the toXXX() methods:

现在,让我们使用 toXXX() 方法重写前面的两个代码段:

long minutes = TimeUnit.SECONDS.toMinutes(60);
assertThat(minutes).isEqualTo(1);

As before, we’ve just converted 60 seconds to minutes.

和之前一样,我们刚刚将 60 秒转换为分钟。

And we can convert the other way:

我们还可以转换成另一种方式:

long seconds = TimeUnit.MINUTES.toSeconds(1);
assertThat(seconds).isEqualTo(60);

As expected, the above examples produce the same result as before, so both signatures are equivalent. But unlike convert(), when we use the toXXX() methods, the enum value represents the source time unit.

不出所料,上述示例产生的结果与之前的相同,因此这两个签名是等价的。但与 convert() 不同的是,当我们使用 toXXX() 方法时,enum 值代表源时间单位。

4. Specific Use Cases

4.具体用例

Now that we know how to convert time using the TimeUnit methods, let’s explore some more detailed scenarios.

既然我们已经知道如何使用 TimeUnit 方法转换时间,那么让我们来探讨一些更详细的应用场景。

4.1. Negative Inputs

4.1.负输入

Firstly, let’s check if the converting methods support negative input values:

首先,让我们检查一下转换方法是否支持负输入值:

long minutes = TimeUnit.SECONDS.toMinutes(-60);
assertThat(minutes).isEqualTo(-1);

The given example shows that negative inputs are also handled by the converting methods, and the returned result is still correct.

示例显示,转换方法也可以处理负输入,而且返回的结果仍然正确。

4.2. Rounding Handling

4.2 四舍五入处理

Let’s now check what happens if we convert a smaller unit to a larger one, expecting a target non-integer result. We know that all methods only declare long as a return type, so decimal results cannot be returned.

现在让我们检查一下,如果我们将一个较小的单位转换为一个较大的单位,并期望得到一个非整数的目标结果,会发生什么情况。我们知道,所有方法都只声明 long 作为返回类型,因此无法返回十进制结果。

Let’s test the rounding rule by converting seconds to minutes:

让我们通过将秒转换成分来测试四舍五入规则:

long positiveUnder = TimeUnit.SECONDS.toMinutes(59);
assertThat(positiveUnder).isEqualTo(0);
long positiveAbove = TimeUnit.SECONDS.toMinutes(61);
assertThat(positiveAbove).isEqualTo(1);

Then, let’s check the negative inputs:

然后,让我们检查负输入:

long negativeUnder = TimeUnit.SECONDS.toMinutes(-59);
assertThat(negativeUnder).isEqualTo(0);

long negativeAbove = TimeUnit.SECONDS.toMinutes(-61);
assertThat(negativeAbove).isEqualTo(-1);

As we see, all conversions are handled without any errors.

正如我们所看到的,所有转换处理都没有出现任何错误。

We should note that all methods implement a rounding toward zero rule that truncates the decimal part.

我们应该注意到,所有方法都采用了向零舍入规则,以截断小数部分

4.3. Overflow Handling

4.3 溢流处理

As we know, all primitives have their value limits which cannot be exceeded. But what happens if the result overflows the limit?

我们知道,所有基元都有其数值限制,不能超出。但如果结果溢出了限值,会发生什么情况呢?

Let’s check the result of converting the minimum and maximum long values of days to milliseconds:

让我们检查一下将天数的最小值和最大值 long 转换为毫秒的结果:

long maxMillis = TimeUnit.DAYS.toMillis(Long.MAX_VALUE);
assertThat(maxMillis).isEqualTo(Long.MAX_VALUE);
long minMillis = TimeUnit.DAYS.toMillis(Long.MIN_VALUE);
assertThat(minMillis).isEqualTo(Long.MIN_VALUE);

The above code executes without throwing any exceptions. We should note that the result isn’t valid, because the overflow results are always truncated to minimum or maximum values defined by the long primitive.

上述代码执行时没有抛出任何异常。我们应该注意到,结果无效,因为溢出结果总是被截断到 long 原始码定义的最小值或最大值

5. Converting to the Finest Unit

5.转换为最精制单位

Sometimes, we may need to convert a duration to the finest unit available in TimeUnit, such as converting seconds to the appropriate combination of hours, minutes, and leftover seconds. Unfortunately, there’s no method for this. This is because all the conversion methods always return the total number of whole periods within a given duration.

有时,我们可能需要将持续时间转换为 TimeUnit 中可用的最细单位,例如将秒转换为小时、分钟和剩余秒的适当组合。遗憾的是,我们没有相应的方法。这是因为 所有转换方法总是返回给定持续时间内的整周期总数

To convert the input to the finest unit, we need to implement a custom function. Let’s use the value of 3672 seconds and fetch an appropriate combination of time units – we expect the value of 1 hour, 1 minute, and 12 seconds.

要将输入转换为最精确的单位,我们需要实现一个自定义函数。让我们使用 3672 秒的值,并获取适当的时间单位组合–我们希望得到 1 小时、1 分钟和 12 秒的值。

To extract hours we can use:

要提取小时数,我们可以使用

long inputSeconds = 3672;
long hours = TimeUnit.SECONDS.toHours(inputSeconds);
assertThat(hours).isEqualTo(1);

Now, if we want to extract the remaining minutes, we should subtract the sum of seconds contained in hours from the input value, and then use this value for further operations:

现在,如果我们想提取剩余的分钟数,就应该从输入值中减去小时数中包含的秒数总和,然后使用该值进行进一步操作:

long secondsRemainingAfterHours = inputSeconds - TimeUnit.HOURS.toSeconds(hours);
long minutes = TimeUnit.SECONDS.toMinutes(secondsRemainingAfterHours);
assertThat(minutes).isEqualTo(1);

We’ve just successfully calculated the hours and minutes based on the input data. Finally, we need to retrieve the remaining seconds.

我们刚刚根据输入数据成功计算了小时和分钟。最后,我们需要获取剩余的秒数。

To do this, we repeat the subtraction logic, remembering to adjust the parameters:

为此,我们重复减法逻辑,记住要调整参数:

long seconds = secondsRemainingAfterHours - TimeUnit.MINUTES.toSeconds(minutes);
assertThat(seconds).isEqualTo(12);

In the example, we’ve just converted 3672 milliseconds to the finest unit representation, which includes hours, minutes, and seconds.

在示例中,我们刚刚将 3672 毫秒转换为最细单位表示法,其中包括小时、分钟和秒。

6. Conclusion

6.结论

In this article, we explored various ways to convert time using the TimeUnit enumeration in Java.

在本文中,我们探讨了使用 Java 中的 TimeUnit 枚举转换时间的各种方法。

The TimeUnit enum provides a convenient and efficient way to convert between different units using convert() and toXXX() methods.

TimeUnit枚举为使用 convert()toXXX() 方法在不同单位之间进行转换提供了方便、高效的方法

In addition, it also handles negative inputs and returns correct results. We can easily convert durations, regardless of whether we’re converting from a smaller to a larger unit or vice versa, with rounding toward zero. It also implements basic overflow protection by trimming the result to borderline values.

此外,它还能处理负输入并返回正确结果。我们可以轻松地转换持续时间,无论是从小单位转换到大单位,还是从大单位转换到小单位,都可以四舍五入为零。它还通过对结果的边界值进行修剪,实现了基本的溢出保护。

If we want to convert a source duration to the appropriate combination of other units (such as days, hours, minutes, and seconds), we can easily implement additional logic. All converters return the total number of specified periods within a specified duration.

如果我们想将源持续时间转换为其他单位的适当组合(如天、小时、分钟和秒),我们可以很容易地实现附加逻辑。所有转换器都会返回指定持续时间内指定周期的总数。

As always, the source code for the examples is available over on GitHub.

与往常一样,这些示例的源代码可在 GitHub 上获取。