Skip to content

2026.08.19

Choose a tag to compare

@rizukirr rizukirr released this 19 Aug 07:01
· 43 commits to main since this release
18daad2

Headers in this release

Header Version Changed since 2026.08.18
prayertimes.h v0.2.0 Yes
hijri.h v0.1.0 No
timezone.h v0.1.0 No

The tag is a calendar date and the headers carry their own semantic versions, so these numbers are not meant to match. Pin a download to the tag. Reason about compatibility from the header version.

prayertimes.h goes from v0.1.1 to v0.2.0. Both changes below are breaking, and both change the layout of struct PrayerTimes, so anything binding this header across the ABI must be rebuilt rather than dropped in.

Breaking: struct PrayerTimes carries the five prescribed prayers only

sunrise and dhuha are removed, along with the DHUHA_ALTITUDE constant.

struct PrayerTimes {
  double fajr;
  double dhuhr;
  double asr;
  double maghrib;
  double isha;
};

Neither removed field is a prescribed prayer. Sunrise is the end of the fajr window. Dhuha is a voluntary prayer and it is carried only by Indonesian timetables, not by MWL, ISNA or Umm al-Qura.

The evidence that these were the weakest part of the surface was already in the repository. Every dhuha fixture came from a single source. tests/test_prayertimes_oracle.c asserted neither field, because the oracle covers maghrib against hijri_find_sunset and nothing else. DHUHA_ALTITUDE documented itself as 4 degrees 30 minutes on the line above while defining 4.3, a gap of about 0.8 minutes at Indonesian latitudes, which is under the 2 minute tolerance, so no test could tell which value was intended.

Both quantities are still computed internally. Maghrib is sunset, and every high-latitude substitution measures the night between sunset and sunrise.

Breaking: the high-latitude rule is a property of the calculation method

MethodParams gains high_lat_method and high_lat_ref, and HighLatMethod gains HIGHLAT_NEAREST_LATITUDE. The enum already existed in v0.1.1 but nothing read it, so the angle-based rule was hardcoded and applied to all 22 methods alike. Kemenag silently received a rule Kemenag never published.

Only two of the researched authorities publish a position. MWL carries HIGHLAT_ANGLE_BASED with a reference latitude of 45, which is what its own Fiqh Council decree names. Moonsighting Committee carries HIGHLAT_ONE_SEVENTH anchored at 60, which is what its published page states. The rest carry no reference latitude, because attributing a ruling to an authority that never issued one is the failure mode this change exists to avoid.

The reference latitude is consulted only inside the polar circle, where there is no sunrise or sunset and every angle-based rule is undefined by construction.

NaN days at latitude 68 north, longitude 0, over 2025:

method                  high_lat_ref   fajr   maghrib   isha
Muslim World League               45      0         0      0
Moonsighting Committee            60      0         0      0
ISNA                               0     52        76     52
Umm al-Qura, Makkah                0     52        76     76

Before this change every one of those rows read like the ISNA row, including MWL. The fajr and isha fallback was itself NaN above 66 degrees, because it measured a night whose endpoints did not exist.

A note on what this release does not claim: 20 of the 22 methods still return NaN inside the polar circle. That is deliberate and it is tracked in #51.

A halt condition, and how it was resolved

Assigning MWL the decree's proportional rule for the case where a night does exist broke three published-table checks, all London.

London 2026-06-15  isha   computed 23:22   published 23:25    3 min
London 2026-07-15  fajr   computed 02:55   published 02:40   15 min
London 2026-07-15  isha   computed 23:08   published 23:25   17 min

The decree and the timetables published under the MWL name are two different things, and this library validates against the timetables. It was resolved by narrowing the implementation, not by widening the 2 minute tolerance that exposed it. The decree is now used only inside the polar circle, where the published tables have nothing to say.

Test counts

The published-table suite reports 745 checks, down from 932. 702 of those compare a computed time against a published table at a uniform 2 minute tolerance, with a residual distribution of 369 at 0 minutes, 326 at 1 and 7 at 2.

The fall is the sunrise and dhuha columns of the same tables. It is lost coverage of two fields the library no longer returns, not lost coverage of the five it does.

Bindings

The Rust and Dart bindings are updated for both changes and pin this ABI in their own probe tests.