timezone in api

I've been working on adding timezone support for the fixture details endpoint /football/fixtures?date=2025-03-29

The easiest and correct way to do this is by adding timezone as a query parameter to the endpoint
GET /football/fixtures?date=2025-03-29&timezone=America/Los_Angeles

Things to consider

example fast api python code

from fastapi import FastAPI, Query, HTTPException
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import pytz  # if using Python < 3.9

app = FastAPI()

@app.get("/football/fixtures")
def get_fixtures(date: str = Query(...), timezone: str = Query("UTC")):
    try:
        # Parse input date
        input_date = datetime.strptime(date, "%Y-%m-%d")

        # Validate timezone
        try:
            tz = ZoneInfo(timezone)
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid timezone")

        # Convert input date to UTC range
        start_dt = input_date.replace(tzinfo=tz).astimezone(ZoneInfo("UTC"))
        end_dt = (input_date + timedelta(days=1)).replace(tzinfo=tz).astimezone(ZoneInfo("UTC"))

        # Query fixtures in that UTC range
        fixtures = query_fixtures_between(start_dt, end_dt)

        # Convert match times to client's timezone
        for f in fixtures:
            f["match_time_local"] = f["match_time_utc"].astimezone(tz).isoformat()

        return fixtures

    except ValueError:
        raise HTTPException(status_code=400, detail="Invalid date format. Use YYYY-MM-DD.")

example of parsing the timezone to select games between 00:00 to 11:59 of the localized date


@app.get("/football/fixtures")
def get_football_fixtures(
    date: Optional[str] = Query(None, description="Date in YYYY-MM-DD format"),
    has_odds: bool = Query(True, description="Filter fixtures that have odds data"),
    timezone: Optional[str] = Query(None, description="Timezone in IANA format (e.g., America/Los_Angeles)"),
    db: Session = Depends(get_db)
):
    from datetime import timedelta
    from zoneinfo import ZoneInfo
    
    # Build the base query
    query = db.query(FootballFixture)
    
    # Apply date filter if provided
    if date:
        try:
            # Parse the date string to datetime object
            parsed_date = datetime.strptime(date, "%Y-%m-%d")
            
            # Apply timezone conversion if timezone is provided
            if timezone:
                try:
                    tz = ZoneInfo(timezone)
                    # Set the start and end of the day in the specified timezone
                    localized_start = datetime(parsed_date.year, parsed_date.month, parsed_date.day, 0, 0, 0, 0, tzinfo=tz)
                    localized_end = datetime(parsed_date.year, parsed_date.month, parsed_date.day, 23, 59, 59, 999999, tzinfo=tz)
                    # Convert to UTC for database comparison
                    utc_start = localized_start.astimezone(ZoneInfo("UTC"))
                    utc_end = localized_end.astimezone(ZoneInfo("UTC"))
                    
                    # Filter fixtures for the specified date in the timezone (from 12:00am to 11:59:59.999999pm)
                    query = query.filter(
                        FootballFixture.date >= utc_start,
                        FootballFixture.date <= utc_end
                    )
                except Exception:
                    return {
                        "get": "fixtures",
                        "parameters": {"date": date, "timezone": timezone},
                        "errors": ["Invalid timezone format. Please use IANA timezone format (e.g., America/Los_Angeles)."],
                        "results": 0,
                        "response": []
                    }
            else:
                # No timezone specified, use UTC
                query = query.filter(
                    FootballFixture.date >= datetime.combine(parsed_date.date(), datetime.min.time()),
                    FootballFixture.date < datetime.combine(parsed_date.date() + timedelta(days=1), datetime.min.time())
                )
        except ValueError:
            return {
                "get": "fixtures",
                "parameters": {"date": date, "timezone": timezone} if timezone else {"date": date},
                "errors": ["Invalid date format. Please use YYYY-MM-DD format."],
                "results": 0,
                "response": []
            }

list of supported timezones

encoding the url because the urls cannot contain raw slashes


Timezone: America/Los_Angeles

should be encoded to 

America%2FLos_Angeles

the example url should look like this

http://localhost:8000/football/fixtures?date=2025-03-29&timezone=America%2FLos_Angeles

when working from the client, for example, ios, use encode a url in swift