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