Skip to content

Latest commit

 

History

History
558 lines (421 loc) · 14.1 KB

File metadata and controls

558 lines (421 loc) · 14.1 KB

PrayTimes Library - Technical Documentation

مكتبة أوقات الصلاة - التوثيق التقني

Table of Contents

  1. Architecture Overview
  2. Mathematical Algorithms
  3. Input Validation Strategy
  4. Error Handling
  5. Calculation Methods Details
  6. Performance Considerations
  7. Testing Strategy

Architecture Overview

Design Principles

The Prayer Times Library is designed with the following principles:

  1. Modularity: Core calculations separated from validation and error handling
  2. Robustness: Comprehensive input validation prevents incorrect calculations
  3. Type Safety: Extensive use of enums for method selection and error codes
  4. Clarity: Bilingual comments and documentation for international audience
  5. Efficiency: Minimal dependencies, optimized calculations

Module Structure

src/libpt.c and include/libpt.h
├── Public API
│   ├── get_prayer_times()        - Main calculation function
│   ├── decimal_to_time()         - Time format conversion
│   └── get_error_message()       - Error message retrieval
├── Validation Layer
│   ├── validate_date()           - Date validation
│   └── validate_coordinates()    - Geographic validation
├── Calculation Engine
│   ├── sun_position()            - Solar position computation
│   ├── compute_time()            - Prayer time calculation
│   ├── compute_asr()             - Asr-specific calculation
│   ├── equation_of_time()        - Equation of time
│   └── sun_declination()         - Solar declination
└── Utility Functions
    ├── deg2rad() / rad2deg()     - Angle conversions
    ├── fix_angle()               - Angle normalization
    ├── fix_hour()                - Time normalization
    └── get_julian_date()         - Julian date calculation

Mathematical Algorithms

1. Julian Date Calculation

Purpose: Convert calendar date to astronomical Julian Date number

Implementation: Uses the standard astronomical conversion formula:

// Input: Gregorian calendar date
// Process:
//   1. Adjust year/month for leap year calculations
//   2. Calculate day number from reference epoch (4713 BC)
//   3. Return fractional day number

// Formula components:
//   a = floor(year / 100)                    // Century
//   b = 2 - a + floor(a / 4)                // Gregorian adjustment
//   JD = floor(365.25 * (year + 4716)) +    // Days in year
//        floor(30.6001 * (month + 1)) +      // Days in month
//        day + b - 1524.5                     // Day plus epoch correction

Accuracy: Accurate for dates 1900-2100 (outside range, accuracy degraded)

2. Solar Position Calculation

Purpose: Determine the sun's position for a given Julian Date

Process:

1. Calculate days from epoch (d = JD - 2451545.0)
   - Reference epoch: J2000.0 (Jan 1, 2000)

2. Mean anomaly: g = 357.529° + 0.98560028° * d
   - Describes sun's position in its orbit

3. Mean longitude: q = 280.459° + 0.98564736° * d
   - Sun's ecliptic longitude

4. Apparent longitude: L = q + 1.915°*sin(g) + 0.020°*sin(2g)
   - Adjusts for orbital eccentricity variations

5. Obliquity of ecliptic: ε = 23.439° - 0.00000036° * d
   - Earth's axial tilt

6. Solar declination: δ = arcsin(sin(ε) * sin(L))
   - Sun's angular position relative to celestial equator

7. Right ascension: RA = atan2(cos(ε)*sin(L), cos(L))
   - Sun's angular position along celestial equator

8. Equation of time: EoT = q/15 - RA/15 (in hours)
   - Correction for elliptical orbit and axial tilt

Accuracy: ±0.0006° (~2 minutes of arc) over 1900-2100

3. Prayer Time Calculation

General Formula:

Prayer Time = Dhuhr ± arccos(sin(angle) / (cos(decl) * cos(lat)))

Where:
  angle   = Solar angle for specific prayer (e.g., 18° for Fajr)
  decl    = Solar declination
  lat     = Geographic latitude
  Dhuhr   = Solar noon time

Specific Prayer Times:

Prayer Angle Formula Notes
Fajr -18° (or -15°, -19.5°) Dhuhr - arccos(...) Method-specific angles
Sunrise -0.833° Dhuhr - arccos(...) Solar disk 0.833° below horizon
Dhuhr 12 - EoT - lng/15 + tz Solar noon
Asr 1 or 2 Depends on juristic method Special calculation for shadow
Sunset -0.833° Dhuhr + arccos(...) Mirror of sunrise
Maghrib +0.05 Sunset + 0.05 hours ~3 minutes after sunset
Isha -17° (or -15°, -17.5°) Dhuhr + arccos(...) Method-specific angles

4. Asr Calculation (Special Case)

