Skip to content

Instantly share code, notes, and snippets.

@dwightgunning
Created September 17, 2023 11:27
Show Gist options
  • Save dwightgunning/fc6c11c00925d20c70bdd1221f9928bd to your computer and use it in GitHub Desktop.
Save dwightgunning/fc6c11c00925d20c70bdd1221f9928bd to your computer and use it in GitHub Desktop.
Proof-of-concept function to determine the NBA season (ie. year) based on a given date
import bisect
from datetime import datetime
from typing import (
Optional
)
import pytz
LEAGUE_OFFICE_TZ = pytz.timezone('America/New_York')
def datetime_league_tz(year, month, day):
return LEAGUE_OFFICE_TZ.localize(datetime(year, month, day))
# https://en.wikipedia.org/wiki/1949%E2%80%9350_NBA_season
FIRST_SEASON_START_DATE = datetime_league_tz(1949,11,1)
# https://data.nba.com/data/10s/v2015/json/mobile_teams/nba/{YEAR}/league/00_full_schedule_week.json
SEASONS = [
(datetime_league_tz(2018, 9, 28), datetime_league_tz(2019, 6, 14)),
(datetime_league_tz(2019, 10, 22), datetime_league_tz(2020, 10, 11)),
(datetime_league_tz(2020, 12, 11), datetime_league_tz(2021, 7, 21)),
(datetime_league_tz(2021, 10, 3), datetime_league_tz(2022, 6, 17)),
(datetime_league_tz(2022, 10, 2),datetime_league_tz(2023, 6, 13)),
(datetime_league_tz(2023, 10, 5),datetime_league_tz(2024, 4, 14)), # Subject to change
]
DEFAULT_SEASON_START_MONTH = 9
DEFAULT_SEASON_START_DAY = 1
DEFAULT_SEASON_END_MONTH = 6
DEFAULT_SEASON_END_DAY = 30
def create_fallback_season(lookup_date):
if (lookup_date.month, lookup_date.day) < (DEFAULT_SEASON_START_MONTH, DEFAULT_SEASON_START_DAY):
season_year = lookup_date.year - 1
else:
season_year = lookup_date.year
return (
datetime_league_tz(season_year, DEFAULT_SEASON_START_MONTH, DEFAULT_SEASON_START_DAY),
datetime_league_tz(season_year + 1, DEFAULT_SEASON_END_MONTH, DEFAULT_SEASON_END_DAY)
)
def get_season_start_year(lookup_date: Optional[datetime] = None) -> int:
if not lookup_date:
lookup_date = datetime.now(LEAGUE_OFFICE_TZ)
if lookup_date < FIRST_SEASON_START_DATE:
return None
season_idx = bisect.bisect_left(SEASONS, lookup_date, key=lambda i: i[0])
if season_idx == 0:
season = SEASONS[season_idx] if lookup_date >= SEASONS[season_idx][0] else create_fallback_season(lookup_date)
elif season_idx == len(SEASONS):
season = SEASONS[season_idx-1] if lookup_date <= SEASONS[season_idx-1][1] else create_fallback_season(lookup_date)
else:
season = SEASONS[season_idx-1]
return season[0].year if lookup_date >= season[0] and lookup_date <= season[1] else None
## testing
assert get_season_start_year(datetime_league_tz(1892,3,12)) is None, "expected None"
assert get_season_start_year(datetime_league_tz(2018,1,1)) == 2017, "expected 2017"
assert get_season_start_year(datetime_league_tz(2019,11,1)) == 2019, "expected 2019"
assert get_season_start_year(datetime_league_tz(2020, 10, 11)) == 2019, "expected 2019"
assert get_season_start_year(datetime_league_tz(2020, 10, 12)) is None, "expected None"
assert get_season_start_year(datetime_league_tz(2023,10,6)) == 2023, "expected 2023"
assert get_season_start_year(datetime_league_tz(2023,10,1)) is None, "expected None"
assert get_season_start_year(datetime_league_tz(2024,12,25)) == 2024, "expected 2024"
assert get_season_start_year(datetime_league_tz(2025,1,3)) == 2024, "expected 2024"
assert get_season_start_year(datetime_league_tz(2027,11,3)) == 2027, "expected 2027"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment