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 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)