# `Tempo.Holidays.SchoolTerms.NSW`
[🔗](https://github.com/elixir-tempo/tempo_holidays/blob/v0.1.0/lib/tempo/holidays/school_terms/nsw.ex#L1)

New South Wales public school terms, school holidays and school
development days, from the rules the Department of Education's calendars
follow.

The Department publishes each year's calendar a few years ahead, and
publishes it as dates, not rules. These rules reproduce every calendar it
has published, 2016 to 2030, in both divisions, and project the years after:

* **Term 1 ends before Easter or in the week of 7–13 April** — on the day
  before Good Friday when Good Friday falls 31 March–13 April, so Easter
  opens the autumn holidays, and otherwise on the Friday that falls 7–13
  April.

* **The autumn, winter and spring holidays are two weeks** — each runs from
  the Monday after a term's last day, and the next term starts on the Monday
  two weeks later, or on the next school day when that Monday is a public
  holiday.

* **Term 3 is ten weeks** — Monday of its first week to Friday of its tenth.

* **Term 2 runs to Term 3** — up to 2025 Term 2 is ten weeks. From 2026 Term 3
  starts on the Monday on or after 18 July, so Term 2 is ten weeks or eleven.

* **Term 4 ends in the week before Christmas** — up to 2025 on the Friday that
  falls 17–23 December, or on that week's Tuesday when the Friday is the 22nd
  or 23rd; from 2026 on the Thursday that falls 17–23 December, or on that
  week's Monday when the Thursday is the 22nd or 23rd.

* **Term 1 starts after Australia Day** — up to 2021 on the school day after
  Australia Day; from 2022 six weeks after the previous Term 4 ended, on the
  same weekday, unless the year would then have fewer than 199 school days,
  when it starts on the school day after Australia Day.

* **The Western division starts a week later** — its Term 1 starts seven days
  after the Eastern division's.

A school day is a weekday that is not one of New South Wales' public holidays,
as `Tempo.Holidays.holidays/2` gives them, and school development days are
school days. `terms/2`, `holidays/2` and `development_days/2` return interval
sets, so they compose with the rest of Tempo.

## Example

    {:ok, terms} = NSW.terms(~o"2027")
    {:ok, holidays} = NSW.holidays(~o"2027")
    {:ok, next_holidays} = Tempo.members_overlapping(holidays, ~o"2027-07")

> *"The NSW school **terms** of 2027, the **holidays** between them, and the
> holidays that fall in July."*

# `division`

```elixir
@type division() :: :eastern | :western
```

A school division: `:eastern`, most of the state, or `:western`, the schools
in the far west, whose Term 1 starts a week later.

# `year`

```elixir
@type year() :: pos_integer() | Tempo.t()
```

A school year: a year from 2016, as an integer or a Tempo value naming it.

# `development_days`

```elixir
@spec development_days(year(), keyword()) ::
  {:ok, Tempo.t()} | {:error, {atom(), term()}}
```

Returns a year's school development days.

Staff attend on a school development day and students do not. The Department
has published them since 2023: the first two school days of Term 1, the first
of Terms 2 and 3, and the last two of Term 4 in 2023 and 2024; from 2025 the
first four school days of Term 1, the first two of Term 2, and the first of
Terms 3 and 4. Each day is tagged with its term's number.

### Arguments

* `year` is a year from 2023, as an integer or a `t:Tempo.t/0` naming it.

### Options

* `:division` is `:eastern` or `:western`, as for `terms/2`: the Western
  division's Term 1 development days are the first days of its own Term 1.

### Returns

* `{:ok, development_days}`, a set (a `t:Tempo.t/0`) of the days.

* `{:error, reason}` as for `terms/2`, or `{:unpublished_development_days,
  year}` for a year before 2023.

### Examples

    iex> {:ok, days} = Tempo.Holidays.SchoolTerms.NSW.development_days(~o"2027")
    iex> days |> Tempo.IntervalSet.members() |> Enum.map(&Tempo.to_iso8601!/1)
    ["2027Y1M28D", "2027Y1M29D", "2027Y2M1D", "2027Y2M2D", "2027Y4M27D", "2027Y4M28D",
     "2027Y7M19D", "2027Y10M11D"]

# `holidays`

```elixir
@spec holidays(year(), keyword()) :: {:ok, Tempo.t()} | {:error, {atom(), term()}}
```

Returns a year's four school holidays.

The holidays are the days between the terms: the autumn, winter and spring
holidays after Terms 1, 2 and 3, and the summer holidays after Term 4, which
run into the next year until its Term 1 starts. Each holiday takes in the
weekends either side, and is tagged `%{holiday: :autumn}`, `:winter`,
`:spring` or `:summer`.

### Arguments

* `year` is a year from 2016, as for `terms/2`.

### Options

* `:division` is `:eastern` or `:western`, as for `terms/2`: the Western
  division's summer holidays run a week longer.

### Returns

* `{:ok, holidays}`, a set (a `t:Tempo.t/0`) of the four holidays.

* `{:error, reason}` as for `terms/2`.

### Examples

    iex> {:ok, holidays} = Tempo.Holidays.SchoolTerms.NSW.holidays(~o"2027")
    iex> holidays |> Tempo.IntervalSet.members() |> Enum.map(&Tempo.to_iso8601!/1)
    ["2027Y4M10D/26D", "2027Y7M3D/18D", "2027Y9M25D/10M10D", "2027Y12M21D/2028Y1M30D"]

# `terms`

```elixir
@spec terms(year(), keyword()) :: {:ok, Tempo.t()} | {:error, {atom(), term()}}
```

Returns a year's four school terms.

Each term runs from its first day to its last, school development days
included, and is tagged with its number: `%{term: 1}` to `%{term: 4}`.

### Arguments

* `year` is a year from 2016, the first the rules were checked against: an
  integer or a `t:Tempo.t/0` naming the year, `~o"2027"`.

### Options

* `:division` is `:eastern`, the default, or `:western` for the schools in the
  far west, whose Term 1 starts a week later.

### Returns

* `{:ok, terms}`, a set (a `t:Tempo.t/0`) of the four terms.

* `{:error, reason}` — `{:invalid_year, year}`, `{:invalid_division, division}`
  or `{:invalid_option, options}`.

### Examples

    iex> {:ok, terms} = Tempo.Holidays.SchoolTerms.NSW.terms(~o"2027")
    iex> terms |> Tempo.IntervalSet.members() |> Enum.map(&Tempo.to_iso8601!/1)
    ["2027Y1M28D/4M9D", "2027Y4M27D/7M2D", "2027Y7M19D/9M24D", "2027Y10M11D/12M20D"]

    iex> {:ok, terms} = Tempo.Holidays.SchoolTerms.NSW.terms(2027, division: :western)
    iex> terms |> Tempo.IntervalSet.first() |> Tempo.to_iso8601!()
    "2027Y2M4D/4M9D"

---

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