如何在Java中将时间四舍五入到最近的四分之一小时?
鉴于今天的时间 2:24 PM,如何将其舍入到2:30 PM?
同样,如果时间是2:17 PM,如何将其舍入为2:15 PM?
lock asked 2020-01-26T03:33:37Z
13个解决方案
80 votes
四舍五入
您将需要使用取模来截断四分之一小时:
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所指出的,这也是可以的(替换最后一行,仅当日历宽大时才有效):
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);
Sean Patrick Floyd answered 2020-01-26T03:34:11Z
21 votes
如果您只想四舍五入,可以使用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
Dirk answered 2020-01-26T03:34:44Z
10 votes
很简单,将自1970年以来的四分之一数加倍,四舍五入并乘以15分钟即可:
long timeMs = System.System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );
设置日期或日历对象。
Lindhardt answered 2020-01-26T03:35:08Z
9 votes
有了以上答案,您最终将获得各种有趣的代码来处理数小时,数天等的溢出。
我会使用自纪元以来的时间(毫秒)。
加7.5分钟或7.5x60x1000 = 450000
并截断为900000的倍数
new Date(900000 * ((date.getTime() + 450000) / 900000))
这是可行的,因为ms时间开始的时间恰好是00:00:00。 并且由于世界上所有时区都以15分钟为单位变化,因此这不会影响到四分之一的舍入。
(糟糕,我的0太大了,忘了一些重要的括号:现在还为时过早)
Peter Tillemans answered 2020-01-26T03:35:50Z
7 votes
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;
}
资料来源:我自己
Dev answered 2020-01-26T03:36:14Z
6 votes
精彩的帖子,非常感谢你们! 这正是我所需要的:)
这是我基于工作的代码。
我的用例是“鉴于现在是上午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());
lboix answered 2020-01-26T03:36:43Z
1 votes
也许您可以使用实用程序库来处理日期,例如,在这里,您有一个对您有用的舍入方法:
[http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/time/DateUtils.html#round%28java.util.Calendar,%20int%29]
这是代码示例:
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));
Torres answered 2020-01-26T03:37:12Z
1 votes
您可以使用此简单的代码...
int mode = min % 15;
if (mode > 15 / 2) {
min = 15 - mode;
} else {
min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
Kandha answered 2020-01-26T03:37:32Z
1 votes
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();
}
contrapost answered 2020-01-26T03:37:47Z
0 votes
如果您有时间,可以使用以下功能将其取整:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;
christian answered 2020-01-26T03:38:11Z
0 votes
minutes = (int) (Math.round(minutes / 15.0) * 15.0);
Christopher Masser answered 2020-01-26T03:38:27Z
0 votes
使用一些我在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));
}
}
当我将代码输出到控制台时,您将必须用System.out.println之类的内容替换LOG.info。
结果:
2016-08-16 15:14:31 INFO 15:05,15:00
2016-08-16 15:14:31 INFO 15:06,15:00
2016-08-16 15:14:31 INFO 15:07,15:00
2016-08-16 15:14:31 INFO 15:08,15:15
2016-08-16 15:14:31 INFO 15:09,15:15
2016-08-16 15:14:31 INFO 15:10,15:15
Xander answered 2020-01-26T03:39:22Z
0 votes
使用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);
Rakesh SKadam answered 2020-01-26T03:39:42Z