如何在java中将时间缩短到最接近的四分之一小时?

loc*_*ock 51 java

鉴于今天的时间,例如下午2:24,如何让它到下午2:30?

同样,如果时间是下午2:17,我如何让它到下午2:15?

Sea*_*oyd 80

四舍五入

您需要使用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));
Run Code Online (Sandbox Code Playgroud)

正如EJP所指出的,这也没关系(替换最后一行,只有在日历宽松的情况下才有效):

calendar.set(Calendar.MINUTE, unroundedMinutes + mod);
Run Code Online (Sandbox Code Playgroud)

改进

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

calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Run Code Online (Sandbox Code Playgroud)

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

calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
Run Code Online (Sandbox Code Playgroud)

  • 这种方法会将分钟数降到最近的季度最低点,您需要添加一些检查是否四舍五入到下一小时,以便您也需要更新小时... (2认同)

Dir*_*irk 22

如果您只想向下舍入,这是一个使用Java Time API的更易读的版本:

LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS)
                                .plusMinutes(15 * (time.getMinute() / 15));
Run Code Online (Sandbox Code Playgroud)

输出:

2016-11-04T10:58:10.228

2016-11-04T10:45:00

  • 顺便说一句,对于时间轴上的某个点,对于实际时刻,`LocalDateTime` 是错误的类。缺乏任何区域/偏移量概念,它们是不确定的。使用相同的逻辑,但使用 `ZonedDateTime.now()`。 (2认同)
  • 顺便说一句,如果您想要一半,则可以是(15 *(time.getMinute()+ 7.5)/ 15)。 (2认同)

小智 10

这很简单,找到自1970年以来的季度数量为双倍,四舍五入并乘以15分钟:

long timeMs = System.System.currentTimeMillis();

long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );
Run Code Online (Sandbox Code Playgroud)

用它设置日期或日历对象.

  • 括号不匹配。我认为代码应该是:`long timeMs = System.currentTimeMillis();``long roundedtimeMs = Math.round( (double)timeMs/(15*60*1000) ) * (15*60*1000);` (2认同)

Pet*_*ans 9

有了上面的答案,你最终得到了所有有趣的代码来处理溢出到几小时,几天等.

我将使用自纪元以来的ms时间.

添加7.5分钟或7.5x60x1000 = 450000

并截断为900000的倍数

new Date(900000 * ((date.getTime() + 450000) / 900000))
Run Code Online (Sandbox Code Playgroud)

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

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

  • 你是绝对正确的,我没有考虑闰秒.但是上次我检查时,java.util.Date中没有对闰秒的支持,所以人们会设置他们的计算机时钟以匹配墙上时间(或原子钟),JVM会计算错误的纪元开始(关闭)按闰秒数).所以在实践中这将起作用并且会节省一堆棘手的代码,这也必须处理闰秒.结论:使用ntp保持计算机时钟同步. (4认同)
  • "世界上所有时区都以30分钟的步伐改变" - 所有时区都不是这样.有时区使用15分钟的实施. (3认同)

Dev*_*Dev 7

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;
  }
Run Code Online (Sandbox Code Playgroud)

来源:我自己


lbo*_*oix 6

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

这是我基于工作的代码。

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