2026-03-12 01:18:12 -04:00
|
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
|
from zoneinfo import ZoneInfo
|
|
|
|
|
|
|
|
|
|
EASTERN = ZoneInfo("America/New_York")
|
|
|
|
|
SHOW_DAY_DEFAULT = 2 # Wednesday (Monday=0)
|
|
|
|
|
SHOW_HOUR_DEFAULT = 22
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_show_week(
|
|
|
|
|
now_utc: datetime,
|
|
|
|
|
show_day: int = SHOW_DAY_DEFAULT,
|
|
|
|
|
show_hour: int = SHOW_HOUR_DEFAULT,
|
|
|
|
|
) -> tuple[datetime, datetime]:
|
|
|
|
|
"""Return (week_start_utc, week_end_utc) for the show week containing now_utc.
|
|
|
|
|
|
|
|
|
|
The week starts at show_day at show_hour Eastern Time and runs for 7 days.
|
|
|
|
|
"""
|
|
|
|
|
now_et = now_utc.astimezone(EASTERN)
|
|
|
|
|
|
|
|
|
|
days_since_show_day = (now_et.weekday() - show_day) % 7
|
|
|
|
|
candidate_date = now_et.date() - timedelta(days=days_since_show_day)
|
|
|
|
|
candidate = datetime(
|
|
|
|
|
candidate_date.year,
|
|
|
|
|
candidate_date.month,
|
|
|
|
|
candidate_date.day,
|
|
|
|
|
show_hour,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
tzinfo=EASTERN,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if candidate > now_et:
|
|
|
|
|
candidate -= timedelta(days=7)
|
|
|
|
|
|
|
|
|
|
week_start_utc = candidate.astimezone(timezone.utc).replace(tzinfo=timezone.utc)
|
|
|
|
|
week_end_utc = (candidate + timedelta(days=7)).astimezone(timezone.utc).replace(tzinfo=timezone.utc)
|
|
|
|
|
|
|
|
|
|
return week_start_utc, week_end_utc
|
2026-04-01 21:29:42 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_current_show_week(
|
|
|
|
|
now_utc: datetime,
|
|
|
|
|
show_day: int = SHOW_DAY_DEFAULT,
|
|
|
|
|
show_hour: int = SHOW_HOUR_DEFAULT,
|
|
|
|
|
rotation_delay_hours: float = 0,
|
|
|
|
|
) -> tuple[datetime, datetime]:
|
|
|
|
|
"""Return the show week that should be treated as "current" right now.
|
|
|
|
|
|
|
|
|
|
When *rotation_delay_hours* > 0 the switchover to a new show is postponed
|
|
|
|
|
by that many hours after the like-window boundary. During the gap the
|
|
|
|
|
previous week's show remains current so the host can view it while
|
|
|
|
|
recording. Likes made during the gap are collected by the new show once
|
|
|
|
|
it rotates in.
|
|
|
|
|
"""
|
|
|
|
|
if rotation_delay_hours <= 0:
|
|
|
|
|
return get_show_week(now_utc, show_day, show_hour)
|
|
|
|
|
effective_now = now_utc - timedelta(hours=rotation_delay_hours)
|
|
|
|
|
return get_show_week(effective_now, show_day, show_hour)
|