1. Introduction
1.导言
In some cases, while we’re working with dates in Java, we may have to round them to a certain unit, like hours, days, or months. It provides such benefits as aggregating data for analysis and reporting purposes and allowing to specify the degree of detail of displayed information.
在某些情况下,当我们使用 Java 处理日期时,可能需要将日期四舍五入到某个单位,如小时、天或月。四舍五入的好处包括:为分析和报告目的汇总数据,以及可以指定显示信息的详细程度。
In this tutorial, we’ll learn how to round the date using the java.util.Date, as well as LocalDateTime and ZonedDateTime.
在本教程中,我们将学习如何使用java.util.Date 以及 LocalDateTime 和 ZonedDateTime.
2. Basic Rounding
2.基本四舍五入
In the basic rounding approach, we can truncate the time part of any date within Java. To be specific, this entails making all temporal elements equal to zero. Here’s how we can do that:
在基本的四舍五入方法中,我们可以截断 Java 中任何日期的时间部分。具体来说,就是让所有时间元素都等于零。下面我们就来看看如何做到这一点:
Date roundToDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
The roundToDay() method takes a Date object as a parameter. Then, we use the setTime() method from the Calender class and use it to use the set() method to round the hour, minute, second, and millisecond to the start of the day.
roundToDay() 方法将 Date 对象作为参数。然后,我们使用 Calender 类中的 setTime() 方法,并用它来使用 set() 方法将小时、分钟、秒和毫秒舍入到一天的开始时间。
3. Rounding to the Nearest Unit
3.四舍五入到最接近的单位
Wе havе thе option to makе thе rounding mеthod constant to makе thе datе match thе rounding across thе units such as hour, day, or month as follows:
我们可以选择四舍五入方法,使数据的四舍五入与小时、天或月等单位的四舍五入保持一致,如下所示:
Date roundToNearestUnit(Date date, int unit) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
switch (unit) {
case Calendar.HOUR:
int minute = calendar.get(Calendar.MINUTE);
if (minute >= 0 && minute < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minute >= 15 && minute < 45) {
calendar.set(Calendar.MINUTE, 30);
} else {
calendar.set(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.DAY_OF_MONTH:
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour >= 12) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.MONTH:
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (day >= 15) {
calendar.add(Calendar.MONTH, 1);
}
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
}
return calendar.getTime();
}
Here, we have a roundToNearestUnit() method that expects a Date and an int unit to be passed in, which seeks to round off the input date to the indicated time unit.
这里,我们有一个 roundToNearestUnit() 方法,该方法需要传入一个 Date 和一个 int 单位,目的是将输入日期舍入到指定的时间单位。
To that effect, the code creates an instance of Calendar and sets it to the input date. We’ll retrieve and adjust the minute, hour, or day component to allow a date to be rounded to the nearest 30-minute interval, day, or month depending upon which unit has been selected (Calendar.HOUR, Calendar.DAY_OF_MONTH, or Calendar.MONTH).
为此,代码将创建一个 Calendar 实例,并将其设置为输入日期。我们将检索并调整分钟、小时或日期组件,以便根据选择的单位(Calendar.HOUR、Calendar.DAY_OF_MONTH或 Calendar.MONTH),将日期四舍五入到最接近的 30 分钟间隔、日或月。
Moreover, we make sure the seconds and milliseconds are also zeroed. Following the above-mentioned modifications according to the defined time unit, the code returns the new Date derived from the generated Calendar entity.
此外,我们还确保秒和毫秒也归零。根据定义的时间单位进行上述修改后,代码将返回从生成的 Calendar 实体派生的新 Date 。
4. Rounding Using LocalDateTime
4.使用 LocalDateTime四舍五入
LocalDateTime is a new class in Java that enables us to round dates at different levels, thereby offering a more current solution for handling dates and times. Here are two methods for rounding dates using LocalDateTime:
LocalDateTime是 Java 中的一个新类,它使我们能够对日期进行不同程度的四舍五入,从而为处理日期和时间提供了一种更新颖的解决方案。下面是使用 LocalDateTime 对日期进行四舍五入的两种方法:
LocalDateTime roundToStartOfMonth(LocalDateTime dateTime) {
return dateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
}
In the above method roundToStartOfMonth(), we set the day of the month to 1 to round the given LocalDateTime to the start of the month and reset all time components at midnight (0 hours, 0 minutes, 0 seconds, and 0 nanoseconds).
在上述方法roundToStartOfMonth()中,我们将月日设置为 1,以便将给定的 LocalDateTime 四舍五入到月首,并在午夜重置所有时间组件(0 小时、0 分钟、0 秒和 0 纳秒)。
We can also use LocalDateTime to round the given date to the end of the week as follows:
我们还可以使用 LocalDateTime 将给定日期四舍五入到周末,如下所示:
LocalDateTime roundToEndOfWeek(LocalDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.withNano(999);
}
The RoundToEndOfWeek() method rounds LocalDateTime to the end of the next Saturday by taking advantage of TemporalAdjusters.next() function that finds the next Saturday and sets its time components such as 23 hours, 59 minutes, 59 seconds, and 999 nanoseconds.
RoundToEndOfWeek()方法通过利用TemporalAdjusters.next()函数将LocalDateTime舍入到下一个星期六的末尾,该函数可查找下一个星期六并设置其时间分量,例如 23 小时、59 分钟、59 秒和 999 纳秒。
5. Rounding Using ZonedDateTime
5.使用 ZonedDateTime四舍五入
The ZonedDateTime class makes it possible to round dates for situations where there are time zones. Here are two methods for rounding dates using ZonedDateTime:
通过 ZonedDateTime 类,可以对存在时区的日期进行四舍五入。下面是使用 ZonedDateTime 对日期进行四舍五入的两种方法:
ZonedDateTime roundToStartOfMonth(ZonedDateTime dateTime) {
return dateTime.withDayOfMonth(1)
.withHour(0)
.withMinute(0)
.withSecond(0)
.with(ChronoField.MILLI_OF_SECOND, 0)
.with(ChronoField.MICRO_OF_SECOND, 0)
.with(ChronoField.NANO_OF_SECOND, 0);
}
The above method roundToStartOfMonth() takes a ZonedDateTime as input and returns a new ZonedDateTime. Specifically, it returns the same date and time but with the time portion set to midnight at the beginning of the month (00:00:00.000).
上述方法 roundToStartOfMonth() 将 ZonedDateTime 作为输入,并返回一个新的 ZonedDateTime 。具体地说,它返回相同的日期和时间,但时间部分被设置为月初的午夜(00:00:00.000)。
To round the input Date to the end of the current week, let’s take the following example:
要将输入的 Date 四舍五入到当前星期的末尾,让我们以下面的示例为例:
public static ZonedDateTime roundToEndOfWeek(ZonedDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.with(ChronoField.MILLI_OF_SECOND, 999)
.with(ChronoField.MICRO_OF_SECOND, 999)
.with(ChronoField.NANO_OF_SECOND, 999);
}
In the roundToEndOfWeek() method, we first find the next Saturday using TemporalAdjusters, then set the time to (23:59:59.999999999).
在 roundToEndOfWeek() 方法中,我们首先使用 TemporalAdjusters 找到下一个星期六,然后将时间设置为 (23:59:59.9999999)。
6. Conclusion
6.结论
In conclusion, working with time-based data rounding dates in Java is one of the most important tasks. In this tutorial, we’ve seen some ways of rounding dates to different units and precision levels, such as truncating and the customized rounding method.
总之,在 Java 中处理基于时间的数据时,日期四舍五入是最重要的任务之一。在本教程中,我们已经了解了将日期舍入到不同单位和精度级别的一些方法,如截断法和自定义舍入法。
Be reminded that time changes should be put into consideration for every date, especially those for applications used internationally.
请注意,每个日期都应考虑时间变化,尤其是国际通用的应用程序。
As always, the complete code samples for this article can be found over on GitHub.
与往常一样,本文的完整代码示例可在 GitHub 上找到。