pray-calc/.wiki/Asr-Calculation.md
Aric Camarata c02f197ece v2.0.0 — TypeScript rewrite, dual ESM/CJS, 14 methods + PCD dynamic algorithm
Complete rewrite from plain JavaScript to TypeScript with dual CJS/ESM output
via tsup. Removes all legacy .js source files and the old CommonJS-only index.

Key changes:
- Full TypeScript source in src/ with strict mode and declaration maps
- tsup build: dist/index.cjs + dist/index.mjs + dual .d.ts / .d.mts types
- 14 traditional fixed-angle methods (UOIF through MUIS) + MSC seasonal method
- PCD dynamic algorithm: MSC seasonal base + Earth-Sun distance correction +
  ecliptic geometry + atmospheric refraction + observer elevation
- getTimesAll() batches all 14x2 zenith angles into a single SPA call
- getMscFajr() / getMscIsha() expose MSC seasonal reference directly
- getAngles() returns the PCD-computed fajrAngle and ishaAngle
- High-latitude bounds: angles clipped to [10, 20] above 55N
- 106 tests across ESM and CJS (test.mjs + test-cjs.cjs)
- CI matrix: Node 20/22/24, typecheck, pack-check
- Wiki: 12 reference pages + 6-page research section with global accuracy study,
  home-territory comparison, observational evidence, and field observation matrix
- Moon functions removed (migrated to moon-sighting package)
- pnpm-only, Node >=20, sideEffects: false
2026-02-25 18:11:20 -05:00

83 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Asr Calculation
## The Rule
Asr is the afternoon prayer. Its start time is defined by shadow length, not by
a solar depression angle.
The standard definition: Asr begins when an object's shadow equals its height
**plus** the length of its shadow at solar noon.
For the Shafi'i, Maliki, and Hanbali schools of law (the majority), the shadow
multiplier is **1**. For the Hanafi school, the multiplier is **2**.
In practice, the difference is typically 3060 minutes, with Hanafi Asr being later.
## The Math
Let:
- φ = observer latitude in radians
- δ = solar declination in radians at local noon
- s = shadow factor (1 for Shafi'i, 2 for Hanafi)
The Sun's altitude when the shadow multiplier condition is met:
```
A = arccot(s + tan(|φ - δ|))
= arctan(1 / (s + tan(|φ - δ|)))
```
This altitude corresponds to a specific hour angle H:
```
cos(H) = (sin(A) - sin(φ)sin(δ)) / (cos(φ)cos(δ))
```
Asr time in local fractional hours:
```
asrTime = solarNoon + H / 15 (H in degrees, since 15° = 1 hour)
```
If `cos(H) < -1` or `cos(H) > 1`, the Sun never reaches the required altitude,
and `getAsr` returns `NaN`. This can happen at extreme latitudes when latitude
and declination are far apart.
## Implementation
`getAsr` is a pure math function. It requires:
1. `solarNoon` — fractional hours (from the SPA output)
2. `latitude` — decimal degrees
3. `declination` — solar declination in degrees (from `solarEphemeris`)
4. `hanafi` — boolean (default `false`)
```typescript
import { getAsr } from 'pray-calc';
const asr = getAsr(
12.15, // solar noon at ~12:09 local time
40.7128, // New York latitude
23.44, // solar declination at summer solstice
false, // Shafi'i
);
```
## Why Not Use the SPA for Asr?
Some prayer time libraries solve for Asr by running the SPA with the altitude A
as the zenith input. This requires an extra SPA call or a second zenith slot in
the batch call.
pray-calc computes Asr analytically using the Meeus declination (`solarEphemeris`)
rather than the SPA's internal declination. This avoids a second SPA call, removes
any dependency on internal SPA state, and is accurate to well within a minute
for any realistic use case.
The SPA uses a more rigorous ephemeris for declination (accurate to ~0.0003°
vs. Meeus at ~0.01°). For Asr, the difference in δ of 0.01° translates to less
than 5 seconds of timing error — completely negligible.
---
*[Back to Home](Home) | [API Reference](API-Reference) | [Architecture](Architecture)*