fix: derive Jalali conversions from the astronomical calendar model - #69
Closed
majiidd wants to merge 11 commits into
Closed
fix: derive Jalali conversions from the astronomical calendar model#69majiidd wants to merge 11 commits into
majiidd wants to merge 11 commits into
Conversation
…y data Add table-driven tests based on the leap-year table (Kabise Shamsi 1206-1498) published by the Calendar Center, Institute of Geophysics, University of Tehran. Covers Norouz dates in both conversion directions, is_leap and Esfand length for all 293 years, year-boundary conversions, and a day-by-day round trip across the entire official range. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
to_jalali, to_gregorian, and toordinal now share a single _days_before_year helper that is exactly consistent with is_leap (33-year cycle plus the non-leap correction years), instead of two independent arithmetic paths. This fixes: - to_jalali producing off-by-one dates for ~185k days and raising ValueError for 237 days in Gregorian 622-1600, because the old epoch-shift branch did not start on a 33-year cycle boundary - one unrepresentable Gregorian day (ValueError) and one double-mapped Jalali date per non-leap correction year (first: 2124-03-20 and 1503-12-30), where conversions ignored the corrections is_leap applies Verified: exhaustive scan of all 3,424,879 supported days round-trips with no exceptions and one-day monotonic steps; conversions now match the astronomical Persian calendar (Calendrical Calculations at 52.5E, roozbehp/persiancalendar) for every year 1178-3000 and remain identical to the official University of Tehran table for 1206-1498. Behavior is unchanged for Jalali years 980-1501. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Correct the epoch to Friday 22 March 622 CE (proleptic Gregorian) and derive leap years 1..1177 from the astronomical Persian calendar (Calendrical Calculations at the 52.5E meridian), keeping the consensus 33-year values for five borderline flip pairs so conversions are unchanged for every day on or after Gregorian 1568-03-21. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #69 +/- ##
==========================================
- Coverage 98.47% 98.19% -0.29%
==========================================
Files 5 5
Lines 1117 1220 +103
==========================================
+ Hits 1100 1198 +98
- Misses 17 22 +5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
added 8 commits
August 5, 2026 03:27
Avoid rebuilding dates during comparisons and format only the strftime directives in use; drop restating comments and clarify the calendar-model notes.
Cover underflow, leap-day replace, combine fold/tzinfo, and to_jalali argument forms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Reported:
persiantoolsconverts Gregorian 623-01-01 to Jalali 1-10-11 while astronomical converters such as time.ir give 1-10-10, and the kabiseh (leap year) logic was internally inconsistent.Investigation confirmed two real defects on master:
year <= 1600epoch branch into_jalaliwas arithmetically wrong — 185,426 days in 622–2130 disagreed with the model the rest of the code implements (e.g. 623-03-21 → 2-1-1, skipping Esfand 30 of leap year 1), and 237 days raisedValueError.is_leap/days_in_monthused the ICU4XNON_LEAP_CORRECTION_SETwhileto_jalali/to_gregorianused plain 33-year arithmetic — so 2124-03-20 was unrepresentable (ValueError) and 1503-12-30 / 1504-01-01 both mapped to 2125-03-21.What changed
All conversions, ordinals, and leap checks now derive from a single internal model (
_days_before_year+is_leap):Behavior changes
ValueErrordays fixed)ValueErroris_leap, years ≤ 1177is_leap(1): True → False)ValueError/collisions)toordinal()/fromordinal()Validation
is_leap.tests/test_official_kabise.py, all 293 years).make checkgreen; opt-in performance tests pass.Note: the jdf.scr.ir algorithm itself also yields 1-10-11 for 623-01-01 — the reported time.ir value comes from the astronomical model, which this PR adopts for ancient years on the strength of the documented epoch (Persian Wikipedia: جمعه ۱ فروردین سال ۱ = ۲۲ مارس ۶۲۲) and the official authority's astronomical practice.
🤖 Generated with Claude Code