# `Calendrical.Persian`

The present Iranian calendar was legally adopted on 31
March 1925, under the early Pahlavi dynasty. The law
said that the first day of the year should be the
first day of spring in "the true solar year", "as it
has been" ever so. It also fixes the number of days
in each month, which previously varied by year with
the sidereal zodiac.

It revived the ancient Persian names, which are still
used. It specifies the origin of the calendar to be
the Hegira of Muhammad from Mecca to Medina in 622 CE).

### Supported date range

This calendar is observational: each year begins at the vernal
equinox observed in Tehran, computed by `Astro.equinox/2`, which
is accurate only for Gregorian years 1000 to 3000. Date
conversions therefore support Gregorian years 1001 to 3000
(approximately Persian years 380 to 2378). Dates outside that
range raise `Calendrical.UnsupportedDateRangeError`.

# `calendar_base`

Identifies whether this calendar is month
or week based.

# `calendar_year`

```elixir
@spec calendar_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendar.year()
```

Returns the calendar year as displayed
on rendered calendars.

# `cldr_calendar_type`

Defines the CLDR calendar type for this calendar.

This type is used in support of `Calendrical.
localize/3`.

# `cyclic_year`

```elixir
@spec cyclic_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendar.year()
```

Returns the cyclic year as displayed
on rendered calendars.

# `date_from_iso_days`

```elixir
@spec date_from_iso_days(integer()) ::
  {Calendar.year(), Calendar.month(), Calendar.day()}
```

Returns a `{year, month, day}` tuple representing the Persian
calendar date for the given count of ISO days.

### Arguments

* `iso_days` is an integer count of days since the proleptic
  ISO epoch.

### Returns

* A three-tuple `{year, month, day}` in the Persian calendar.

* Raises `Calendrical.UnsupportedDateRangeError` if `iso_days`
  falls outside the supported range described in the module
  documentation.

### Examples

    iex> Calendrical.Persian.date_from_iso_days(739_335)
    {1403, 1, 6}

# `date_to_iso_days`

```elixir
@spec date_to_iso_days(Calendar.year(), Calendar.month(), Calendar.day()) :: integer()
```

Returns the number of days since the ISO calendar epoch for a given
Persian `year`, `month`, and `day`.

### Arguments

* `year` is any Persian year as an integer.

* `month` is a Persian month in the range `1..12`.

* `day` is a Persian day-of-month in the range `1..31`.

### Returns

* An integer count of days since the proleptic ISO epoch.

* Raises `Calendrical.UnsupportedDateRangeError` if the date falls
  outside the supported range described in the module
  documentation.

### Examples

    iex> Calendrical.Persian.date_to_iso_days(1404, 1, 1)
    739696

# `day_of_era`

```elixir
@spec day_of_era(Calendar.year(), Calendar.month(), Calendar.day()) ::
  {day :: Calendar.day(), era :: Calendar.era()}
```

Calculates the day and era from the given
`year`, `month`, and `day`.

By default we consider on two eras: before the epoch
and on-or-after the epoch.

# `day_of_year`

```elixir
@spec day_of_year(Calendar.year(), Calendar.month(), Calendar.day()) :: Calendar.day()
```

Calculates the day of the year from the given
`year`, `month`, and `day`.

# `days_in_month`

```elixir
@spec days_in_month(Calendar.month()) ::
  Calendar.month()
  | {:ambiguous, Range.t() | [pos_integer()]}
  | {:error, :undefined}
```

Returns how many days there are in the given month.

Must be implemented in derived calendars because
we cannot know what the calendar format is.

# `days_in_month`

```elixir
@spec days_in_month(Calendar.year(), Calendar.month()) :: Calendar.month()
```

Returns how many days there are in the given year
and month.

# `days_in_week`

Returns the number days in a a week.

# `days_in_year`

Returns the number days in a given year.

The year is the number of years since the
epoch.

# `epoch`

# `epoch_day_of_week`

# `extended_year`

```elixir
@spec extended_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendar.year()
```

Returns the extended year as displayed
on rendered calendars.

# `first_day_of_week`

# `iso_week_of_year`

```elixir
@spec iso_week_of_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  {:error, :not_defined}
```

Calculates the ISO week of the year from the
given `year`, `month`, and `day`.

By default this function always returns
`{:error, :not_defined}`.

# `last_day_of_week`

# `leap_year?`

```elixir
@spec leap_year?(Calendar.year()) :: boolean()
```

Returns whether the given Persian year is a leap year.

Since this calendar is observational we calculate the start of
successive years and then calculate the difference in days to
determine whether it is a leap year.

### Arguments

* `year` is any Persian year as an integer.

### Returns

* `true` if the year contains 366 days; otherwise `false`.

### Examples

    iex> Calendrical.Persian.leap_year?(1403)
    true

    iex> Calendrical.Persian.leap_year?(1404)
    false

# `month`

Returns a `t:Date.Range.t/0` representing
a given month of a year.

# `month_of_year`

```elixir
@spec month_of_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendar.month() | {Calendar.month(), Calendrical.leap_month?()}
```

Returns the month of the year from the given
`year`, `month`, and `day`.

# `months_in_leap_year`

Returns the number of months in a leap year.

# `months_in_ordinary_year`

Returns the number of months in a normal year.

# `months_in_year`

Returns the number of months in a year, without a year.

Returns an integer when every year has the same number of
months, or `{:ambiguous, first..last}` for lunisolar calendars
whose year length varies (e.g. the Hebrew calendar's 12 or 13
months).

