How to round time to the nearest quarter hour in Dart and Flutter?

Viewed 2750

I have a DateTime and would like to round it down to 15 seconds (or another interval).

e.g. "2020-03-16 12:23:53.756" to "2020-03-16 12:23:45.000"

and "2020-03-16 12:24:01.1234" to "2020-03-16 12:24:00.000"

3 Answers

You can do this in Dart and Flutter with an Extension on DateTime:

extension on DateTime{

  DateTime roundDown({Duration delta = const Duration(seconds: 15)}){
    return DateTime.fromMillisecondsSinceEpoch(
        this.millisecondsSinceEpoch -
        this.millisecondsSinceEpoch % delta.inMilliseconds
    );
  }
}

Usage:

DateTime roundedDateTime = DateTime.now().roundDown();
print(roundedDateTime);

Output: "2020-03-16 12:23:45.000"

or

DateTime roundedDateTime = DateTime.now().roundDown(delta: Duration(hour: 1));
print(roundedDateTime);

Output: "2020-03-16 12:00:00.000"

Additional to answer above (remember to give a name for your extension, and beware of using this.):

extension DateTimeExtension on DateTime {
  DateTime roundDown({Duration delta = const Duration(days: 1)}) {
    return DateTime.fromMillisecondsSinceEpoch(
        millisecondsSinceEpoch - millisecondsSinceEpoch % delta.inMilliseconds);
  }
}

A more flexible option is this one

You can use this function to round up the time.

DateTime alignDateTime(DateTime dt, Duration alignment,
    [bool roundUp = false]) {
  assert(alignment >= Duration.zero);
  if (alignment == Duration.zero) return dt;
  final correction = Duration(
      days: 0,
      hours: alignment.inDays > 0
          ? dt.hour
          : alignment.inHours > 0
              ? dt.hour % alignment.inHours
              : 0,
      minutes: alignment.inHours > 0
          ? dt.minute
          : alignment.inMinutes > 0
              ? dt.minute % alignment.inMinutes
              : 0,
      seconds: alignment.inMinutes > 0
          ? dt.second
          : alignment.inSeconds > 0
              ? dt.second % alignment.inSeconds
              : 0,
      milliseconds: alignment.inSeconds > 0
          ? dt.millisecond
          : alignment.inMilliseconds > 0
              ? dt.millisecond % alignment.inMilliseconds
              : 0,
      microseconds: alignment.inMilliseconds > 0 ? dt.microsecond : 0);
  if (correction == Duration.zero) return dt;
  final corrected = dt.subtract(correction);
  final result = roundUp ? corrected.add(alignment) : corrected;
  return result;
}

and then use it the following way

void main() {
  DateTime dt = DateTime.now();
  var newDate = alignDateTime(dt,Duration(minutes:30));
  print(dt);  // prints 2022-01-07 15:35:56.288
  print(newDate); // prints 2022-01-07 15:30:00.000
}
Related