DateLocator in matplotlib to show the first days of both the week and the month

I would like to create a DateLocator in matplotlib that selects all Mondays and the first days of the month. As matplotlib uses the dateutil library I read the docs of how to use RRuleLocator with rrule objects. With the rruleset object from dateutil I can achieve the required functionality:

>>> rrset = rruleset()
>>> rrset.rrule(rrule(DAILY, byweekday=MO, count=5))
>>> rrset.rrule(rrule(DAILY, bymonthday=1, count=5))
>>> list(rrset)
[datetime.datetime(2020, 11, 30, 16, 10, 2),
 datetime.datetime(2020, 12, 1, 16, 10, 2),
 datetime.datetime(2020, 12, 7, 16, 10, 2),
 datetime.datetime(2020, 12, 14, 16, 10, 2),
 datetime.datetime(2020, 12, 21, 16, 10, 2),
 datetime.datetime(2020, 12, 28, 16, 10, 2),
 datetime.datetime(2021, 1, 1, 16, 10, 2),
 datetime.datetime(2021, 2, 1, 16, 10, 2),
 datetime.datetime(2021, 3, 1, 16, 10, 2),
 datetime.datetime(2021, 4, 1, 16, 10, 2)]

But unfortunately I did not manage to find out how to use rruleset with matplotlib. RRuleLocator expects a rrulewrapper object (defined in matplotlib) that hides away the rrule instance and I can not use it with rruleset. Any other way to do this?

Answer

If I understood you correctly, calling .set_xticks(list(rrset)) might be enough. For example:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import dateutil
from dateutil.rrule import *
import datetime
import numpy as np

rrset = rruleset()
rrset.rrule(rrule(DAILY, byweekday=MO, count=5))
rrset.rrule(rrule(DAILY, bymonthday=1, count=5))
print(list(rrset))

## generate dates 90 days into the future
base = datetime.datetime.today()
dates = [base + datetime.timedelta(days=3*x) for x in range(30)]

fig = plt.figure(figsize=(10,5))
ax = plt.subplot(111)
ax.set_autoscale_on(True)

## simply plot dates over dates
ax.plot(dates,dates,marker='s')

ax.set_xticks(list(rrset))

formatter = mdates.DateFormatter('%m/%d/%y')
ax.xaxis.set_major_formatter(formatter)

ax.xaxis.set_tick_params(rotation=30, labelsize=10)

ax.autoscale_view()
ax.grid()
plt.show()

yields (today on 11/26/20 where 11/30/2020 is the next Monday, hence the tick label overlapping with the first of the month):

plotting with a custom date formatter