# `months_in_year`

Returns the number of months in a
given `year`.

# `naive_datetime_from_iso_days`

```elixir
@spec naive_datetime_from_iso_days(Calendar.iso_days()) ::
  {Calendar.year(), Calendar.month(), Calendar.day(), Calendar.hour(),
   Calendar.minute(), Calendar.second(), Calendar.microsecond()}
```

Converts the `t:Calendar.iso_days` format to the
datetime format specified by this calendar.

# `naive_datetime_to_iso_days`

```elixir
@spec naive_datetime_to_iso_days(
  Calendar.year(),
  Calendar.month(),
  Calendar.day(),
  Calendar.hour(),
  Calendar.minute(),
  Calendar.second(),
  Calendar.microsecond()
) :: Calendar.iso_days()
```

Returns the `t:Calendar.iso_days` format of
the specified date.

# `new_year_gregorian`

```elixir
@spec new_year_gregorian(Calendar.year()) ::
  {:ok, Date.t()} | {:error, :year_out_of_range}
```

Returns the Gregorian `Date` of the Persian new year that falls in
the given Gregorian `year`.

The Persian new year (Nowruz) is the day on which the March equinox
occurs in Tehran local time.

### Arguments

* `year` is the Gregorian year in which the desired Persian new
  year falls.

### Returns

* `{:ok, date}` where `date` is a `t:Date.t/0` in `Calendar.ISO`.

* `{:error, :year_out_of_range}` if `year` is outside the
  Gregorian years 1000 to 3000 for which the equinox can be
  computed.

### Examples

    iex> Calendrical.Persian.new_year_gregorian(2025)
    {:ok, ~D[2025-03-21]}

    iex> Calendrical.Persian.new_year_gregorian(900)
    {:error, :year_out_of_range}

# `new_year_on_or_before`

```elixir
@spec new_year_on_or_before(integer()) :: integer()
```

Returns the count of ISO days of the most recent Persian new year on
or before `iso_days`.

### Arguments

* `iso_days` is an integer count of days since the proleptic
  ISO epoch.

### Returns

* An integer count of days since the proleptic ISO epoch
  corresponding to the most recent Persian new year on or before
  the supplied date.

* Raises `Calendrical.UnsupportedDateRangeError` if the date falls
  outside the supported Gregorian years 1001 to 3000.

### Examples

    iex> Calendrical.Persian.new_year_on_or_before(739_400)
    739330

# `periods_in_year`

Returns the number of periods in a given
`year`. A period corresponds to a month
in month-based calendars and a week in
week-based calendars.

# `plus`

Adds an `increment` number of `date_part`s
to a `year-month-day`.

`date_part` can be `:years`, `:months`, `:weeks` or `:days`.

# `quarter`

Returns a `t:Date.Range.t/0` representing
a given quarter of a year.

# `quarter_of_year`

```elixir
@spec quarter_of_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendrical.quarter()
```

Returns the quarter of the year from the given
`year`, `month`, and `day`.

# `related_gregorian_year`

```elixir
@spec related_gregorian_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  Calendar.year()
```

Returns the related Gregorian year as displayed
on rendered calendars.

Per TR35 this is the Gregorian year in which this
calendar's `year` begins, so it is constant for every
date of the calendar year.

# `valid_date?`

Determines if the `date` given is valid according to
this calendar.

# `week`

Returns a `t:Date.Range.t/0` representing
a given week of a year.

# `week_of_month`

```elixir
@spec week_of_month(Calendar.year(), Calendar.month(), Calendar.day()) ::
  {pos_integer(), pos_integer()} | {:error, :not_defined}
```

Calculates the week of the year from the given
`year`, `month`, and `day`.

By default this function always returns
`{:error, :not_defined}`.

# `week_of_year`

```elixir
@spec week_of_year(Calendar.year(), Calendar.month(), Calendar.day()) ::
  {:error, :not_defined}
```

Calculates the week of the year from the given
`year`, `month`, and `day`.

By default this function always returns
`{:error, :not_defined}`.

# `weeks_in_year`

Returns the number of weeks in a
given `year`.

# `year`

Returns a `t:Date.Range.t/0` representing
a given year.

# `year_end_gregorian`

```elixir
@spec year_end_gregorian(Calendar.year()) ::
  {:ok, Date.t()} | {:error, :year_out_of_range}
```

Returns the Gregorian `Date` of the last day of the Persian year
that begins in the given Gregorian `year`.

### Arguments

* `year` is the Gregorian year in which the Persian year starts.

### Returns

* `{:ok, date}` where `date` is a `t:Date.t/0` in `Calendar.ISO`,
  one day before the next Persian new year.

* `{:error, :year_out_of_range}` if `year + 1` is outside the
  Gregorian years 1000 to 3000 for which the equinox can be
  computed.

### Examples

    iex> Calendrical.Persian.year_end_gregorian(2025)
    {:ok, ~D[2026-03-20]}

# `year_of_era`

```elixir
@spec year_of_era(Calendar.year()) :: {year :: Calendar.year(), era :: Calendar.era()}
```

Calculates the year and era from the given `year`.

# `year_of_era`

```elixir
@spec year_of_era(Calendar.year(), Calendar.month(), Calendar.day()) ::
  {year :: Calendar.year(), era :: Calendar.era()}
```

Calculates the year and era from the given `date`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