Standard Method (Shafi'i, Maliki, Hanbali):

Shadow length = 1 * object_height
angle = -arctan(1 / (1 + tan(|lat - decl|)))

Hanafi Method:

Shadow length = 2 * object_height
angle = -arctan(1 / (2 + tan(|lat - decl|)))

The negative angle indicates below the horizon mathematically.

5. Time Normalization

Angle Normalization (0° - 360°):

// Ensures angle is in [0, 360)
angle = angle - 360.0 * floor(angle / 360.0)
if (angle < 0) angle += 360.0

Hour Normalization (0:00 - 23:59):

// Ensures time is in [0, 24)
time = time - 24.0 * floor(time / 24.0)
if (time < 0) time += 24.0

Input Validation Strategy

Three-Layer Validation

Layer 1: Type Validation

- Enums prevent invalid calculation methods
- Array size via TIMES_COUNT constant
- Prevents memory corruption

Layer 2: Range Validation

Date validation:
  Year:   1900-2100 (astronomical algorithm precision)
  Month:  1-12
  Day:    1-31 (with month-specific max, leap year handling)

Coordinate validation:
  Latitude:   -90.0 to 90.0 degrees
  Longitude:  -180.0 to 180.0 degrees
  Timezone:   -12.0 to 14.0 hours

Special cases:
  Polar regions (lat > 66°) - warning only
  NULL output pointer - error

Layer 3: Semantic Validation

- Leap year calculation for February
- Geographic coordinate realism
- Timezone range (UTC-12 to UTC+14)

Validation Error Codes

PT_ERR_INVALID_YEAR        // Year outside 1900-2100
PT_ERR_INVALID_MONTH       // Month outside 1-12
PT_ERR_INVALID_DAY         // Day invalid for month (including leap years)
PT_ERR_INVALID_LATITUDE    // Latitude outside -90 to 90
PT_ERR_INVALID_LONGITUDE   // Longitude outside -180 to 180
PT_ERR_INVALID_TIMEZONE    // Timezone outside -12 to 14
PT_ERR_NULL_OUTPUT         // Output array pointer is NULL
PT_ERR_POLAR_REGION        // High latitude (lat > 66°)

Error Handling

Error Propagation Strategy

// Early return on validation failure
if (validation_fails) return ERROR_CODE;

// Prevents cascading errors
// Ensures function never processes invalid input

Bilingual Error Messages

// English messages: Technical terminology
get_error_message(error, ERR_LANG_ENGLISH)
// Returns: "Invalid year (must be between 1900-2100)"

// Arabic messages: Clear Islamic context
get_error_message(error, ERR_LANG_ARABIC)
// Returns: "سنة غير صحيحة (يجب أن تكون بين 1900-2100)"

Calculation Methods Details

1. Umm Al-Qura University (جامعة أم القرى)

Usage: Primary method in Saudi Arabia

Angles:

  • Fajr: 18.5°
  • Isha: 90 minutes after Maghrib (not angular)

Notes:

  • Isha uses fixed offset instead of angle
  • Designed for geographical latitude 21.4° (Mecca)
  • May vary in other regions

2. Muslim World League (رابطة العالم الإسلامي)

Usage: International standard

Angles:

  • Fajr: 18°
  • Isha: 17°

Notes:

  • More balanced than region-specific methods
  • Works well globally
  • Most scientifically accepted

3. Islamic Society of North America (جمعية إسلامية)

Usage: North America

Angles:

  • Fajr: 15°
  • Isha: 15°

Notes:

  • Adjusted for higher northern latitudes
  • Accounts for extended twilight in summer

4. Egyptian General Authority (الهيئة المصرية)

Usage: Egypt and surrounding regions

Angles:

  • Fajr: 19.5°
  • Isha: 17.5°

Notes:

  • Officially used in Egypt
  • Accounts for Mediterranean climate

5. Karachi Islamic University (جامعة كراتشي)

Usage: Pakistan and South Asia

Angles:

  • Fajr: 18°
  • Isha: 18°

Notes:

  • Designed for South Asian geography
  • Used in Pakistan and neighboring regions

Performance Considerations

Computational Complexity

Time Complexity:
  O(1) - All calculations are constant time
  No loops or recursive calls
  Fixed number of mathematical operations

Space Complexity:
  O(1) - All parameters pass by value
  Output array allocated by caller
  No dynamic memory allocation

Optimization Techniques

  1. Precomputed Constants:

    • PI: Full precision constant
    • Method-specific angles: Switch statement, not lookup table
  2. Efficient Math Functions:

    • Uses optimized libc sin(), cos(), atan2()
    • Minimal trigonometric calculations
    • Avoids expensive operations like sqrt
  3. Early Returns:

    • Validation errors return immediately
    • Prevents unnecessary computations

Benchmark Results

Single prayer time calculation: ~1 microsecond
All 7 prayer times: ~7 microseconds
Test suite (38 tests): ~50 milliseconds

Testing Strategy

Test Categories

1. Validation Tests (10 tests)

Purpose: Ensure input validation works correctly
Coverage:
  - Invalid year (too old: 1800)
  - Invalid year (too new: 2150)
  - Invalid month (0)
  - Invalid month (13)
  - Invalid day (32)
  - Invalid latitude (95)
  - Invalid latitude (-95)
  - Invalid longitude (185)
  - Invalid timezone (20)
  - NULL output pointer

2. Calculation Tests (8 tests)

Purpose: Verify prayer time calculations
Coverage:
  - Algiers, Algeria (MWL method)
  - Time range verification
  - Time ordering (Fajr < Sunrise < Dhuhr < Asr < Sunset < Maghrib < Isha)
  - Sunrise/sunset symmetry
  - Maghrib proximity to sunset

3. Method Comparison Tests (3 tests)

Purpose: Verify different methods produce different results
Coverage:
  - Umm Al-Qura vs. MWL vs. ISNA
  - Method parameter differences
  - Consistency across runs

4. Juristic Method Tests (2 tests)

Purpose: Verify juristic method differences
Coverage:
  - Standard method (Shafi'i)
  - Hanafi method (later Asr time expected)
  - Asr shadow calculation

5. Utility Function Tests (4 tests)

Purpose: Verify helper functions
Coverage:
  - decimal_to_time(5.5) -> 5:30
  - decimal_to_time(23.75) -> 23:45
  - decimal_to_time(14.25) -> 14:15
  - decimal_to_time(0.1) -> 0:06

6. Global Coverage Tests (4 tests)

Purpose: Test in diverse geographic locations
Coverage:
  - London (51.5°N) - high latitude
  - Cairo (30.04°N) - medium latitude
  - Jakarta (-6.2°S) - equatorial
  - Sydney (-33.9°S) - southern hemisphere

7. Error Message Tests (6 tests)

Purpose: Verify error messages in both languages
Coverage:
  - English messages (all error types)
  - Arabic messages (all error types)
  - Message completeness and clarity

Test Execution

# Build and run all tests
make run-test

# Output includes:
- Individual test results (✓ or ✗)
- Test statistics (total, passed, failed)
- Pass rate percentage
- Detailed error information if failures occur

Test Results Interpretation

✓ PASS  - Test completed successfully
✗ FAIL  - Test failed with error details

Summary:
  Total Tests:   38
  Passed:        38 ✓
  Failed:        0 ✗
  Pass Rate:     100.0%
  Status:        🎉 All tests passed!

Accuracy and Limitations

Accuracy Levels

  • Very High Accuracy: ±1 minute for latitudes -60° to +60°, years 1900-2100
  • Good Accuracy: ±2-3 minutes for latitudes -66° to +66°, years 1900-2100
  • Limited Accuracy: ±5+ minutes for polar regions, before 1900 or after 2100

Known Limitations

  1. Polar Regions (lat > 66°):

    • Solar angles may exceed valid range
    • Days with no sunrise/sunset (polar night/day)
    • Results become unreliable
  2. Year Range (1900-2100):

    • Optimal precision within this range
    • Extrapolation beyond range decreases accuracy
    • Astronomical constants may need updates for very distant dates
  3. Timezone Handling:

    • Supports standard timezone offsets (-12 to +14)
    • Does not handle historical timezone changes
    • Does not account for daylight saving time (user responsibility)
  4. Geographic Precision:

    • Uses spherical Earth model
    • Ellipsoid corrections not applied
    • Suitable for most practical applications

Building and Compilation

Compiler Flags Explanation

-Wall       # Enable all common warnings
-Wextra     # Enable extra warnings
-fPIC       # Generate position-independent code (for shared library)
-lm         # Link math library (for trigonometric functions)
-g          # Include debug symbols (debug builds only)
-O0         # No optimization (debug builds only)

Output Files

bin/libpt.so              # Shared library
bin/test_libpt            # Executable test suite
bin/prayer_times_demo     # Example program

Integration Guide

Linking Against libpt

# Compile your program with library
gcc -o myprogram myprogram.c -o libpt.so -lm

# Or compile directly with source
gcc -o myprogram myprogram.c src/libpt.c -lm

# Run with shared library in LD_LIBRARY_PATH
export LD_LIBRARY_PATH=./bin:$LD_LIBRARY_PATH
./myprogram

Contributing

Code Style Guidelines

  1. Comments:

    • Use bilingual comments (Arabic and English)
    • Document algorithm, not obvious code
    • Include @brief tags for functions
  2. Variable Naming:

    • Clear, descriptive names
    • Use underscores for multi-word names
    • Avoid single-letter variables (except loop counters)
  3. Testing:

    • Add tests for new features
    • Ensure all tests pass before committing
    • Document test purpose and coverage

Document Version: 1.0 Last Updated: 2026-06-16 Audience: Developers, Contributors, Advanced Users