Creating a Personalised Bin Calendar

surprisetalk1 pts0 comments

Creating a personalised bin calendar – alexwlchanSkip to main contentCreating a personalised bin calendar<br>Posted 26 March 2026<br>Also filed in Python<br>Every spring, my council publish a new bin collection calendar. These calendars are typically published as a single PDF to cover the entire region, with the information packed into a compact design. I imagine this design is for economy of printing – you can print one calendar in bulk, and post the same thing to everybody.<br>Here’s an example of this sort of compact diagram from South Cambridge, where breaks the county into four different regions:<br>I haven’t lived in South Cambridge for over eight years so this isn’t my calendar, but I don’t want to tell the Internet where I live by linking to a local council.For example, if your usual bin day is Thursday, your final collection of the year would be on Monday 22nd December.<br>This compact representation is a marvel of design, but it’s not that useful for me, a person who only lives in a single house. I only care about bin day on my street, not across the county.<br>For several years now, I’ve created a personalised calendar which shows when my bins will be collected, which gets printed and stuck it on my fridge. It’s a manual process, but a small amount of effort now pays off across the year.<br>I start by generating an HTML calendar using Python. There’s a built-in calendar module, which lets you output calendars in different formats. It doesn’t embed individual date information in the cells, so I customise the HTMLCalendar class to write the date as an id attribute.<br>Here’s my script, which generates a calendar from April 2026 to March 2027:<br>from calendar import HTMLCalendar<br>from datetime import date

class PerDateCalendar(HTMLCalendar):<br>"""<br>A customised HTML calendar that adds an `id` attribute to every day<br>(for example, `d-2026-03-27`) and uses single-letter abbrevations for<br>days of the week (M, Tu, W, …).<br>"""

def formatday(self, day: int, weekday: int) -> str:<br>"""<br>Returns a table cell representing a single day, or an empty cell<br>if this is a blank space in the calendar.<br>"""<br>if day == 0:<br>return f'{self.cssclass_noday}">&nbsp;'<br>else:<br>current_date = date(self.current_year, self.current_month, day)<br>date_string = current_date.strftime("%Y-%m-%d")<br>return f'{date_string}">{day}'

def formatmonth(self, year: int, month: int, withyear=True) -> str:<br>"""<br>Returns a table representing a month's calendar.<br>"""<br># Store the current month/year so they're visible to formatday()<br>self.current_year = year<br>self.current_month = month

return super().formatmonth(year, month, withyear)

def formatweekday(self, day: int) -> str:<br>"""<br>Returns a table header cell representing the name of a single weekday.<br>"""<br>custom_names = ["M", "Tu", "W", "Th", "F", "Sa", "Su"]

return f"{custom_names[day]}"

if __name__ == "__main__":<br>cal = PerDateCalendar()

start_year, start_month = 2026, 4<br>end_year, end_month = 2027, 3

full_calendar_html = (<br>""<br>''<br>''

current_year, current_month = start_year, start_month

while (current_year end_year) or (<br>current_year == end_year and current_month end_month<br>):<br>month_html = cal.formatmonth(current_year, current_month)<br>full_calendar_html += month_html

if current_month == 12:<br>current_month = 1<br>current_year += 1<br>else:<br>current_month += 1

full_calendar_html += ""

with open("bin_calendar.html", "w") as f:<br>f.write(full_calendar_html)This writes a calendar to an HTML file, where each month is a table, and each day is an individually identifiable cell. Here’s a sample of the output:<br>table border="0" cellpadding="0" cellspacing="0" class="month"><br>tr><br>th colspan="7" class="month">April 2026th><br>tr><br>tr><br>th>Mth><br>th>Tuth><br>th>Wth><br>th>Thth><br>th>Fth><br>th>Sath><br>th>Suth><br>tr><br>tr><br>td class="noday">&nbsp;td><br>td class="noday">&nbsp;td><br>td id="d-2026-04-01">1td><br>td id="d-2026-04-02">2td><br>td id="d-2026-04-03">3td><br>td id="d-2026-04-04">4td><br>td id="d-2026-04-05">5td><br>tr>The HTML references an external stylesheet style.css, which contains some basic styles that turn the calendar into a three-column view:<br>#grid {<br>display: grid;<br>grid-template-columns: repeat(3, 1fr);<br>gap: 3em;<br>width: 600px;<br>margin: 0 auto;<br>font-family: Helvetica;

th {<br>padding-bottom: 5px;

td {<br>font-size: 0.9em;<br>line-height: 1.4em;<br>text-align: center;<br>}Then I can highlight the individual days for my bin collections, by targeting the cells for each day using the id I created:<br>#d-2026-04-03,<br>#d-2026-04-24 {<br>font-size: 1.1em;<br>font-weight: bold;<br>background: black;<br>color: white;

border-bottom: 1px solid white;<br>border-top: 1px solid white;

#d-2026-04-10,<br>#d-2026-04-24 {<br>font-size: 1.1em;<br>font-weight: bold;<br>background: green;<br>color: white;

border-bottom: 1px solid white;<br>border-top: 1px solid white;<br>}It takes less than five minutes for me to transcribe all my bin dates to the calendar by hand, and this is what the result looks like:

That fits nicely on a single sheet of paper, so I print it and stick it on my fridge. It’s easy to see when I have an off-cycle bin day, or when my next...

calendar self current_month month current_year single

Related Articles