Created
September 17, 2023 11:27
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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