如何在java中将时间四舍五入到最近的四分之一小时?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3553964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:48:44  来源:igfitidea点击:

How to round time to the nearest quarter hour in java?

java

提问by lock

Given today's time e.g. 2:24PM, how do I get it to round to 2:30PM?

考虑到今天的时间,例如下午 2:24,我如何将其四舍五入到下午 2:30?

Similarly if the time was 2:17PM, how do I get it to round to 2:15PM?

同样,如果时间是下午 2 点 17 分,我如何将其舍入到下午 2 点 15 分?

采纳答案by Sean Patrick Floyd

Rounding

四舍五入

You will need to use modulo to truncate the quarter hour:

您将需要使用 modulo 来截断一刻钟:

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));

As pointed out by EJP, this is also OK (replacement for the last line, only valid if the calendar is lenient):

正如 EJP 所指出的,这也可以(替换最后一行,仅在日历宽松时有效):

calendar.set(Calendar.MINUTE, unroundedMinutes + mod);


Improvements

改进

If you want to be exact, you will also have to truncate the smaller fields:

如果您想准确,您还必须截断较小的字段:

calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

You can also use DateUtils.truncate()from Apache Commons / Langto do this:

您还可以使用DateUtils.truncate()Apache的共享/郎做到这一点:

calendar = DateUtils.truncate(calendar, Calendar.MINUTE);

回答by Peter Tillemans

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

添加 7.5 分钟或 7.5x60x1000 = 450000

and truncate to a multiple of 900000

并截断为 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.

这是有效的,因为 ms 时间开始的时间恰好是 00:00:00。由于世界上所有时区都以 15 分钟为步长变化,因此这不会影响四舍五入。

(Oops, I had a 0 too much and forgot some important parentheses : it is still too early)

(哎呀,我的 0 太多了,忘记了一些重要的括号:现在还为时过早)

回答by christian

if you have the minutes you can round them with the following function:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;

如果您有时间,您可以使用以下功能对它们进行四舍五入:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;

回答by Kandha

You can use this simple code...

您可以使用这个简单的代码...

int mode = min % 15;
if (mode > 15 / 2) {
    min = 15 - mode;
} else {
    min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);

回答by Torres

Maybe you can use an utility library for manipulating Dates, here for example you have a round method which can be useful for you:

也许您可以使用实用程序库来操作日期,例如,您有一个 round 方法,它对您很有用:

http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/time/DateUtils.html#round%28java.util.Calendar,%20int%29

http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/time/DateUtils.html#round%28java.util.Calendar,%20int%29

Here an example in code:

这是代码中的示例:

    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));

回答by Lindhardt

It's simple, find the number of quaters since 1970 as double, round it and multiply by 15 minutes:

很简单,求自 1970 年以来的四分位数为两倍,四舍五入并乘以 15 分钟:

long timeMs = System.System.currentTimeMillis();

long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );

Set your Date or Calendar object with that.

用它设置你的 Date 或 Calendar 对象。

回答by Christopher Masser

minutes = (int) (Math.round(minutes / 15.0) * 15.0);

回答by lboix

Wonderful post, thank you so much guys! It was exactly what I needed :)

精彩的帖子,非常感谢你们!这正是我所需要的:)

Here's my code based on jour work.

这是我基于 jour 工作的代码。

My usecase is "Given it's 11:47 am, I want to set two dates symbolizing the current 5-minutes frame : 11:45 am and 11:50 am"

我的用例是“鉴于现在是上午 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()); 

回答by Dev

A commented implementation for Java 8. Accepts arbitrary rounding units and increments:

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;
  }

Source: myself

来源:我自己

回答by Xander

Using some code on I found on Stackoverflow, I have created the following code. It will output for every minute the quarter it will be rounded to.

使用我在 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));
  }
}

As I output the code to a console, you will have to replace the LOG.info with something like System.out.println.

当我将代码输出到控制台时,您必须将 LOG.info 替换为 System.out.println 之类的内容。

Result:

结果:

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

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