プログラミング
パーソナルなゴミ収集カレンダーの作成
Creating a Personalised Bin Calendar (alexwlchan.net)
要約
著者は、自治体が配布する情報密度の高いゴミ収集カレンダーの読みにくさを解消するため、Pythonを使ってパーソナルなゴミ収集カレンダーを自作する方法を紹介しています。標準のHTMLカレンダーモジュールをカスタマイズし、各日付にID属性を付与してHTMLファイルとして出力後、CSSで装飾することで、個人のゴミ収集日を視覚的に分かりやすく表示できるカレンダーを作成します。
全文翻訳
パーソナルなゴミ収集カレンダーの作成
2026年3月26日投稿
Pythonにも分類
毎年春になると、私の自治体は新しいゴミ収集カレンダーを発行します。これらのカレンダーは通常、地域全体をカバーする単一のPDFとして公開され、情報はコンパクトなデザインに詰め込まれています。印刷コストを節約するためでしょう。皆に同じものを配布できるよう、一括でカレンダーを印刷できるのです。
これはサウス・ケンブリッジのこうしたコンパクトな図の例です。この地域は郡を4つの異なる地域に分けています。
私は8年以上サウス・ケンブリッジには住んでいませんので、これは私のカレンダーではありませんが、地元の自治体にリンクすることでインターネットに私の居住地を教えたくはありません。
例えば、いつものゴミの収集日が木曜日なら、その年の最後の収集は12月22日月曜日になります。
このコンパクトな表現はデザインの驚異ですが、一軒家に住む私にとってはあまり役に立ちません。郡全体ではなく、私の通りのゴミ収集日だけが重要です。
数年前から、私はゴミがいつ収集されるかを示すパーソナルなカレンダーを作成しており、それを印刷して冷蔵庫に貼っています。手作業ですが、今少しの労力を払うことで、一年を通してその恩恵を受けることができます。
まずPythonを使ってHTMLカレンダーを生成します。組み込みのcalendarモジュールがあり、さまざまな形式でカレンダーを出力できます。これは<td>セルに個別の日付情報を埋め込むわけではないので、HTMLCalendarクラスをカスタマイズして、日付をid属性として書き込みます。
これは2026年4月から2027年3月までのカレンダーを生成する私のスクリプトです。
```python
from calendar import HTMLCalendar
from datetime import date
class PerDateCalendar(HTMLCalendar):
"""
各日付にID属性(例: `d-2026-03-27`)を追加し、曜日の略称(M, Tu, W, …)を使用する、カスタマイズされたHTMLカレンダー。
"""
def formatday(self, day: int, weekday: int) -> str:
"""
単一の日付を表すテーブルセル、またはカレンダー上の空白の場合は空のセルを返します。
"""
if day == 0:
return f'<td class="{self.cssclass_noday}"> </td>'
else:
current_date = date(self.current_year, self.current_month, day)
date_string = current_date.strftime("%Y-%m-%d")
return f'<td id="d-{date_string}">{day}</td>'
def formatmonth(self, year: int, month: int, withyear=True) -> str:
"""
月ごとのカレンダーを表すテーブルを返します。
"""
# formatday() から見えるように、現在の月/年を保存します
self.current_year = year
self.current_month = month
return super().formatmonth(year, month, withyear)
def formatweekday(self, day: int) -> str:
"""
単一の曜日の名前を表すテーブルヘッダーセルを返します。
"""
custom_names = ["M", "Tu", "W", "Th", "F", "Sa", "Su"]
return f"<th>{custom_names[day]}</th>"
if __name__ == "__main__":
cal = PerDateCalendar()
start_year, start_month = 2026, 4
end_year, end_month = 2027, 3
full_calendar_html = (
"<html>"
'<head><link href="style.css" rel="stylesheet"></head>'
'<body><div id="grid">'
)
current_year, current_month = start_year, start_month
while (current_year < end_year) or \
( current_year == end_year and current_month <= end_month ):
month_html = cal.formatmonth(current_year, current_month)
full_calendar_html += month_html
if current_month == 12:
current_month = 1
current_year += 1
else:
current_month += 1
full_calendar_html += "</div></body></html>"
with open("bin_calendar.html", "w") as f:
f.write(full_calendar_html)
```
これにより、各月がテーブルで、各日が個別に識別可能なセルであるHTMLファイルが生成されます。出力のサンプルは以下の通りです。
```html
<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr>
<th colspan="7" class="month">April 2026</th>
</tr>
<tr>
<th>M</th><th>Tu</th><th>W</th><th>Th</th><th>F</th><th>Sa</th><th>Su</th>
</tr>
<tr>
<td class="noday"> </td><td class="noday"> </td><td id="d-2026-04-01">1</td><td id="d-2026-04-02">2</td><td id="d-2026-04-03">3</td><td id="d-2026-04-04">4</td><td id="d-2026-04-05">5</td>
</tr>
```
HTMLは外部スタイルシート`style.css`を参照しており、これにはカレンダーを3列表示に変換する基本的なスタイルが含まれています。
```css
#grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3em;
width: 600px;
margin: 0 auto;
font-family: Helvetica;
}
th {
padding-bottom: 5px;
}
td {
font-size: 0.9em;
line-height: 1.4em;
text-align: center;
}
```
その後、作成したIDを使用して各日付の<td>セルをターゲットにすることで、個々のゴミ収集日をハイライトできます。
```css
/* 黒/白の背景 */
#d-2026-04-03, #d-2026-04-24 {
font-size: 1.1em;
font-weight: bold;
background: black;
color: white;
border-bottom: 1px solid white;
border-top: 1px solid white;
}
/* 緑/白の背景 */
#d-2026-04-10, #d-2026-04-24 {
font-size: 1.1em;
font-weight: bold;
background: green;
color: white;
border-bottom: 1px solid white;
border-top: 1px solid white;
}
```
すべてのゴミ収集日を手作業でカレンダーに転記するのに5分もかかりませんが、結果は以下のようになります。
これは紙一枚にきれいに収まるので、印刷して冷蔵庫に貼ります。収集日が通常と異なる日や、次の収集日がいつかを確認するのが簡単です。
私はこのカレンダーを使って、収集をスキップできるかどうかを知ることがよくあります。一人暮らしでゴミの量は少ないため、ゴミ箱が半分以上満杯になることはめったにありません。半分も満たないゴミ箱を出すのはもったいないと思いますが、次の数回の収集を欠席することが分かっていれば、それでも出します。