| Copyright | (C) 2017 Jason Johnson |
|---|---|
| License | BSD-style (see the file LICENSE) |
| Maintainer | Jason Johnson <jason.johnson.081@gmail.com> |
| Stability | experimental |
| Portability | POSIX, Windows |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Data.HodaTime.Calendar.Persian
Contents
Description
This is the module for CalendarDate and CalendarDateTime in the Persian (Solar Hijri) calendar, the official calendar of Iran and Afghanistan. It is a solar calendar whose year begins at the
vernal equinox (Nowruz, around 20/21 March): the first six months (Farvardin through Shahrivar) have 31 days, the next five (Mehr through Bahman) have 30, and the final month (Esfand) has
29, or 30 in a leap year. Year 1 begins on 22.Mar.622 CE (proleptic Gregorian), the year of the Hijra; dates share the same absolute timeline as every other calendar.
Leap years: the astronomical calendar
This is the astronomical Solar Hijri calendar — the official civil calendar of Iran (equivalent to the .NET PersianCalendar from 4.6 onwards and NodaTime's PersianAstronomical). Rather than an
arithmetic cycle, a year is a leap year exactly when the astronomical rule places the following Nowruz 366 days later. Nowruz is the day on which the March equinox occurs if the equinox is before true
noon at the reference meridian (52.5°E, Iran Standard Time), otherwise the next day. The equinox and leap years are computed in Data.HodaTime.Calendar.Persian.Astronomical; the table is built lazily,
so programs that don't use the Persian calendar pay nothing for it.
Supported range and why it is capped at 1500
The calendar is vouched for over Persian years 1 .. 1500 (≈ 622 .. 2121 CE); calendarDate rejects years outside that range. This is a deliberately narrower window than NodaTime's
PersianAstronomical, which spans years 1 .. 9377 (≈ 622 .. 9999 CE). The difference is not an oversight but a consequence of how each library determines Nowruz:
- NodaTime embeds a fixed lookup table of leap-year bits that was generated once from the .NET 4.6 BCL
PersianCalendar. Every year up to 9377 therefore has a frozen, deterministic answer, even far-future years for which the "astronomical" leap flag is really just whatever value the BCL happened to precompute. - We instead compute each Nowruz on demand from first principles: the March equinox (Meeus, Astronomical Algorithms ch. 27/28), the equation of time (to reduce mean noon to apparent noon at the Iranian reference meridian), and ΔT — the difference between Terrestrial Time and Universal Time caused by the slow, irregular change in the Earth's rotation.
ΔT is the limiting factor. It can only be measured for the past and extrapolated for the future, and the standard Espenak–Meeus polynomials are only trustworthy through roughly 2150 CE; beyond that the extrapolation error grows without bound and can shift the computed equinox — and hence a borderline Nowruz — by a whole day. Capping at Persian year 1500 (≈ 2121 CE) keeps every result inside the range where the astronomy is genuinely well constrained, so every leap year we report is defensible rather than speculative. Over this range our results match NodaTime exactly, including all of the documented years where the astronomical calendar diverges from the arithmetic one (e.g. Persian 1404 = 21.Mar.2025, where the arithmetic calendar gives the 20th).
If you need dates past 2121 CE, prefer the arithmetic (Birashk) Solar Hijri calendar, whose leap rule is exact by definition and carries no astronomical uncertainty.
Synopsis
- calendarDate :: DayOfMonth -> Month Persian -> Year -> Maybe (CalendarDate Persian)
- fromNthDay :: DayNth -> DayOfWeek Persian -> Month Persian -> Year -> Maybe (CalendarDate Persian)
- fromWeekDate :: WeekNumber -> DayOfWeek Persian -> Year -> Maybe (CalendarDate Persian)
- data family Month cal
- data family DayOfWeek cal
- data Persian
Constructors
calendarDate :: DayOfMonth -> Month Persian -> Year -> Maybe (CalendarDate Persian) Source #
fromNthDay :: DayNth -> DayOfWeek Persian -> Month Persian -> Year -> Maybe (CalendarDate Persian) Source #
fromWeekDate :: WeekNumber -> DayOfWeek Persian -> Year -> Maybe (CalendarDate Persian) Source #
Smart constructor for a Persian calendar date given as a week date. Note that this method assumes weeks start on Saturday (as in the Persian calendar) and the first week of the year is the
one which has at least one day in the new year.
Types
data family Month cal Source #
Instances
data family DayOfWeek cal Source #