Quantization
Sometimes nanosecond precision is more than you need or is even too much. Quantization reduces the precision of a datetime by rounding down (or up, if that’s your thing) to a given amount. For example, quantizing 12:36 to 5 minutes gives 12:35, quantizing to 10 minutes gives 12:30, and quantizing to 1 hour gives 12:00.
This is useful for grouping datetimes into buckets such as hours, weeks or months, and for answering questions like “what quarter does this date land in?”
Date and time objects have a quantize() method that takes either a
Timespan
or
Period.
Normally you use the former for quantizing to less than one day, and the latter
for a day or more. Quantizing by a positive amount rounds down, and a negative
amount rounds up.
Less Than a Day
Quantizing by timespans less than a day works pretty much like you would expect. Some examples:
final date = LocalDateTime(2021, 2, 3, 13, 17, 46, 123456789);
date.quantize(Timespan(minutes: 5)) == LocalDateTime(2021, 2, 3, 13, 15);
date.quantize(-Timespan(minutes: 5)) == LocalDateTime(2021, 2, 3, 13, 20);
date.quantize(Timespan(hours: 12)) == LocalDateTime(2021, 2, 3, 12);
date.quantize(-Timespan(hours: 12)) == LocalDateTime(2021, 2, 4, 0);Days
Quantizing by days uses the total number of days since a fixed epoch beginning on Sunday and not the beginning of the month. This ensures a consistent amount of time between quantized dates. It’s also useful for quantizing to the beginning of the week. For example:
final date = LocalDate(2026, 2, 10); // (A Tuesday)
date.quantize(Period(days: 7)) == hasDate(2026, 2, 8); // (Sunday)Zoned
or
OffsetDateTime
to a Timespan of days works nearly the same as a Period of days, there is
one important difference: The Timespan will quantize to a date in UTC rather
than the date in the given zone or offset. In general, it’s best to use a
Period of days instead, which uses the correct zone or offset.Quantizing to a week that starts on a different day is a bit trickier. The basic idea is to subtract the number of days from Sunday to the target weekday, quantize, and then add those days back:
final adjustment = Period(days: Weekday.thursday.us);
final mostRecentThursday =
(date - adjustment).quantize(Period(days: 7)) + adjustment;
mostRecentThursday == hasDate(2026, 2, 5);Months
Quantizing by month uses the number of months since the beginning of the year.
For example, quantizing by Period(months: 3) rounds down to the nearest start
of the quarter (January 1, April 1, July 1, or October 1).
final date = LocalDate(2025, 5, 3);
final startOfMonth = date.quantize(Period(months: 1));
startOfMonth == hasDate(2025, 5, 1);
final startOfQuarter = date.quantize(Period(months: 3));
startOfQuarter == hasDate(2025, 4, 1);
final endOfQuarter = date.quantize(-Period(months: 3)) - Period(days: 1);
endOfQuarter == hasDate(2025, 6, 30);Years
Year quantization is straightforward. It rounds down (or up) to the beginning of a year. Some examples:
final date = LocalDate(2027, 7, 24);
final startOfDecade = date.quantize(Period(years: 10));
startOfDecade == LocalDate(2020, 1, 1);
final turnOfCentury = date.quantize(Period(years: 100));
turnOfCentury == LocalDate(2000, 1, 1);