给定今天的时间,例如下午 2:24,我如何让它四舍五入到下午 2:30?
同样,如果时间是下午 2:17,我如何让它四舍五入到下午 2:15?
您将需要使用模来截断一刻钟:
Date whateverDateYouWant = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(whateverDateYouWant);
int unroundedMinutes = calendar.get(Calendar.MINUTE);
int mod = unroundedMinutes % 15;
calendar.add(Calendar.MINUTE, mod < 8 ? -mod : (15-mod));
正如 EJP 所指出的,这也可以(替换最后一行,仅当日历为 lenient 时才有效):
calendar.set(Calendar.MINUTE, unroundedMinutes + mod);
如果要准确,还必须截断较小的字段:
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
您还可以使用来自Apache Commons / Lang的DateUtils.truncate()来执行此操作:
calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
如果您只想四舍五入,这是使用Java Time API的更易读的版本:
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * (time.getMinute() / 15));
输出:
2016-11-04T10:58:10.228
2016-11-04T10:45:00
Java 8 的注释实现。接受任意舍入单位和增量:
public static ZonedDateTime round(ZonedDateTime input, TemporalField roundTo, int roundIncrement) {
/* Extract the field being rounded. */
int field = input.get(roundTo);
/* Distance from previous floor. */
int r = field % roundIncrement;
/* Find floor and ceiling. Truncate values to base unit of field. */
ZonedDateTime ceiling =
input.plus(roundIncrement - r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
ZonedDateTime floor =
input.plus(-r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
/*
* Do a half-up rounding.
*
* If (input - floor) < (ceiling - input)
* (i.e. floor is closer to input than ceiling)
* then return floor, otherwise return ceiling.
*/
return Duration.between(floor, input).compareTo(Duration.between(input, ceiling)) < 0 ? floor : ceiling;
}
来源:本人
With the answer above you end up with all kind of interesting code to handle overflows to hours, days etc.
I would use the time in ms since the epoch.
add 7.5minutes or 7.5x60x1000 = 450000
and truncate to a multiple of 900000
new Date(900000 * ((date.getTime() + 450000) / 900000))
This works, because the time where the ms time starts happens to be 00:00:00. And since all time zones in the world change in 15min steps, this does not affect rounding to quarters.
(Oops, I had a 0 too much and forgot some important parentheses : it is still too early)
很简单,找到自 1970 年以来的四分位数的两倍,将其四舍五入并乘以 15 分钟:
long timeMs = System.System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );
用它设置您的日期或日历对象。
精彩的帖子,非常感谢你们!这正是我需要的:)
这是我基于 jour 工作的代码。
我的用例是“鉴于现在是上午 11:47,我想设置两个日期来表示当前的 5 分钟帧:上午 11:45 和上午 11:50”
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
int modulo = calendar.get(Calendar.MINUTE) % 5;
if(modulo > 0) {
calendar.add(Calendar.MINUTE, -modulo);
}
myObject.setStartDate(calendar.getTime());
calendar.add(Calendar.MINUTE, 5);
myObject.setDueDate(calendar.getTime());
你可以使用这个简单的代码...
int mode = min % 15;
if (mode > 15 / 2) {
min = 15 - mode;
} else {
min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
另一种使用 java Instant api 的替代方法。
Instant instant = Instant.now();
int intervalInMinutes = 10;
instant.truncatedTo(ChronoUnit.MINUTES).minus(instant.atZone(ZoneId.of("UTC")).getMinute() % (1* intervalInMinutes),ChronoUnit.MINUTES);
我建议您使用现代日期时间 API *:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// Change it to the applicable ZoneId e.g. ZoneId.of("Asia/Kolkata")
ZoneId zoneId = ZoneId.systemDefault();
Stream.of(
"10:00",
"10:05",
"10:10",
"10:15",
"10:20",
"10:25",
"10:30"
).forEach(t -> System.out.println(roundToNearestQuarter(t, zoneId)));
}
static ZonedDateTime roundToNearestQuarter(String strTime, ZoneId zoneId) {
LocalTime time = LocalTime.parse(strTime);
return LocalDate.now()
.atTime(time)
.atZone(zoneId)
.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * Math.round(time.getMinute() / 15.0));
}
}
输出:
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
如果您正在寻找时间,请使用从获得ZonedDateTime#toLocalTime
的.LocalTime
ZonedDateTime
从Trail: Date Time了解有关现代日期时间 API 的更多信息。
*java.util
日期时间 API 及其格式化 APISimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到现代日期时间 API。出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目工作并且您的 Android API 级别仍然不兼容 Java-8,请通过脱糖和How to use ThreeTenABP in Android Project检查可用的 Java 8+ API。
如果您需要将时间四舍五入到最接近的任意级别,提供为Duration
:
static long truncateTo(long timeEpochMillis, Duration d) {
long x = timeEpochMillis / d.toMillis();
return x * d.toMillis();
}
也许您可以使用实用程序库来操作日期,例如,您有一个对您有用的 round 方法:
这是代码中的示例:
FastDateFormat formatter = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT;
Date now = new Date();
System.out.println("now = " + formatter.format(now));
// Get nearest second
Date nearestSecond = DateUtils.round(now, Calendar.SECOND);
System.out.println("nearestSecond = " + formatter.format(nearestSecond));
// Get nearest minute
Date nearestMinute = DateUtils.round(now, Calendar.MINUTE);
System.out.println("nearestMinute = " + formatter.format(nearestMinute));
// Get nearest hour
Date nearestHour = DateUtils.round(now, Calendar.HOUR);
System.out.println("nearestHour = " + formatter.format(nearestHour));
public static Date getCurrentDateTimeWithQuarterRounding() {
final Calendar calendar = new GregorianCalendar();
calendar.setTime(new Date());
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
final int minutes = calendar.get(Calendar.MINUTE);
if (minutes < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minutes >= 45) {
calendar.set(Calendar.MINUTE, 45);
} else if (minutes < 30) {
calendar.set(Calendar.MINUTE, 15);
} else {
calendar.set(Calendar.MINUTE, 30);
}
return calendar.getTime();
}
如果您有分钟,您可以使用以下功能将它们四舍五入:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;
minutes = (int) (Math.round(minutes / 15.0) * 15.0);
如果有人有兴趣获得最近的(向上或向下)五或十五间隔,我使用模块制作了一个功能来完成这项工作。
public LocalTime roundToTheNearestInterval(LocalTime original, Integer measurementInterval) {
LocalTime nearest;
int mod;
switch (measurementInterval) {
case 5:
mod = original.getMinute() % 5;
nearest = mod >= 3 ?
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 5 * (original.getMinute() / 5) + 5) :
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 5 * (original.getMinute() / 5));
break;
case 15:
mod = original.getMinute() % 15;
nearest = mod >= 8 ?
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 15 * (original.getMinute() / 15) + 15) :
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 15 * (original.getMinute() / 15));
break;
default:
nearest = original;
}
return nearest;
}
你可以试试这个单元测试
@Test
void roundToTheNearestInterval() {
//given
LocalTime originalTime1 = LocalTime.of(6, 31, 15);
LocalTime originalTime2 = LocalTime.of(19, 13, 42);
LocalTime originalTime3 = LocalTime.of(6, 37, 11);
LocalTime originalTime4 = LocalTime.of(19, 40, 34);
Integer measurementInterval_5min = 5;
Integer measurementInterval_15min = 15;
MyService myService = new MyService();
//when
LocalTime rounded1_5min = myService.roundToTheNearestInterval(originalTime1, measurementInterval_5min);
LocalTime rounded2_5min = myService.roundToTheNearestInterval(originalTime2, measurementInterval_5min);
LocalTime rounded1_15min = myService.roundToTheNearestInterval(originalTime3, measurementInterval_15min);
LocalTime rounded2_15min = myService.roundToTheNearestInterval(originalTime4, measurementInterval_15min);
//then
assertEquals(LocalTime.of(6, 30, 0), rounded1_5min);
assertEquals(LocalTime.of(19, 15, 0), rounded2_5min);
assertEquals(LocalTime.of(6, 30, 0), rounded1_15min);
assertEquals(LocalTime.of(19, 45, 0), rounded2_15min);
}
使用我在 Stackoverflow 上找到的一些代码,我创建了以下代码。它将每分钟输出四舍五入的季度。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
DateTimeFormatter Datum_Format = DateTimeFormatter.ofPattern("HH:mm");
LocalDateTime time = LocalDateTime.now();
for(int i=0; i<=59; i++) {
time = time.withMinute(i);
int Minute = time.getMinute();
int Quarter = 15 * (int) Math.round(Minute / 15);
if (Quarter == 60) {
Time2 = time.plusHours(1);
Time2 = Time2.withMinute(0);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
else {
Time2 = time;
Time2 = Time2.withMinute(Quarter);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
}
当我将代码输出到控制台时,您必须将 LOG.info 替换为 System.out.println 之类的内容。
结果:
2016-08-16 15:14:31 信息 15:05,15:00
2016-08-16 15:14:31 信息 15:06,15:00
2016-08-16 15:14:31 信息 15:07 ,15:00
2016-08-16 15:14:31 信息 15:08,15:15
2016-08-16 15:14:31 信息 15:09,15:15
2016-08-16 15:14:31信息 15:10,15:15
使用以下函数将分钟数四舍五入到最后一个季度getRecentQuater():Date
,getSysDate_LastQuarterMins("dd.MM.yyyy HH:mm:ss"):String
:将LocalDateTime 转换为日期
public static Date getRecentQuater() {
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS).plusMinutes(getLastQuarterValue(time.getMinute()));
System.out.println("lastQuarter LocalDateTime: " + lastQuarter);
Date date = Date.from(lastQuarter.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("lastQuarter Date: " + lastQuarter);
return date;
}
public static String getSysDate_LastQuarterMins(String dateFormat) {
Date date = getRecentQuater();
SimpleDateFormat ft = new SimpleDateFormat (dateFormat);
String sysDate_RoundMin = ft.format(date);
System.out.println("getSysDate_LastQuarterMins() LocalDateTime : "+sysDate_RoundMin);
return sysDate_RoundMin;
}
getSysDate_LastQuarterMins() : Mon Jan 20 17:30:00 CET 2020
public static Date getSysDate_LastQuarterMins() {
Calendar cal = Calendar.getInstance();
cal.setTime( new Date(System.currentTimeMillis()) );
int min = cal.get(Calendar.MINUTE);
cal.set(Calendar.MINUTE, getLastQuarterValue(min));
cal.set(Calendar.SECOND, 00);
Date lastQuarter = cal.getTime();
System.out.println("getSysDate_LastQuarterMins() Calendar : "+lastQuarter);
return lastQuarter;
}
您可以从以下函数中找到 LastQuarter Value Round 值,并在函数调用中提供了一些输出diaplayLastQuarter_RoundValue(min)
:
Min: 10, LastQuarter: 0, Round: 15
Min: 24, LastQuarter: 15, Round: 30
Min: 36, LastQuarter: 30, Round: 30
Min: 37, LastQuarter: 30, Round: 30
Min: 38, LastQuarter: 30, Round: 45
Min: 39, LastQuarter: 30, Round: 45
Min: 44, LastQuarter: 30, Round: 45
Min: 57, LastQuarter: 45, Round: 00 [57, 07:45:00, 08:00:00]
public static void diaplayLastQuarter_RoundValue(int minutes) {
System.out.format("Min: %2d, LastQuarter: %2d, Round: %2d\n",
minutes, getLastQuarterValue(minutes), getRoundValue(minutes));
}
public static int getLastQuarterValue(int minutes) {
int min = 15 * (minutes / 15);
//System.out.println("Min: "+minutes+", getLastQuarterValue : "+ min);
return min;
}
public static int getRoundValue(int minutes) {
getLastQuarterValue(minutes);
int minRound = (int) (Math.round(minutes / 15.0) * 15.0);
//System.out.println("Min: "+minutes+", getRoundValue : "+minRound);
return minRound;
}