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.