currentCycle function
The half-open [start, end) billing cycle that contains on for
anchorDay.
start is the billing date on/before on's date; end is the next billing
date (the start of the following cycle), so the range is half-open and two
adjacent cycles never both claim the boundary day. anchorDay must be 1..31.
Example:
// Anchor 15, the 20th falls in the cycle that opened on the 15th.
currentCycle(DateTime(2026, 3, 20), 15);
// (start: 2026-03-15, end: 2026-04-15)
Audited: 2026-06-12 11:26 EDT
Implementation
({DateTime start, DateTime end}) currentCycle(DateTime on, int anchorDay) {
_checkAnchor(anchorDay);
final DateTime onDate = _dateOnly(on);
final DateTime thisMonth = billingDateInMonth(onDate.year, onDate.month, anchorDay);
// The cycle start is this month's billing date if [on] is on/after it,
// otherwise the previous month's billing date.
final DateTime start = thisMonth.isAfter(onDate)
? billingDateInMonth(onDate.year, onDate.month - 1, anchorDay)
: thisMonth;
final DateTime end = billingDateInMonth(start.year, start.month + 1, anchorDay);
return (start: start, end: end);
}