Back to Projects

Prayer Time API

Python
FastAPI
Pydantic
Web Scraping
Timezone Handling

Sep 2024 - Present

Prayer Time API Screenshot

Project Overview

The Prayer Time API is an open-source project that provides accurate prayer times for 35 locations across the UK. Built with Python, FastAPI, and Pydantic, it offers a reliable and easy-to-use interface for developers to integrate prayer times into their applications.

This project addresses the need for a standardized, accessible API for prayer times that can be used by mosques, Islamic centers, and individual developers to build applications that serve the Muslim community.

Key Features

  • Coverage for 35 UK locations including London, Birmingham, Manchester, and more
  • Automatic timezone handling with proper BST/GMT adjustments
  • Flexible endpoints for retrieving prayer times by day, month, or year
  • Convenience endpoints for today, tomorrow, and yesterday
  • Support for both 12-hour and 24-hour time formats
  • Comprehensive data validation using Pydantic models
  • RESTful API design with intuitive URL structure

Technical Implementation

The project consists of three main components:

1. Data Collection


import requests, json
from bs4 import BeautifulSoup

locations = [
    "aberystwyth", "bangor-wales", "birmingham", "bournemouth",
    # ... 35 UK locations in total
]

def decode_day(table_row):
    prayer_labels = ["imsaak", "dawn", "sunrise", "noon", "sunset", "maghrib", "midnight"]
    times = reversed(list(map(lambda x: x.string, day.find_all("td")))[:-1])
    return dict(zip(prayer_labels, times))

all_times = {}

for location in locations:
    print(f"Scraping times for {location.capitalize()}")
    # ... scraping logic
                

The data collection script uses BeautifulSoup to scrape prayer times from a reliable source for all 35 locations. The data is structured and saved as JSON for further processing.

2. Timezone Adjustment


import datetime
import json

# ... load prayer times

day = datetime.datetime(2024, 3, 31) # First day of BST (2024)
end_date = datetime.datetime(2024, 10, 27) # First day of reverting to GMT (2024)

while day != end_date:
    for location in locations:
        daily_times = prayer_times[location][day.month - 1][day.day - 1]
        for timename, time in daily_times.items():
            if timename in ("month", "day"):
                continue
            time = datetime.datetime.strptime(time, "%H:%M")
            new_time = datetime.datetime.strftime(time - datetime.timedelta(hours=1), "%H:%M")
            daily_times[timename] = new_time

    day += datetime.timedelta(days=1)
                

A dedicated script handles the conversion of prayer times to account for British Summer Time (BST), ensuring that the API always returns accurate times regardless of the time of year.

3. FastAPI Implementation


import json
import datetime as dt
from zoneinfo import ZoneInfo
from fastapi import FastAPI
from pydantic import BaseModel, conint, Field
from typing import Literal

PRAYER_LABELS = Literal["imsaak", "dawn", "sunrise", "noon", "sunset", "maghrib", "midnight"]

LOCATIONS = Literal["aberystwyth", "bangor-wales", "birmingham", /* ... */]

uk = ZoneInfo("Europe/London")

# ... data validation models

app = FastAPI()

# Today
@app.get("/{location}/today")
def get_today(location: str, use_24_hour: bool = True):
    today = dt.datetime.now(dt.UTC).astimezone(uk)
    return get_day(location, today.month, today.day, use_24_hour)

# ... more endpoints for different time periods and formats
                

The API is built using FastAPI with strong type checking and validation through Pydantic models. It provides intuitive endpoints for accessing prayer times by location, date, and specific prayer times, with proper timezone handling using Python's zoneinfo module.

API Endpoints

Get today's prayer times:

GET /{location}/today

Get a specific prayer time for today:

GET /{location}/today/{prayer_name}

Get prayer times for a specific date:

GET /{location}/{month}/{day}

Get prayer times for an entire month:

GET /{location}/{month}

Get prayer times for the entire year:

GET /{location}

Challenges & Solutions

One of the main challenges was handling British Summer Time (BST) correctly. The UK switches between GMT and BST, which affects prayer times. I implemented a robust timezone handling system using Python's datetime and zoneinfo modules to ensure accurate prayer times year-round.

Another challenge was ensuring data integrity across 35 different locations. I created a comprehensive data validation system using Pydantic models to verify that all inputs and outputs conform to expected formats and ranges.

The project also required efficient data scraping and processing to collect prayer times for the entire year across all locations. I optimized the scraping process to be respectful of the source website while ensuring complete data collection.