Skip to content

aaronshivers/calendar

Repository files navigation

US Holidays Calendar

This project builds an iCalendar (.ics) feed for a curated set of US holidays. The repository is optimized around serving that calendar from a stable URL that clients such as Apple Calendar, Google Calendar, and Outlook can subscribe to directly.

What This Repo Does

  • Generates a static us_holidays.ics file.
  • Bundles the holiday definitions with the Python package so the CLI works outside the repo root.
  • Serves the current year plus the next year by default, which keeps the feed practical without overcommitting to a long forecasting window.
  • Supports editing the holiday definition file with add-holiday and remove-holiday.
  • Treats weekend observance and per-holiday enable/disable switches as data in holidays.yaml, including leap-day safety.

Requirements

  • Python 3.13+
  • Poetry

Installation

poetry install

Generate the Calendar

Generate the current year plus the next year into us_holidays.ics:

poetry run generate_calendar

Generate a custom range:

poetry run generate_calendar --year 2025 --end-year 2030

Write to a different path:

poetry run generate_calendar --output /tmp/us-holidays.ics

Preview the build without writing a file:

poetry run generate_calendar --dry-run

Manage Holiday Definitions

The bundled holiday definitions live at src/generate_calendar/holidays.yaml.

Add a holiday to a specific YAML file:

poetry run generate_calendar add-holiday --holidays-file src/generate_calendar/holidays.yaml "National Pizza Day" 2 9

Remove a holiday from a specific YAML file:

poetry run generate_calendar remove-holiday --holidays-file src/generate_calendar/holidays.yaml "National Pizza Day"

If you run these commands against an installed, read-only package, pass --holidays-file so the CLI knows which editable YAML file to modify.

You can also disable a holiday without deleting it:

manual_holidays:
  - name: National Ice Cream Day
    month: 7
    day: 21
    enabled: false

If enabled is omitted, the holiday is included by default.

Cloudflare Deployment

The recommended permanent deployment path is Cloudflare Workers using the root-level wrangler.toml and package.json.

How it works:

  • Wrangler runs build_static_calendar.py at deploy time to generate a bundled .ics fallback artifact
  • the Worker serves the most recently stored calendar from Cloudflare KV and only falls back to the deploy-built artifact if KV is empty
  • a monthly Cloudflare cron trigger refreshes the stored calendar on the schedule in wrangler.toml
  • subscriber traffic only reads the stored calendar; it does not regenerate the feed
  • the Worker returns the file with text/calendar headers from a stable HTTPS URL

The monthly cron runs at 00:00 UTC on the first day of each month (0 0 1 * *).

Setup steps:

  1. From the repo root, run npm install.
  2. Create the KV namespace once with npx wrangler kv namespace create CALENDAR_CACHE.
  3. Copy the returned IDs into the commented [[kv_namespaces]] block in wrangler.toml.
  4. Deploy from the repo root with npx wrangler deploy.
  5. Subscribe iCloud or any other calendar client to the Worker URL.

When the repository is connected to Cloudflare, merging to the configured production branch triggers the Cloudflare build and deploy. The Worker compares the bundled deploy-time calendar timestamp with CALENDAR_CACHE; if KV is stale, it serves the fresh bundled calendar and refreshes KV in the background so subscribers receive the new feed without waiting for the monthly cron.

Repository Automation

update-calendar.yml is validation-only. It checks formatting, linting, typing, tests, and a dry-run calendar build on pushes and pull requests.

Quality Checks

poetry run black --check .
poetry run flake8 .
poetry run mypy .
poetry run pytest -q
npm run worker:verify

Project Layout

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

2 stars

Watchers

2 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors