Skip to main content

Drop-in `holidays`-compatible lookup of special-event dates (Super Bowl, Oscars, ...). Data sourced from Wikidata; offline-only at runtime.

Project description

special-days

tests PyPI

Lookup dates for special events — Super Bowl Sunday, Oscars night, World Series Game 7, NCAA championship. Drop-in compatible with the holidays package, so the same date in calendar logic you already use for public holidays answers "is today Super Bowl Sunday?" too.

Zero runtime dependencies. Lookups are local by default; data is refreshed in CI from Wikidata and pip install --upgrade pulls the new dates. A long-running process can opt into a Wikidata refresh mid-run — see the dev guide.

Status: Alpha. Currently ships Super Bowl + Academy Awards (Oscars). The API is still moving — expect breaking changes on any release until the maintenance process has run for a while and I've learned what wants to change.

Install

pip install special-days

Quickstart — "what's special about today?"

The most common use: ask "is this date significant?" in the holidays-compatible way.

from datetime import date
from special_days import SpecialDays

sd = SpecialDays()                       # all events the package ships
sd.get_list(date(2025, 2, 9))            # ['Super Bowl']
sd.get_list(date(2025, 3, 2))            # ['Academy Awards']
sd.get_list(date(2025, 5, 1))            # []

Compose with the holidays package via union(...), preserving laziness on both sides:

import holidays
from special_days import SpecialDays, union

combined = union(holidays.US(), SpecialDays())
combined.get_list(date(2025, 2, 9))      # ['Super Bowl']
combined.get_list(date(2025, 7, 4))      # ['Independence Day']

Drop a flat name → emoji dict on top and you have a "what's special about today?" UI in a dozen lines:

EMOJI = {
    "Independence Day": "🎆",
    "Super Bowl":       "🏈",
    "Academy Awards":   "🎬",
}

def specials(d):
    return [(n, EMOJI[n]) for n in combined.get_list(d) if n in EMOJI]

specials(date(2025, 2, 9))               # [('Super Bowl', '🏈')]
specials(date(2025, 7, 4))               # [('Independence Day', '🎆')]
specials(date(2025, 5, 1))               # []

The full version is in examples/by_date.py.

Two ways to use it

Date-keyed (drop-in for holidays)

A dict[date, str] subclass populated from the shipped snapshot at construction time.

from datetime import date
from special_days import SuperBowl

sb = SuperBowl()                         # every known Super Bowl date
date(2025, 2, 9) in sb                   # True
sb[date(2025, 2, 9)]                     # 'Super Bowl'
sb.get_list(date(2025, 2, 9))            # ['Super Bowl']
len(sb)                                  # one entry per game, grows each year

# Filter to a subset of years.
SuperBowl(years=[1967, 2024, 2025])
SuperBowl(years=range(2020, 2030))

datetime.datetime values are normalized to date automatically, so mixing the two in a lookup just works.

Year-keyed (planner-style)

from datetime import date
from special_days import super_bowl

super_bowl.date(2025)                    # datetime.date(2025, 2, 9)
super_bowl.is_super_bowl_sunday(date(2025, 2, 9))   # True
super_bowl.all_known()                   # {1967: date(1967, 1, 15), ..., 2027: date(2027, 2, 14)}

Pick whichever shape fits the question.

Display strings

By default the dict value is the constant event name ("Super Bowl", "Academy Awards"). Pass label_with_edition=True for edition-numbered display strings:

SuperBowl(label_with_edition=True)[date(2025, 2, 9)]    # 'Super Bowl LIX'
Oscars(label_with_edition=True)[date(2025, 3, 2)]        # '97th Academy Awards'

Super Bowl 50 (2016) uses the Arabic numeral, matching official NFL branding; every other edition uses Roman. The Academy Awards labeller handles 1930's two ceremonies (the 2nd in April, the 3rd in November) and the subsequent resync at the 6th ceremony in 1934.

Two ceremonies in one year

Most series have at most one installment per year, but not all. 1930 hosted two Academy Awards (the 2nd and 3rd):

from special_days import oscars

oscars.date(1930)                        # datetime.date(1930, 4, 3)  -- first only
oscars.dates(1930)                       # [date(1930, 4, 3), date(1930, 11, 5)]

SpecialDays/Oscars dicts contain both dates and label them distinctly when label_with_edition=True.

Recipes

Next upcoming event from today

is_super_bowl_sunday over a date range, or just iterate dates() / all_known():

from datetime import date, timedelta
from special_days import super_bowl

today = date.today()
upcoming = next(
    d for d in (today + timedelta(days=i) for i in range(365 * 2))
    if super_bowl.is_super_bowl_sunday(d)
)

All special days in a date range

from datetime import date, timedelta
from special_days import SpecialDays

sd = SpecialDays()
start, end = date(2025, 1, 1), date(2025, 12, 31)
days = [d for d in (start + timedelta(days=i)
                    for i in range((end - start).days + 1))
        if d in sd]
# [date(2025, 2, 9), date(2025, 3, 2)]

Just one event, not all of them

SpecialDays(events=[...]) accepts string names, classes, or already-built instances:

from special_days import SpecialDays, SuperBowl

SpecialDays(events=["super_bowl"])      # by registered name
SpecialDays(events=[SuperBowl])         # by class
SpecialDays(events=[SuperBowl(years=[2024, 2025])])   # pre-filtered instance

Data freshness

The shipped snapshot covers every event known to the maintainers at release time — every past game and every officially-announced future game. A daily CI job rebuilds the snapshot from Wikidata; if anything changed, it opens a PR. Once merged, a new patch release ships to PyPI. Run pip install --upgrade special-days to pull the latest.

For maintainers and curious users, the full pipeline is documented in docs/how_it_works.md.

Errors

  • super_bowl.date(year) raises KeyError if the year is not in the shipped snapshot. Upgrade the package to pick up newly-announced dates.
  • Non-int year arguments raise TypeError immediately.
  • SpecialDays(events=[...]) raises ValueError for unknown event strings, listing the valid ones.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

special_days-0.3.0.tar.gz (26.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

special_days-0.3.0-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file special_days-0.3.0.tar.gz.

File metadata

  • Download URL: special_days-0.3.0.tar.gz
  • Upload date:
  • Size: 26.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for special_days-0.3.0.tar.gz
Algorithm Hash digest
SHA256 cd4ba0d63df2272859152f22576b46503196b0f6da5cd24d4e07a07df863f5d1
MD5 2a954a762c14bc66750470a6a51c85f9
BLAKE2b-256 3374b4dca190bb6381de222dac989e3defb302c6ab232dc7593e5f71c387b77e

See more details on using hashes here.

Provenance

The following attestation bundles were made for special_days-0.3.0.tar.gz:

Publisher: release.yml on stringertheory/special-days

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file special_days-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: special_days-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for special_days-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b718cae2f34ca39bebc29ed11b928f3f9702526bf9e3bf3bb5b78bb03f6f0c2d
MD5 fb328f2cd8148dac79a010b975f6084c
BLAKE2b-256 ed60fdc108e9723515a331fca8d54c05734b7b0c76e11af9a57edcdf71f2680d

See more details on using hashes here.

Provenance

The following attestation bundles were made for special_days-0.3.0-py3-none-any.whl:

Publisher: release.yml on stringertheory/special-days

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page