How to round DateTime of Joda library to the nearest X minutes?

后端 未结 6 1532
[愿得一人]
[愿得一人] 2020-12-28 14:42

How to round DateTime of Joda library to the nearest X minutes ?
For example:

X = 10 minutes
Jun 27, 11:32 -> Jun 27, 11         


        
相关标签:
6条回答
  • 2020-12-28 15:00

    I have a function for LocalTime class but I think it's very easy to adopt my sample for your case:

    (Kotlin lang)

    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())
        }
    }
    

    And usage:

    var userWakeTime = LocalTime(6, 42)
    userWakeTime = userWakeTime.round(15 * 60 * 1000) // userWakeTime = 6:45
    
    0 讨论(0)
  • 2020-12-28 15:06

    When you want to round Joda DateTime the best solution IMHO is to use the built-in roundHalfCeilingCopy and roundHalfFloorCopy methods:

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

    Please note that roundHalfCeilingCopy will favor the ceiling if halfway. You can use roundHalfFloorCopy in order to favor the floor in case it's halfway.

    0 讨论(0)
  • 2020-12-28 15:07

    Using pure DateTime (Joda) Java Library:

    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()
        );
    
    0 讨论(0)
  • 2020-12-28 15:15

    Here's another approach that uses arithmetic on Unix time for completeness:

    (Implemented in Scala for clarity.)

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

    Example usage:

    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
    
    0 讨论(0)
  • 2020-12-28 15:20

    The accepted answer doesn't correctly handle datetimes that have seconds or milliseconds set. For completeness, here's a version that does handle that correctly:

    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);
    }
    
    0 讨论(0)
  • 2020-12-28 15:21

    I once hacked this Method to do something like it. It's not optimized in any way, but it did what I wanted at the time. Never made it in any production environment, and I cannot tell you anything about performance.

    @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);
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题