如何将Joda库的DateTime四舍五入到最接近的X分钟?

问题描述 投票:0回答:6

如何将

DateTime
库的
Joda
舍入到最接近的
X
分钟?
例如:

X = 10 分钟
6月27日 11:32 → 6月27日 11:30
6月27日 11:33 → 6月27日 11:30
6月27日 11:34 → 6月27日 11:30
6月27日 11:35 → 6月27日 11:40
6月27日 11:36 → 6月27日 11:40
6月27日 11:37 → 6月27日 11:40
java datetime jodatime
6个回答
32
投票

原始接受的答案无法正确处理设置了秒或毫秒的日期时间。为了完整起见,这里有一个正确处理该问题的版本:

private DateTime roundDate(final DateTime dateTime, final int minutes) {
    if (minutes < 1 || 60 % minutes != 0) {
        throw new IllegalArgumentException("minutes must be a factor of 60");
    }

    final DateTime hour = dateTime.hourOfDay().roundFloorCopy();
    final long millisSinceHour = new Duration(hour, dateTime).getMillis();
    final int roundedMinutes = ((int)Math.round(
        millisSinceHour / 60000.0 / minutes)) * minutes;
    return hour.plusMinutes(roundedMinutes);
}

17
投票

使用纯 DateTime (Joda) Java 库:

DateTime dt = new DateTime(1385577373517L, DateTimeZone.UTC);
// Prints 2013-11-27T18:36:13.517Z
System.out.println(dt);

// Prints 2013-11-27T18:36:00.000Z (Floor rounded to a minute)
System.out.println(dt.minuteOfDay().roundFloorCopy());

// Prints 2013-11-27T18:30:00.000Z (Rounded to custom minute Window)
int windowMinutes = 10;
System.out.println(
    dt.withMinuteOfHour((dt.getMinuteOfHour() / windowMinutes) * windowMinutes)
        .minuteOfDay().roundFloorCopy()
    );

9
投票

我曾经破解过这个方法来做类似的事情。它没有以任何方式优化,但它做了我当时想要的。从未在任何生产环境中实现过,我无法告诉您任何有关性能的信息。

@Test
     public void test() {
         System.out.println(roundDate(new DateTime().withMinuteOfHour(13)));
         System.out.println(roundDate(new DateTime().withMinuteOfHour(48)));
         System.out.println(roundDate(new DateTime().withMinuteOfHour(0)));
         System.out.println(roundDate(new DateTime().withMinuteOfHour(59)));
         System.out.println(roundDate(new DateTime().withMinuteOfHour(22)));
         System.out.println(roundDate(new DateTime().withMinuteOfHour(37)));
     }

    private DateTime roundDate(final DateTime dateTime) {
        final double minuteOfHour = dateTime.getMinuteOfHour();
        final double tenth = minuteOfHour / 10;
        final long round = Math.round(tenth);
        final int i = (int) (round * 10);

        if (i == 60) {
            return dateTime.plusHours(1).withMinuteOfHour(0);
        } else {
            return dateTime.withMinuteOfHour(i);
        }

    }

9
投票

为了完整性,这是另一种使用 Unix 时间算术的方法:

(为了清晰起见,在 Scala 中实现。)

import org.joda.time.{DateTime, Duration}

def roundDateTime(t: DateTime, d: Duration) = {
  t minus (t.getMillis - (t.getMillis.toDouble / d.getMillis).round * d.getMillis)
}

使用示例:

roundDateTime(new DateTime("2013-06-27T11:32:00"), Duration.standardMinutes(10))
// => 2013-06-27T11:30:00.000+02:00

roundDateTime(new DateTime("2013-06-27T11:37:00"), Duration.standardMinutes(10))
// => 2013-06-27T11:40:00.000+02:00

6
投票

当您想要舍入 Joda DateTime 时,最好的解决方案恕我直言是使用内置

roundHalfCeilingCopy
roundHalfFloorCopy
方法:

DateTime dateTime = DateTime.now();
DateTime newDateTime = dateTime.minuteOfHour().roundHalfCeilingCopy();

请注意,如果中途,

roundHalfCeilingCopy
将有利于天花板。您可以使用
roundHalfFloorCopy
来保护地板,以防地板半途而废。


1
投票

我有一个 LocalTime 类的函数,但我认为针对您的情况采用我的示例非常容易:

(科特林语言)

fun LocalTime.round(roundValue: Int): LocalTime {
    val timeInMillis = this.millisOfDay
    val remainder = timeInMillis % roundValue
    return when {
        remainder < (roundValue / 2) -> LocalTime.fromMillisOfDay((timeInMillis - remainder).toLong())
        else -> LocalTime.fromMillisOfDay((timeInMillis + (roundValue - remainder)).toLong())
    }
}

及用法:

var userWakeTime = LocalTime(6, 42)
userWakeTime = userWakeTime.round(15 * 60 * 1000) // userWakeTime = 6:45
© www.soinside.com 2019 - 2024. All rights reserved.