Spaces:
Sleeping
Sleeping
File size: 3,366 Bytes
e780e98 0170ac5 2c59439 0170ac5 e780e98 0170ac5 e780e98 2c59439 e780e98 2c59439 e780e98 2c59439 e780e98 0170ac5 e780e98 0170ac5 e780e98 0170ac5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | from datetime import datetime, time, timedelta
def _eastern_utc_offset(now_utc):
"""
Returns the UTC offset in hours for Eastern time (EST=-5, EDT=-4).
Uses North American DST rules: starts second Sunday in March at 2 AM EST (07:00 UTC),
ends first Sunday in November at 2 AM EDT (06:00 UTC).
"""
year = now_utc.year
from datetime import timezone
march_1 = datetime(year, 3, 1, tzinfo=timezone.utc)
first_sun_mar = march_1 + timedelta(days=(6 - march_1.weekday()) % 7)
dst_start = first_sun_mar + timedelta(weeks=1, hours=7)
nov_1 = datetime(year, 11, 1, tzinfo=timezone.utc)
first_sun_nov = nov_1 + timedelta(days=(6 - nov_1.weekday()) % 7)
dst_end = first_sun_nov + timedelta(hours=6)
if dst_start <= now_utc < dst_end:
return 4 # EDT
return 5 # EST
def hms_to_seconds(hms_str):
"""Converts GTFS 'HH:MM:SS' (e.g. '25:30:00') to total seconds from midnight."""
h, m, s = map(int, hms_str.split(':'))
return (h * 3600) + (m * 60) + s
def get_service_day_start_ts():
"""
Returns the Unix timestamp (UTC) for 00:00:00 of the CURRENT service day.
TTC service day flips at 4:00 AM Eastern time (handles DST automatically).
All timestamps are in UTC to match GTFS Realtime timestamps.
"""
from datetime import timezone
try:
# Python 3.9+ has zoneinfo built-in
from zoneinfo import ZoneInfo
eastern_tz = ZoneInfo("America/Toronto")
except ImportError:
# Fallback for older Python versions - use pytz if available
try:
import pytz
eastern_tz = pytz.timezone("America/Toronto")
except ImportError:
# Last resort: pure-Python DST-aware Eastern offset
now_utc = datetime.now(timezone.utc)
utc_offset = _eastern_utc_offset(now_utc)
if now_utc.hour < (4 + utc_offset): # 4 AM Eastern in UTC
service_date = now_utc.date() - timedelta(days=1)
else:
service_date = now_utc.date()
service_start_utc = datetime.combine(service_date, time.min, tzinfo=timezone.utc) + timedelta(hours=utc_offset)
return int(service_start_utc.timestamp())
# Get current UTC time and convert to Eastern
now_utc = datetime.now(timezone.utc)
now_eastern = now_utc.astimezone(eastern_tz)
# TTC service day flips at 4:00 AM Eastern
if now_eastern.hour < 4:
service_date = now_eastern.date() - timedelta(days=1)
else:
service_date = now_eastern.date()
# Create datetime at 00:00:00 Eastern, convert to UTC
try:
# zoneinfo (Python 3.9+)
service_start_eastern = datetime.combine(service_date, time.min, tzinfo=eastern_tz)
except TypeError:
# pytz needs localize
service_start_eastern = eastern_tz.localize(datetime.combine(service_date, time.min))
service_start_utc = service_start_eastern.astimezone(timezone.utc)
return int(service_start_utc.timestamp())
def translate_occupancy(status):
"""Maps GTFS occupancy enums to human readable strings."""
mapping = {
0: "Empty", 1: "Many Seats Available", 2: "Few Seats Available",
3: "No Seats Available", 5: "Full", 6: "Not In Service"
}
return mapping.get(status, "Full") # when in doubt assume the bus is full |