# `Calendrical.LunarJapanese`

Implementation of the Japanese lunisolar calendar.

In a normal Japanese lunisolar calendar, one year
is divided into 12 months, with one month corresponding
to the time between two full moons.

Since the cycle of the moon is not
an even number of days, a month in the lunar calendar
can vary between 29 and 30 days and a normal year can
have 353, 354, or 355 days.

We define the epoch to the first new moon in the first
year of the [Taika era](https://en.wikipedia.org/wiki/Taika_(era))
which is recorded as the first imperial era.

The epoch can be changed by setting the `:lunar_japanese_epoch`
configuration key in `config.exs`:

    # Alternative epoch starting from the reign of Emperor
    # Huangdi
    config :calendrical,
      lunar_japanese_epoch: ~D[0645-07-20]

## Two month numbering conventions

The Japanese lunisolar calendar (like the Chinese and Korean ones) has
**two distinct month numbering conventions**. Choosing the wrong one
silently produces dates that are off by one full lunar month after the
intercalary month in leap years. The conventions are:

* **Ordinal** — months counted monotonically 1..12 in ordinary years
  and 1..13 in leap years. The intercalary appears at whatever position
  the astronomical no-zhongqi rule places it; it is not separately
  labelled. This is the convention `Date.new/4` accepts, the `Date.t`
  struct stores, and `Date.convert/2` returns. It is what the standard
  `Calendar` behaviour callbacks expect.

* **Traditional** — months always numbered 1..12, with the intercalary
  expressed as `{month, :leap}` (read 閏N月 — "intercalary Nth month")
  where `month` is the *preceding* traditional month number. This is
  the convention used by primary chronicles and cultural references.
  `Calendrical.LunarJapanese.new/3` and the return value of
  `lunar_month_of_year/1` use this convention.

As an example, in lunar year 1210 (= AD 1854, 嘉永7 / Kaei 7) the
intercalary is the 8th ordinal month, equivalent to the traditional
notation `{7, :leap}` (閏7月):

    # Build a date using traditional notation:
    iex> {:ok, date} = Calendrical.LunarJapanese.new(1210, {7, :leap}, 1)
    iex> Date.convert(date, Calendar.ISO)
    {:ok, ~D[1854-08-24]}

    # The same day via Date.new/4 uses ordinal numbering (m8 = the leap):
    iex> {:ok, date} = Date.new(1210, 8, 1, Calendrical.LunarJapanese)
    iex> Date.convert(date, Calendar.ISO)
    {:ok, ~D[1854-08-24]}

    # The Date.t struct stores months in ordinal form:
    iex> {:ok, date} = Calendrical.LunarJapanese.new(1210, {7, :leap}, 1)
    iex> {date.month, Calendrical.LunarJapanese.lunar_month_of_year(date)}
    {8, {7, :leap}}

Converting between the two: if a year is a leap year, traditional
numbers below the leap-month position equal the ordinal numbers, and
traditional numbers at or above the leap-month position equal
ordinal-minus-one. `leap_month/1` returns the **ordinal** position of
the intercalary; `traditional_leap_month/1` returns the **traditional**
number that the intercalary repeats.

# `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(date :: Date.t()) :: Calendrical.Lunisolar.cycle()
```

Returns the year in the lunisolar sexigesimal 60-year
cycle.

Traditionally years are numbered only within the cycle
however in this implementation the year is an offset from
the epoch date. It can be converted to the current year in
the current cycle with this function.

The cycle year is commonly shown on lunisolar calendars and
it forms part of the traditional Chinese zodiac.

### Arguments

* `date` which is any `t:Calendar.date/0` in the `Calendrical.LunarJapanese`
  calendar, *or*

*`year` and `month` representing the calendar year and month.

### Returns

* the integer year within the sexigesimal cycle of 60 years.

### Examples

    iex> Calendrical.LunarJapanese.cyclic_year(~D[1380-04-01 Calendrical.LunarJapanese])
    60

    iex> Calendrical.LunarJapanese.cyclic_year(~D[1381-01-01 Calendrical.LunarJapanese])
    1

    iex> Calendrical.LunarJapanese.cyclic_year(~D[1200-01-02 Calendrical.LunarJapanese])
    60

    iex> Calendrical.LunarJapanese.cyclic_year(~D[1260-01-01 Calendrical.LunarJapanese])
    60

# `cyclic_year`

# `cyclic_year`

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

Returns the cyclic year as displayed
on rendered calendars.

# `date_to_iso_days`

# `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.

# `elapsed_years`

# `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`

# `gregorian_date_for_lunar`

Returns the Gregorian date for the given gregorian year
and lunar month and day.

### Arguments

* `gregorian_year` is any year in the Gregorian calendar.

* `lunar_month` is either a cardinal month number between 1 and 12 or
  for a leap month the 2-tuple in the format `{month, :leap}`.

* `day` is any day number valid for `year` and `lunar_month`.

### Returns

* A gregorian date `t:Date.t()`.

# `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_month`

```elixir
@spec leap_month(date_or_year :: Date.t() | Calendar.year()) :: Calendar.month() | nil
```

Returns the **ordinal** position (1..13) of the leap month for a year,
or `nil` if the year is not a leap year.

This is the position of the intercalary in the monotonic 1..13 ordinal
sequence used by `Date.t` structs and the standard `Calendar` callbacks.
See `traditional_leap_month/1` for the traditional notation (the
preceding-month number that the intercalary repeats).

### Arguments

* `date_or_year` is either an integer year number
  or a `t:Calendar.date/0` in the `Calendrical.LunarJapanese`
  calendar.

### Returns

* the ordinal position of the leap month (1..13), or

* `nil` if there is no leap month in the given year.

### Examples

    # Y1379 is a leap year; the intercalary is at ordinal m3
    # (= traditional {2, :leap})
    iex> Calendrical.LunarJapanese.leap_month(1379)
    3

    iex> Calendrical.LunarJapanese.leap_month(~D[1379-13-29 Calendrical.LunarJapanese])
    3

    iex> Calendrical.LunarJapanese.leap_month(1380)
    nil

# `leap_month?`

```elixir
@spec leap_month?(date :: Date.t()) :: boolean()
```

Returns a boolean indicating if the given year and month
is a leap month.

### Arguements

* `date` is any `t:Calendar.date/0` in the `Calendrical.LunarJapanese` calendar.

### Returns

* A booelan indicating if the given year and month is a leap
  month.

### Examples

    iex> Calendrical.LunarJapanese.leap_month?(~D[1379-01-01 Calendrical.LunarJapanese])
    false

    iex> Calendrical.LunarJapanese.leap_month?(~D[1379-03-29 Calendrical.LunarJapanese])
    true

# `leap_month?`

```elixir
@spec leap_month?(year :: Calendar.year(), month :: Calendar.month()) :: boolean()
```

Returns a boolean indicating if the given year and month
is a leap month.

### Arguements

* `year` is any year in the `Calendrical.LunarJapanese` calendar.

* `month` is any ordinal month number in the `Calendrical.LunarJapanese`
  calendar.

### Returns

* A booelan indicating if the given year and month is a leap
  month.

### Examples

    iex> Calendrical.LunarJapanese.leap_month?(1379, 1)
    false

    iex> Calendrical.LunarJapanese.leap_month?(1379, 3)
    true

# `leap_year?`

```elixir
@spec leap_year?(date_or_year :: Calendar.year() | Date.t()) :: boolean()
```

Returns a boolean indicating if the given year is a leap
year.

Leap years have 13 months. To determine if a year
is a leap year, calculate the number of new moons
between the 11th month in one year (i.e., the month
containing the Winter Solstice) and the 11th month
in the following year.

If there are 13 new moons from the start of the 11th
month in the first year to the start of the 11th
month in the second year, a leap month must be inserted.

In leap years, at least one month does not contain a
Principal Term. The first such month is the leap month.

The additional complexity is that a leap year is
calculated for the solar year, but the calendar
is managed in lunar years and months. Therefore when
a leap year is detected, the leap month could be in
the current lunar year or the next lunar year.

### Arguments

* `date_or_year` is either an integer year number
  or a `t:Calendar.date/0` in the `Calendrical.LunarJapanese`
  calendar.

### Returns

* A booelan indicating if the given year is a leap
  year.

### Examples

    iex> Calendrical.LunarJapanese.leap_year?(1379)
    true

    iex> Calendrical.LunarJapanese.leap_year?(1378)
    false

# `lunar_month_of_year`

```elixir
@spec lunar_month_of_year(date :: Date.t()) :: Calendrical.Lunisolar.lunar_month()
```

Returns the lunar month of the year for a given date or
year and month.

The lunar month number in the traditional lunisolar calendar is
between 1 and 12 with a leap month added when there are 13 new moons
between Winter solstices. This intercalary leap month is not
representable in its traditional form in the `t:Calendar.date/0` struct.

This function takes a date, or year and month, and returns either the
month number between 1 and 12 or a 2-tuple representing the leap month.
This 2-tuple looks like `{month_number, :leap}`.

The value returned from this function can be passed to `Calendrical.LunarJapanese.new/3` to
define a date using traditional lunar months.

### Arguments

* `date` which is any `t:Calendar.date/0` in the `Calendrical.LunarJapanese`
  calendar, *or*

*`year` and `month` representing the calendar year and month.

### Returns

* the lunar month as either an integer between 1 and 12 or a
tuple of the form `{lunar_month, :leap}`.

### Examples

    iex> Calendrical.LunarJapanese.lunar_month_of_year(~D[1379-02-01 Calendrical.LunarJapanese])
    2

    iex> Calendrical.LunarJapanese.lunar_month_of_year(~D[1379-03-01 Calendrical.LunarJapanese])
    {2, :leap}

    iex> Calendrical.LunarJapanese.lunar_month_of_year(~D[1379-04-01 Calendrical.LunarJapanese])
    3

# `lunar_month_of_year`

```elixir
@spec lunar_month_of_year(year :: Calendar.year(), month :: Calendar.month()) ::
  Calendrical.Lunisolar.lunar_month()
```

# `month`

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

# `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
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`

```elixir
@spec new(
  year :: Calendar.year(),
  month :: Calendrical.Lunisolar.lunar_month(),
  day :: Calendar.day()
) ::
  {:ok, Date.t()} | {:error, atom()}
```

Returns a `t:Calendar.date/0` in the `Calendrical.LunarJapanese` calendar
formed by a calendar year, a **traditional** lunar month number, and
a day number.

The lunar month is that used in traditional lunisolar calendar
notation. It is either a number between 1 and 12 (the number of months
in an ordinary year) or a leap month specified by the 2-tuple
`{month, :leap}` where `month` is the preceding traditional month
number that the intercalary repeats (read 閏N月 — "intercalary Nth
month"). See the moduledoc for the full ordinal-vs-traditional
discussion.

This function is the right entry point for creating dates from
primary chronicles, cultural references, or any other source that
reports a lunisolar date in its native form. To build a date from an
ordinal (1..13) month number — the form stored on the `Date.t`
struct itself — use `Date.new/4` instead.

### Arguments

* `year` is any year in the `Calendrical.LunarJapanese` calendar.

* `lunar_month` is either a traditional month number between 1 and 12,
  or for an intercalary month the 2-tuple `{month, :leap}` where `month`
  is the preceding traditional month number.

* `day` is any day number valid for `year` and `lunar_month`.

### Returns

* `{:ok, date}` where `date.month` is the **ordinal** position of the
  given lunar month within the year (1..12 in ordinary years, 1..13 in
  leap years), or

* `{:error, reason}`.

### Examples

    # Lunar new year
    iex> Calendrical.LunarJapanese.new(1379, 1, 1)
    {:ok, ~D[1379-01-01 Calendrical.LunarJapanese]}

    # First day of the intercalary 2nd month (閏2月) of Y1379 —
    # traditional notation: {2, :leap}; the resulting date.month is
    # the ordinal 3
    iex> Calendrical.LunarJapanese.new(1379, {2, :leap}, 1)
    {:ok, ~D[1379-03-01 Calendrical.LunarJapanese]}

    # Kaei 7, traditional 11th month, day 27 (安政改元日) — Y1210 has
    # an intercalary {7, :leap}, so traditional M11 is ordinal m12
    iex> {:ok, date} = Calendrical.LunarJapanese.new(1210, 11, 27)
    iex> Date.convert(date, Calendar.ISO)
    {:ok, ~D[1855-01-15]}

# `new!`

```elixir
@spec new!(
  year :: Calendar.year(),
  month :: Calendrical.Lunisolar.lunar_month(),
  day :: Calendar.day()
) ::
  Date.t()
```

Raising variant of `new/3`.

Raises `ArgumentError` if the date is not valid in this calendar.

# `new_year_for_gregorian_year`

```elixir
@spec new_year_for_gregorian_year(Calendar.year()) :: Date.t()
```

Returns the gregorian date of the
Luanr New Year for a given gregorian year.

### Arguments

* `gregorian_year` is any year in the Gregorian calendar.

### Returns

* a `t:Calendar.date/0` representing the Gregorian date of
  the lunar year of the given Gregorian year.

### Example

    iex> Calendrical.Chinese.new_year_for_gregorian_year(2021)
    ~D[2021-02-12]

    iex> Calendrical.Chinese.new_year_for_gregorian_year(2022)
    ~D[2022-02-01]

    iex> Calendrical.Chinese.new_year_for_gregorian_year(2023)
    ~D[2023-01-22]

# `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 `:months` only.

# `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 gregorain year as displayed
on rendered calendars.

# `traditional_leap_month`

```elixir
@spec traditional_leap_month(date_or_year :: Date.t() | Calendar.year()) ::
  Calendar.month() | nil
```

Returns the **traditional** number (1..12) of the leap month for a year,
or `nil` if the year is not a leap year.

The intercalary month in lunisolar tradition repeats the number of the
preceding non-leap month. For example, the intercalary that appears at
ordinal position 3 of Y1379 is written 閏2月 in traditional notation
and used as `{2, :leap}` in this module's API.

### Arguments

* `date_or_year` is either an integer year number
  or a `t:Calendar.date/0` in the `Calendrical.LunarJapanese`
  calendar.

### Returns

* the traditional number of the leap month (1..12), or

* `nil` if there is no leap month in the given year.

### Examples

    iex> Calendrical.LunarJapanese.traditional_leap_month(1379)
    2

    iex> Calendrical.LunarJapanese.traditional_leap_month(1210)
    7

    iex> Calendrical.LunarJapanese.traditional_leap_month(1380)
    nil

# `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_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*
