'rrule.between skips months with missing days

I am trying to generate employee monthly anniversaries for a use-case I am working on. RRule offers a very convenient way to do this. However, I am unable to get the results I want from it.

See snippet below -

import arrow
from dateutil.rrule import MONTHLY, rrule

by_monthday = 31
start = arrow.get("2021-12-31").to(tz="utc")
end = arrow.get("2022-06-01").to(tz="utc")

rule = rrule(
    freq=MONTHLY,
    bymonthday=by_monthday,
    byhour=0,
    byminute=0,
    bysecond=0,
    dtstart=start.datetime,
)

for r in rule.between(start.datetime, end.datetime, inc=True):
    print(r)

Result --

2021-12-31 00:00:00+00:00
2022-01-31 00:00:00+00:00
2022-03-31 00:00:00+00:00
2022-05-31 00:00:00+00:00

rrule skips over the months that do not have the 31st which IMO is the expected behaviour of the library.

How can I handle the missing months in a clean way and set their default value to something like 2022-02-28 or 2022-04-30

Thanks!



Solution 1:[1]

I encounter your same problem and a solution that I found was to create a new dummy date that start on the first day of the month and use it on the rrule object, and then if you need the last day of the month you can use the calendar module

import datetime, calendar
from dateutil.rrule import MONTHLY, rrule

by_monthday = 1
start = datetime.datetime(2021, 12, 31)
end = datetime.datetime(2022, 6, 1)

rule = rrule(
    freq=MONTHLY,
    bymonthday=by_monthday,
    byhour=0,
    byminute=0,
    bysecond=0,
    dtstart=datetime.datetime(start.year, start.month, 1),
)

for r in rule.between(start, end, inc=True):
    print(datetime.datetime(r.year, r.month, calendar.monthrange(r.year, r.month)[1]))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Massimo Palmieri