Contents

Timezone lookup using latitude and longitud (part 2)

fastapi test project.

Contents

For the fastapi project we are going to use Sqlalchemy and postgresql taking some reference from the fastapi documentation.

# create a virtualenv, with any tool: poetry, pipenv, virtualenv module, etc 
pip install fastapi uvicorn aiofiles SQLAlchemy psycopg2-binary

project structure

.
├── Dockerfile
├── LICENSE
├── main.py
├── README.md
├── requirements.txt
└── timezone_utils
    ├── database.py
    ├── __init__.py
    ├── models.py
    ├── schemas.py
    └── utils.py

1 directory, 10 files

we define the models, schemas and engine for sqlalchemy and the api in the package timezone_utils

for the query of the timezone using sqlalchemy will be like this:

import sqlalchemy as sa
from sqlalchemy.orm import Session

from . import models, schemas


def get_timezone(db: Session, point: schemas.TimezoneInput) -> schemas.Timezone:
    name = db.query(models.Timezones.tzid).filter(
        sa.func.ST_Contains(
            models.Timezones.geom, sa.func.ST_MakePoint(
                point.longitude,
                point.latitude)
        )
    ).scalar()
    return schemas.Timezone(name=name)

similar to the query in SQL, but using sqlalchemy, for the api the endpoint will accept query parameters for latitude and longitude and return a json with the timezone name.

the endpoint is defined like this:

from fastapi import FastAPI, Depends, Query
from sqlalchemy.orm import Session

from timezone_utils import schemas, models, utils
from timezone_utils.database import engine, SessionLocal

models.Base.metadata.create_all(bind=engine)

tags_metadata = [
    {
        "name": "timezone",
        "description": "Find timezone"
    }
]

app = FastAPI(
    title="Timezone Lookup",
    description="Find timezone name using latitude and longitude",
    version="0.0.1",
    openapi_tags=tags_metadata
)


def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@app.get("/timezone", response_model=schemas.Timezone, tags=["timezone"])
async def get_timezone(
        latitude: float = Query(gt=-85, lt=85, default=0, example=12),
        longitude: float = Query(gt=-180, lt=180, default=0, example=-86),
        db: Session = Depends(get_db)
):
    point = schemas.TimezoneInput(latitude=latitude, longitude=longitude)
    return utils.get_timezone(db, point)

Then we can test using curl or the swagger ui from the api documentation.

curl -X GET "http://localhost:8000/timezone?latitude=16&longitude=-86" -H  "accept: application/json"

{
  "name": "America/Tegucigalpa"
}

timezone-api

This also can be implemented in Go and using a key value db Boltdb go - version

reference:

project code python - version