# `Intl.DateTimeFormat`
[🔗](https://github.com/elixir-localize/intl/blob/v1.1.0/lib/intl/date_time_format.ex#L1)

Locale-sensitive date and time formatting, modelled on
[`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).

Formats dates, times, and datetimes according to locale conventions.
Accepts `Date`, `Time`, `DateTime`, and `NaiveDateTime` structs.

Delegates to `Localize.DateTime`, `Localize.Date`, and
`Localize.Time` for the underlying formatting.

# `format`

```elixir
@spec format(
  Date.t() | Time.t() | DateTime.t() | NaiveDateTime.t() | map(),
  Keyword.t()
) ::
  {:ok, String.t()} | {:error, term()}
```

Formats a date, time, or datetime value according to locale conventions.

### Arguments

* `value` is a `Date`, `Time`, `DateTime`, or `NaiveDateTime`
  struct, or a map with date and/or time keys.

* `options` is a keyword list of options.

### Options

* `:locale` is a locale identifier string or atom. The default
  is the current process locale.

* `:date_style` is `:full`, `:long`, `:medium`, or `:short`.
  Provides a predefined date format. Cannot be combined with
  individual component options.

* `:time_style` is `:full`, `:long`, `:medium`, or `:short`.
  Provides a predefined time format. Cannot be combined with
  individual component options.

* `:era` is `:long`, `:short`, or `:narrow` (for example,
  "Anno Domini", "AD", "A").

* `:weekday` is `:long`, `:short`, or `:narrow`.

* `:year` is `:numeric` or `:"2-digit"`.

* `:month` is `:numeric`, `:"2-digit"`, `:long`, `:short`,
  or `:narrow`.

* `:day` is `:numeric` or `:"2-digit"`.

* `:hour` is `:numeric` or `:"2-digit"`.

* `:minute` is `:numeric` or `:"2-digit"`.

* `:second` is `:numeric` or `:"2-digit"`.

* `:day_period` is `:long`, `:short`, or `:narrow`. Renders
  flexible day periods such as "in the morning" or "noon".

* `:fractional_second_digits` is `1`, `2`, or `3`. Renders
  that many fractional-second digits after the seconds field.

* `:time_zone_name` is `:short`, `:long`, `:short_offset`,
  `:long_offset`, `:short_generic`, or `:long_generic`. Only
  applies to `DateTime` values with a time zone.

* `:hour12` is a boolean selecting a 12-hour (`true`) or
  24-hour (`false`) clock for the `:hour` component.

* `:hour_cycle` is `:h11`, `:h12`, `:h23`, or `:h24`. Takes
  precedence over `:hour12`.

* `:numbering_system` is a CLDR numbering system name (for
  example, `:thai`). All numeric fields render in that system.

* `:time_zone` is a time zone identifier string (for example,
  `"America/New_York"`).

* `:calendar` is a calendar type atom (for example,
  `:gregorian`).

### Returns

* `{:ok, formatted_string}` on success.

* `{:error, reason}` if the value or options are invalid.

### Examples

    iex> Intl.DateTimeFormat.format(~D[2017-07-10], locale: :en, date_style: :full)
    {:ok, "Monday, July 10, 2017"}

    iex> Intl.DateTimeFormat.format(~D[2017-07-10], locale: :en, date_style: :short)
    {:ok, "7/10/17"}

    iex> Intl.DateTimeFormat.format(~N[2017-07-10 14:30:00], locale: :en, date_style: :medium, time_style: :short, prefer: :ascii)
    {:ok, "Jul 10, 2017, 2:30 PM"}

    iex> Intl.DateTimeFormat.format(~D[2017-07-10], locale: :en, year: :numeric, month: :long, day: :numeric)
    {:ok, "July 10, 2017"}

    iex> Intl.DateTimeFormat.format(~T[14:30:00], locale: :en, hour: :numeric, minute: :numeric, hour12: false)
    {:ok, "14:30"}

# `format!`

```elixir
@spec format!(
  Date.t() | Time.t() | DateTime.t() | NaiveDateTime.t() | map(),
  Keyword.t()
) ::
  String.t() | no_return()
```

Formats a date, time, or datetime value, raising on error.

Same as `format/2` but returns the string directly or raises.

### Arguments

* `value` is a `Date`, `Time`, `DateTime`, or `NaiveDateTime`
  struct, or a map with date and/or time keys.

* `options` is a keyword list of options.

### Returns

* A formatted string.

### Examples

    iex> Intl.DateTimeFormat.format!(~D[2017-07-10], locale: :en, date_style: :full)
    "Monday, July 10, 2017"

# `format_range`

```elixir
@spec format_range(map(), map(), Keyword.t()) :: {:ok, String.t()} | {:error, term()}
```

Formats a date/time range according to locale conventions.

### Arguments

* `from` is the start date, time, or datetime.

* `to` is the end date, time, or datetime.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`.

### Returns

* `{:ok, formatted_string}` on success.

* `{:error, reason}` if the values or options are invalid.

### Examples

    iex> Intl.DateTimeFormat.format_range(~D[2017-07-10], ~D[2017-07-15], locale: :en)
    {:ok, "Jul 10 – 15, 2017"}

# `format_range!`

```elixir
@spec format_range!(map(), map(), Keyword.t()) :: String.t() | no_return()
```

Formats a date/time range, raising on error.

Same as `format_range/3` but returns the string directly or raises.

### Arguments

* `from` is the start date, time, or datetime.

* `to` is the end date, time, or datetime.

* `options` is a keyword list of options.

### Returns

* A formatted string.

### Examples

    iex> Intl.DateTimeFormat.format_range!(~D[2017-07-10], ~D[2017-07-15], locale: :en)
    "Jul 10 – 15, 2017"

# `format_range_to_parts`

```elixir
@spec format_range_to_parts(map(), map(), Keyword.t()) ::
  {:ok, [%{type: atom(), value: String.t(), source: atom()}]} | {:error, term()}
```

Formats a date/time range into a list of typed parts.

Modelled on the JS `Intl.DateTimeFormat.formatRangeToParts()`. In
addition to `:type` and `:value`, each part carries a `:source`
key: `:start_range`, `:end_range`, or `:shared`. When the range
endpoints have no practical difference, the single formatted value
carries source `:shared` throughout, matching JS.

### Arguments

* `from` is the start date, time, or datetime.

* `to` is the end date, time, or datetime.

* `options` is a keyword list of options. Accepts the same
  options as `format_range/3`.

### Returns

* `{:ok, parts}` where `parts` is a list of
  `%{type: atom, value: String.t(), source: atom}` maps.

* `{:error, reason}` if the values or options are invalid.

### Examples

    iex> Intl.DateTimeFormat.format_range_to_parts(~D[2022-04-22], ~D[2022-04-25], locale: :en)
    {:ok, [
      %{type: :month, value: "Apr", source: :start_range},
      %{type: :literal, value: " ", source: :start_range},
      %{type: :day, value: "22", source: :start_range},
      %{type: :literal, value: " – ", source: :shared},
      %{type: :day, value: "25", source: :end_range},
      %{type: :literal, value: ", ", source: :end_range},
      %{type: :year, value: "2022", source: :end_range}
    ]}

# `format_range_to_parts!`

```elixir
@spec format_range_to_parts!(map(), map(), Keyword.t()) ::
  [%{type: atom(), value: String.t(), source: atom()}] | no_return()
```

Formats a date/time range into typed parts, raising on error.

Same as `format_range_to_parts/3` but returns the parts directly or raises.

### Arguments

* `from` is the start date, time, or datetime.

* `to` is the end date, time, or datetime.

* `options` is a keyword list of options.

### Returns

* A list of `%{type: atom, value: String.t(), source: atom}` maps.

### Examples

    iex> Intl.DateTimeFormat.format_range_to_parts!(~D[2022-04-22], ~D[2022-04-25], locale: :en) |> length()
    7

# `format_to_parts`

```elixir
@spec format_to_parts(
  Date.t() | Time.t() | DateTime.t() | NaiveDateTime.t() | map(),
  Keyword.t()
) ::
  {:ok, [%{type: atom(), value: String.t()}]} | {:error, term()}
```

Formats a date, time, or datetime into a list of typed parts.

Modelled on the JS `Intl.DateTimeFormat.formatToParts()`. Each
part is a map with a `:type` and a `:value` key. Part types
include `:year`, `:month`, `:day`, `:weekday`, `:era`, `:hour`,
`:minute`, `:second`, `:fractional_second`, `:day_period`,
`:time_zone_name`, and `:literal`.

### Arguments

* `value` is a `Date`, `Time`, `DateTime`, or `NaiveDateTime`
  struct, or a map with date and/or time keys.

* `options` is a keyword list of options. Accepts the same
  options as `format/2`.

### Returns

* `{:ok, parts}` where `parts` is a list of
  `%{type: atom, value: String.t()}` maps.

* `{:error, reason}` if the value or options are invalid.

### Examples

    iex> Intl.DateTimeFormat.format_to_parts(~D[2017-07-10], locale: :en, year: :numeric, month: :long, day: :numeric)
    {:ok, [
      %{type: :month, value: "July"},
      %{type: :literal, value: " "},
      %{type: :day, value: "10"},
      %{type: :literal, value: ", "},
      %{type: :year, value: "2017"}
    ]}

# `format_to_parts!`

```elixir
@spec format_to_parts!(
  Date.t() | Time.t() | DateTime.t() | NaiveDateTime.t() | map(),
  Keyword.t()
) ::
  [%{type: atom(), value: String.t()}] | no_return()
```

Formats a date, time, or datetime into typed parts, raising on error.

Same as `format_to_parts/2` but returns the parts directly or raises.

### Arguments

* `value` is a `Date`, `Time`, `DateTime`, or `NaiveDateTime`
  struct, or a map with date and/or time keys.

* `options` is a keyword list of options.

### Returns

* A list of `%{type: atom, value: String.t()}` maps.

### Examples

    iex> Intl.DateTimeFormat.format_to_parts!(~D[2017-07-10], locale: :en, date_style: :short) |> length()
    5

---

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