Date & times formatting functions for the Common Locale Data Repository (CLDR) package https://github.com/elixir-cldr/cldr
Elixir
73
547 commits
updated Mar 15, 2026
Note that ex_cldr_dates_times requires Elixir 1.12 or later.
Add ex_cldr_dates_time as a dependency to your mix project:
defp deps do
[
{:ex_cldr_dates_times, "~> 2.0"}
]
end
then retrieve ex_cldr_dates_times from hex:
mix deps.get
mix deps.compile
ex_cldr_dates_times uses the configuration set for the dependency ex_cldr. See the documentation for ex_cldr.
A backend module is required that is used to host the functions that manage CLDR data. An example to get started is:
Create a backend module (see ex_cldr for details of the available options). Note the requirement to configure the appropriate Cldr provider backends.
defmodule MyApp.Cldr do
use Cldr,
locales: ["en", "fr", "ja"],
providers: [Cldr.Number, Cldr.Calendar, Cldr.DateTime]
end
[Optional] Update config.exs configuration to specify this backend as the system default. Not required, but often useful.
config :ex_cldr,
default_locale: "en",
default_backend: MyApp.Cldr
ex_cldr_dates_times is an addon library application for ex_cldr that provides localisation and formatting for dates, times and date_times.
The primary API is MyApp.Cldr.Date.to_string/2, MyApp.Cldr.Time.to_string/2, MyApp.Cldr.DateTime.to_string/2 and MyApp.Cldr.DateTime.Relative.to_string/2. In the following examples MyApp refers to a CLDR backend module that must be defined by the developer:
iex> MyApp.Cldr.Date.to_string ~D[2020-05-30]
{:ok, "May 30, 2020"}
iex> MyApp.Cldr.Time.to_string ~U[2020-05-30 03:52:56Z]
{:ok, "3:52:56 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z]
{:ok, "May 30, 2020, 3:52:56 AM"}
# Note that if options are provided, a backend
# module is also required
iex> MyApp.Cldr.DateTime.Relative.to_string 1, unit: :day, format: :narrow
{:ok, "tomorrow"}
For help in iex:
iex> h MyApp.Cldr.Date.to_string
iex> h MyApp.Cldr.Time.to_string
iex> h MyApp.Cldr.DateTime.to_string
iex> h MyApp.Cldr.DateTime.Relative.to_string
Dates, Times and DateTimes can be formatted using standard formats, format strings or format IDs.
Standard formats provide cross-locale standardisation and therefore should be preferred where possible. The format types, implemented for MyApp.Cldr.Date.to_string/2, MyApp.Cldr.Time.to_string/2,MyApp.Cldr.DateTime.to_string/2 are :short, :medium, :long and :full. The default is :medium. For example, assuming a configured backend called MyApp.Cldr:
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :short
{:ok, "5/30/20, 3:52 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :long
{:ok, "May 30, 2020 at 3:52:56 AM UTC"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :medium
{:ok, "May 30, 2020, 3:52:56 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :long, locale: "fr"
{:ok, "30 mai 2020 à 03:52:56 UTC"}
Format strings use one or more formatting symbols to define what date and time elements should be placed in the format. A simple example to format the time into hours and minutes:
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: "hh:mm"
{:ok, "03:52"}
Format IDs are an atom that is a key into a map of formats defined by CLDR. These format IDs are returned by MyApp.Cldr.DateTime.Format.date_time_available_formats/2 (assuming your backend is MyApp.Cldr). The set of common format names across all locales configured in ex_cldr can be returned by MyApp.Cldr.DateTime.Format.common_date_time_format_names/0.
iex> MyApp.Cldr.DateTime.Format.date_time_available_formats()
%{mmmm_w_count_one: "'week' W 'of' MMMM", gy_mmm: "MMM y G", md: "M/d",
mmm_md: "MMMM d", e_hms: "E HH:mm:ss", ed: "d E", y_mmm: "MMM y",
e_hm: "E HH:mm", mmm_ed: "E, MMM d", y_mmm_ed: "E, MMM d, y",
gy_mm_md: "MMM d, y G", mmm: "LLL", y_md: "M/d/y", gy: "y G",
hms: "h:mm:ss a", hm: "h:mm a", y_mmmm: "MMMM y", m: "L",
gy_mmm_ed: "E, MMM d, y G", y_qqq: "QQQ y", e: "ccc", y_qqqq: "QQQQ y",
hmsv: "h:mm:ss a v", mmmm_w_count_other: "'week' W 'of' MMMM",
ehm: "E h:mm a", y_m_ed: "E, M/d/y", h: "h a", hmv: "h:mm a v",
yw_count_other: "'week' w 'of' y", mm_md: "MMM d", y_m: "M/y", m_ed: "E, M/d",
ms: "mm:ss", d: "d", y_mm_md: "MMM d, y", yw_count_one: "'week' w 'of' y",
y: "y", ehms: "E h:mm:ss a"}
# These format types can be invoked for any locale - meaning
# these format names are defined for all configured locales.
iex> MyApp.Cldr.DateTime.Format.common_date_time_format_names()
[:gy_mmm, :md, :mmm_md, :e_hms, :ed, :y_mmm, :e_hm, :mmm_ed, :y_mmm_ed,
:gy_mm_md, :mmm, :y_md, :gy, :hms, :hm, :y_mmmm, :m, :gy_mmm_ed, :y_qqq, :e,
:y_qqqq, :hmsv, :mmmm_w_count_other, :ehm, :y_m_ed, :h, :hmv, :yw_count_other,
:mm_md, :y_m, :m_ed, :ms, :d, :y_mm_md, :y, :ehms]
iex> Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :gy_mmm_ed
{:ok, "Sat, May 30, 2020 AD"}
iex(2)> Cldr.Time.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :hm
{:ok, "3:52 AM"}
iex(3)> Cldr.Date.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :yMd
{:ok, "5/30/2020"}
The CLDR standard
defines a wide range of format symbols. Most - but not all - of these symbols are supported in
Cldr. The supported symbols are described below. Note the known restrictions and limitations.
| Element | Symbol | Example | Cldr Format |
|---|---|---|---|
| Era | G, GG, GGG | "AD" | Abbreviated |
| GGGG | "Anno Domini" | Wide | |
| GGGGG | "A" | Narrow | |
| Year | y | 7 | Minimum necessary digits |
| yy | "17" | Least significant 2 digits | |
| yyy | "017", "2017" | Padded to at least 3 digits | |
| yyyy | "2017" | Padded to at least 4 digits | |
| yyyyy | "02017" | Padded to at least 5 digits | |
| ISOWeek Year | Y | 7 | Minimum necessary digits |
| YY | "17" | Least significant 2 digits | |
| YYY | "017", "2017" | Padded to at least 3 digits | |
| YYYY | "2017" | Padded to at least 4 digits | |
| YYYYY | "02017" | Padded to at least 5 digits | |
| Related Gregorian Year | r, rr, rr+ | 2017 | Minimum necessary digits |
| Cyclic Year | U, UU, UUU | "甲子" | Abbreviated |
| UUUU | "甲子" (for now) | Wide | |
| UUUUU | "甲子" (for now) | Narrow | |
| Extended Year | u+ | 4601 | Minimum necessary digits |
| Quarter | Q | 2 | Single digit |
| "02" | Two digits | ||
| QQQ | "Q2" | Abbreviated | |
| QQQQ | "2nd quarter" | Wide | |
| QQQQQ | "2" | Narrow | |
| Standalone Quarter | q | 2 | Single digit |
| "02" | Two digits | ||
| qqq | "Q2" | Abbreviated | |
| qqqq | "2nd quarter" | Wide | |
| qqqqq | "2" | Narrow | |
| Month | M | 9 | Single digit |
| MM | "09" | Two digits | |
| MMM | "Sep" | Abbreviated | |
| MMMM | "September" | Wide | |
| MMMMM | "S" | Narrow | |
| Standalone Month | L | 9 | Single digit |
| LL | "09" | Two digits | |
| LLL | "Sep" | Abbreviated | |
| LLLL | "September" | Wide | |
| LLLLL | "S" | Narrow | |
| Week of Year | w | 2, 22 | Single digit |
| ww | 02, 22 | Two digits, zero padded | |
| Week of Month | W | 2 | Single digit. NOT IMPLEMENTED YET |
| Day of Year | D | 3, 33, 333 | Minimum necessary digits |
| DD | 03, 33, 333 | Minimum of 2 digits, zero padded | |
| DDD | 003, 033, 333 | Minimum of 3 digits, zero padded | |
| Day of Month | d | 2, 22 | Minimum necessary digits |
| dd | 02, 22 | Two digits, zero padded | |
| Day of Week | E, EE, EEE | "Tue" | Abbreviated |
| EEEE | "Tuesday" | Wide | |
| EEEEE | "T" | Narrow | |
| EEEEEE | "Tu" | Short | |
| e | 2 | Single digit | |
| ee | "02" | Two digits | |
| eee | "Tue" | Abbreviated | |
| eeee | "Tuesday" | Wide | |
| eeeee | "T" | Narrow | |
| eeeeee | "Tu" | Short | |
| Standalone Day of Week | c, cc | 2 | Single digit |
| ccc | "Tue" | Abbreviated | |
| cccc | "Tuesday" | Wide | |
| ccccc | "T" | Narrow | |
| cccccc | "Tu" | Short | |
| AM or PM | a, aa, aaa | "am." | Abbreviated |
| aaaa | "am." | Wide | |
| aaaaa | "am" | Narrow | |
| Noon, Mid, AM, PM | b, bb, bbb | "mid." | Abbreviated |
| bbbb | "midnight" | Wide | |
| bbbbb | "md" | Narrow | |
| Flexible time period | B, BB, BBB | "at night" | Abbreviated |
| BBBB | "at night" | Wide | |
| BBBBB | "at night" | Narrow | |
| Hour | h, K, H, k | See the table below | |
| Minute | m | 3, 10 | Minimum digits of minutes |
| mm | "03", "12" | Two digits, zero padded | |
| Second | s | 3, 48 | Minimum digits of seconds |
| ss | "03", "48" | Two digits, zero padded | |
| Fractional Seconds | S | 3, 48 | Minimum digits of fractional seconds |
| SS | "03", "48" | Two digits, zero padded | |
| Milliseconds | A+ | 4000, 63241 | Minimum digits of milliseconds since midnight |
| Generic non-location TZ | v | "Etc/UTC" | :time_zone key, unlocalised |
| vvvv | "unk" | Generic timezone name. Currently returns only "unk" | |
| Specific non-location TZ | z..zzz | "UTC" | :zone_abbr key, unlocalised |
| zzzz | "GMT" | Delegates to zone_gmt/4 | |
| Timezone ID | V | "unk" | :zone_abbr key, unlocalised |
| VV | "Etc/UTC | Delegates to zone_gmt/4 | |
| VVV | "Unknown City" | Exemplar city. Not supported. | |
| VVVV | "GMT" | Delegates to `zone_gmt/4 | |
| ISO8601 Format | Z..ZZZ | "+0100" | ISO8601 Basic Format with hours and minutes |
| ZZZZ | "+01:00" | Delegates to `zone_gmt/4 | |
| ZZZZZ | "+01:00:10" | ISO8601 Extended format with optional seconds | |
| ISO8601 plus Z | X | "+01" | ISO8601 Basic Format with hours and optional minutes or "Z" |
| XX | "+0100" | ISO8601 Basic Format with hours and minutes or "Z" | |
| XXX | "+0100" | ISO8601 Basic Format with hours and minutes, optional seconds or "Z" | |
| XXXX | "+010059" | ISO8601 Basic Format with hours and minutes, optional seconds or "Z" | |
| XXXXX | "+01:00:10" | ISO8601 Extended Format with hours and minutes, optional seconds or "Z" | |
| ISO8601 minus Z | x | "+0100" | ISO8601 Basic Format with hours and optional minutes |
| xx | "-0800" | ISO8601 Basic Format with hours and minutes | |
| xxx | "+01:00" | ISO8601 Extended Format with hours and minutes | |
| xxxx | "+010059" | ISO8601 Basic Format with hours and minutes, optional seconds | |
| xxxxx | "+01:00:10" | ISO8601 Extended Format with hours and minutes, optional seconds | |
| GMT Format | O | "+0100" | Short localised GMT format |
| OOOO | "+010059" | Long localised GMT format |
The hour of day can be formatted differently depending whether a 12- or 24-hour day is being represented and depending on the way in which midnight and noon are represented. The following table illustrates the differences:
| Symbol | Midn. | Morning | Noon | Afternoon | Midn. |
|---|---|---|---|---|---|
| h | 12 | 1...11 | 12 | 1...11 | 12 |
| K | 0 | 1...11 | 0 | 1...11 | 0 |
| H | 0 | 1...11 | 12 | 13...23 | 0 |
| k | 24 | 1...11 | 12 | 13...23 | 24 |
The primary API for formatting relative dates and datetimes is MyApp.Cldr.DateTime.Relative.to_string/2. Some examples:
iex> MyApp.Cldr.DateTime.Relative.to_string(-1)
{:ok, "1 second ago"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1)
{:ok, "in 1 second"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day)
{:ok, "tomorrow"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
{:ok, "demain"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day, format: :narrow)
{:ok, "tomorrow"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1234, unit: :year)
{:ok, "in 1,234 years"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
{:ok, "dans 1 234 ans"}
iex> MyApp.Cldr.DateTime.Relative.to_string(31)
{:ok, "in 31 seconds"}
iex> MyApp.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
{:ok, "in 3 days"}
iex> MyApp.Cldr.DateTime.Relative.to_string(310, format: :short, locale: "fr")
{:ok, "dans 5 min"}
iex> MyApp.Cldr.DateTime.Relative.to_string(310, format: :narrow, locale: "fr")
{:ok, "+5 min"}
iex> MyApp.Cldr.DateTime.Relative.to_string 2, unit: :wed, format: :short
{:ok, "in 2 Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string 1, unit: :wed, format: :short
{:ok, "next Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :wed, format: :short
{:ok, "last Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :wed
{:ok, "last Wednesday"}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :quarter
{:ok, "last quarter"}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :mon, locale: "fr"
{:ok, "lundi dernier"}
iex> MyApp.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
{:error, {Cldr.UnknownTimeUnit,
"Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}}
Interval formats allow for software to format intervals like "Jan 10-12, 2008" as a shorter and more natural format than "Jan 10, 2008 - Jan 12, 2008". They are designed to take a start and end date, time or datetime plus a formatting pattern and use that information to produce a localized format.
An interval is expressed as either a from and to date, time or datetime. Or it can also be a Date.Range or CalendarInterval from the calendar_interval library.
Cldr.Interval.to_string/3 function to format an interval based upon the type of the arguments: date, datetime or time. The modules Cldr.Date.Interval, Cldr.Time.Interval and Cldr.DateTime.Interval also provide a to_string/3 function for when the desired output format is more specific.
Some examples:
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-31], MyApp.Cldr
{:ok, "Jan 1 – Dec 31, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12], MyApp.Cldr
{:ok, "Jan 1 – 12, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12], MyApp.Cldr,
...> format: :long
{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-01], MyApp.Cldr,
...> format: :long, style: :year_and_month
{:ok, "January – December 2020"}
iex> use CalendarInterval
iex> Cldr.Interval.to_string ~I"2020-01-01/12", MyApp.Cldr,
...> format: :long
{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-12-01 10:05:00.0Z], MyApp.Cldr,
...> format: :long
{:ok, "January 1, 2020 at 12:00:00 AM UTC – December 1, 2020 at 10:05:00 AM UTC"}
iex> Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:05:00.0Z], MyApp.Cldr,
...> format: :long
{:ok, "January 1, 2020 at 12:00:00 AM UTC – 10:05:00 AM UTC"}
Although largely complete (with respect to the CLDR data), there are some known limitations as of release 2.0.
v, V, x, X, z, Z, O) not all localisations are performed. Only that data available within a t:DateTime.t/0 struct is used to format timezone data.Elixir
98.7%
Erlang
1.2%
Date & times formatting functions for the Common Locale Data Repository (CLDR) package https://github.com/elixir-cldr/cldr
Elixir
73
547 commits
updated Mar 15, 2026
Note that ex_cldr_dates_times requires Elixir 1.12 or later.
Add ex_cldr_dates_time as a dependency to your mix project:
defp deps do
[
{:ex_cldr_dates_times, "~> 2.0"}
]
end
then retrieve ex_cldr_dates_times from hex:
mix deps.get
mix deps.compile
ex_cldr_dates_times uses the configuration set for the dependency ex_cldr. See the documentation for ex_cldr.
A backend module is required that is used to host the functions that manage CLDR data. An example to get started is:
Create a backend module (see ex_cldr for details of the available options). Note the requirement to configure the appropriate Cldr provider backends.
defmodule MyApp.Cldr do
use Cldr,
locales: ["en", "fr", "ja"],
providers: [Cldr.Number, Cldr.Calendar, Cldr.DateTime]
end
[Optional] Update config.exs configuration to specify this backend as the system default. Not required, but often useful.
config :ex_cldr,
default_locale: "en",
default_backend: MyApp.Cldr
ex_cldr_dates_times is an addon library application for ex_cldr that provides localisation and formatting for dates, times and date_times.
The primary API is MyApp.Cldr.Date.to_string/2, MyApp.Cldr.Time.to_string/2, MyApp.Cldr.DateTime.to_string/2 and MyApp.Cldr.DateTime.Relative.to_string/2. In the following examples MyApp refers to a CLDR backend module that must be defined by the developer:
iex> MyApp.Cldr.Date.to_string ~D[2020-05-30]
{:ok, "May 30, 2020"}
iex> MyApp.Cldr.Time.to_string ~U[2020-05-30 03:52:56Z]
{:ok, "3:52:56 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z]
{:ok, "May 30, 2020, 3:52:56 AM"}
# Note that if options are provided, a backend
# module is also required
iex> MyApp.Cldr.DateTime.Relative.to_string 1, unit: :day, format: :narrow
{:ok, "tomorrow"}
For help in iex:
iex> h MyApp.Cldr.Date.to_string
iex> h MyApp.Cldr.Time.to_string
iex> h MyApp.Cldr.DateTime.to_string
iex> h MyApp.Cldr.DateTime.Relative.to_string
Dates, Times and DateTimes can be formatted using standard formats, format strings or format IDs.
Standard formats provide cross-locale standardisation and therefore should be preferred where possible. The format types, implemented for MyApp.Cldr.Date.to_string/2, MyApp.Cldr.Time.to_string/2,MyApp.Cldr.DateTime.to_string/2 are :short, :medium, :long and :full. The default is :medium. For example, assuming a configured backend called MyApp.Cldr:
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :short
{:ok, "5/30/20, 3:52 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :long
{:ok, "May 30, 2020 at 3:52:56 AM UTC"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :medium
{:ok, "May 30, 2020, 3:52:56 AM"}
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :long, locale: "fr"
{:ok, "30 mai 2020 à 03:52:56 UTC"}
Format strings use one or more formatting symbols to define what date and time elements should be placed in the format. A simple example to format the time into hours and minutes:
iex> MyApp.Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: "hh:mm"
{:ok, "03:52"}
Format IDs are an atom that is a key into a map of formats defined by CLDR. These format IDs are returned by MyApp.Cldr.DateTime.Format.date_time_available_formats/2 (assuming your backend is MyApp.Cldr). The set of common format names across all locales configured in ex_cldr can be returned by MyApp.Cldr.DateTime.Format.common_date_time_format_names/0.
iex> MyApp.Cldr.DateTime.Format.date_time_available_formats()
%{mmmm_w_count_one: "'week' W 'of' MMMM", gy_mmm: "MMM y G", md: "M/d",
mmm_md: "MMMM d", e_hms: "E HH:mm:ss", ed: "d E", y_mmm: "MMM y",
e_hm: "E HH:mm", mmm_ed: "E, MMM d", y_mmm_ed: "E, MMM d, y",
gy_mm_md: "MMM d, y G", mmm: "LLL", y_md: "M/d/y", gy: "y G",
hms: "h:mm:ss a", hm: "h:mm a", y_mmmm: "MMMM y", m: "L",
gy_mmm_ed: "E, MMM d, y G", y_qqq: "QQQ y", e: "ccc", y_qqqq: "QQQQ y",
hmsv: "h:mm:ss a v", mmmm_w_count_other: "'week' W 'of' MMMM",
ehm: "E h:mm a", y_m_ed: "E, M/d/y", h: "h a", hmv: "h:mm a v",
yw_count_other: "'week' w 'of' y", mm_md: "MMM d", y_m: "M/y", m_ed: "E, M/d",
ms: "mm:ss", d: "d", y_mm_md: "MMM d, y", yw_count_one: "'week' w 'of' y",
y: "y", ehms: "E h:mm:ss a"}
# These format types can be invoked for any locale - meaning
# these format names are defined for all configured locales.
iex> MyApp.Cldr.DateTime.Format.common_date_time_format_names()
[:gy_mmm, :md, :mmm_md, :e_hms, :ed, :y_mmm, :e_hm, :mmm_ed, :y_mmm_ed,
:gy_mm_md, :mmm, :y_md, :gy, :hms, :hm, :y_mmmm, :m, :gy_mmm_ed, :y_qqq, :e,
:y_qqqq, :hmsv, :mmmm_w_count_other, :ehm, :y_m_ed, :h, :hmv, :yw_count_other,
:mm_md, :y_m, :m_ed, :ms, :d, :y_mm_md, :y, :ehms]
iex> Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :gy_mmm_ed
{:ok, "Sat, May 30, 2020 AD"}
iex(2)> Cldr.Time.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :hm
{:ok, "3:52 AM"}
iex(3)> Cldr.Date.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :yMd
{:ok, "5/30/2020"}
The CLDR standard
defines a wide range of format symbols. Most - but not all - of these symbols are supported in
Cldr. The supported symbols are described below. Note the known restrictions and limitations.
| Element | Symbol | Example | Cldr Format |
|---|---|---|---|
| Era | G, GG, GGG | "AD" | Abbreviated |
| GGGG | "Anno Domini" | Wide | |
| GGGGG | "A" | Narrow | |
| Year | y | 7 | Minimum necessary digits |
| yy | "17" | Least significant 2 digits | |
| yyy | "017", "2017" | Padded to at least 3 digits | |
| yyyy | "2017" | Padded to at least 4 digits | |
| yyyyy | "02017" | Padded to at least 5 digits | |
| ISOWeek Year | Y | 7 | Minimum necessary digits |
| YY | "17" | Least significant 2 digits | |
| YYY | "017", "2017" | Padded to at least 3 digits | |
| YYYY | "2017" | Padded to at least 4 digits | |
| YYYYY | "02017" | Padded to at least 5 digits | |
| Related Gregorian Year | r, rr, rr+ | 2017 | Minimum necessary digits |
| Cyclic Year | U, UU, UUU | "甲子" | Abbreviated |
| UUUU | "甲子" (for now) | Wide | |
| UUUUU | "甲子" (for now) | Narrow | |
| Extended Year | u+ | 4601 | Minimum necessary digits |
| Quarter | Q | 2 | Single digit |
| "02" | Two digits | ||
| QQQ | "Q2" | Abbreviated | |
| QQQQ | "2nd quarter" | Wide | |
| QQQQQ | "2" | Narrow | |
| Standalone Quarter | q | 2 | Single digit |
| "02" | Two digits | ||
| qqq | "Q2" | Abbreviated | |
| qqqq | "2nd quarter" | Wide | |
| qqqqq | "2" | Narrow | |
| Month | M | 9 | Single digit |
| MM | "09" | Two digits | |
| MMM | "Sep" | Abbreviated | |
| MMMM | "September" | Wide | |
| MMMMM | "S" | Narrow | |
| Standalone Month | L | 9 | Single digit |
| LL | "09" | Two digits | |
| LLL | "Sep" | Abbreviated | |
| LLLL | "September" | Wide | |
| LLLLL | "S" | Narrow | |
| Week of Year | w | 2, 22 | Single digit |
| ww | 02, 22 | Two digits, zero padded | |
| Week of Month | W | 2 | Single digit. NOT IMPLEMENTED YET |
| Day of Year | D | 3, 33, 333 | Minimum necessary digits |
| DD | 03, 33, 333 | Minimum of 2 digits, zero padded | |
| DDD | 003, 033, 333 | Minimum of 3 digits, zero padded | |
| Day of Month | d | 2, 22 | Minimum necessary digits |
| dd | 02, 22 | Two digits, zero padded | |
| Day of Week | E, EE, EEE | "Tue" | Abbreviated |
| EEEE | "Tuesday" | Wide | |
| EEEEE | "T" | Narrow | |
| EEEEEE | "Tu" | Short | |
| e | 2 | Single digit | |
| ee | "02" | Two digits | |
| eee | "Tue" | Abbreviated | |
| eeee | "Tuesday" | Wide | |
| eeeee | "T" | Narrow | |
| eeeeee | "Tu" | Short | |
| Standalone Day of Week | c, cc | 2 | Single digit |
| ccc | "Tue" | Abbreviated | |
| cccc | "Tuesday" | Wide | |
| ccccc | "T" | Narrow | |
| cccccc | "Tu" | Short | |
| AM or PM | a, aa, aaa | "am." | Abbreviated |
| aaaa | "am." | Wide | |
| aaaaa | "am" | Narrow | |
| Noon, Mid, AM, PM | b, bb, bbb | "mid." | Abbreviated |
| bbbb | "midnight" | Wide | |
| bbbbb | "md" | Narrow | |
| Flexible time period | B, BB, BBB | "at night" | Abbreviated |
| BBBB | "at night" | Wide | |
| BBBBB | "at night" | Narrow | |
| Hour | h, K, H, k | See the table below | |
| Minute | m | 3, 10 | Minimum digits of minutes |
| mm | "03", "12" | Two digits, zero padded | |
| Second | s | 3, 48 | Minimum digits of seconds |
| ss | "03", "48" | Two digits, zero padded | |
| Fractional Seconds | S | 3, 48 | Minimum digits of fractional seconds |
| SS | "03", "48" | Two digits, zero padded | |
| Milliseconds | A+ | 4000, 63241 | Minimum digits of milliseconds since midnight |
| Generic non-location TZ | v | "Etc/UTC" | :time_zone key, unlocalised |
| vvvv | "unk" | Generic timezone name. Currently returns only "unk" | |
| Specific non-location TZ | z..zzz | "UTC" | :zone_abbr key, unlocalised |
| zzzz | "GMT" | Delegates to zone_gmt/4 | |
| Timezone ID | V | "unk" | :zone_abbr key, unlocalised |
| VV | "Etc/UTC | Delegates to zone_gmt/4 | |
| VVV | "Unknown City" | Exemplar city. Not supported. | |
| VVVV | "GMT" | Delegates to `zone_gmt/4 | |
| ISO8601 Format | Z..ZZZ | "+0100" | ISO8601 Basic Format with hours and minutes |
| ZZZZ | "+01:00" | Delegates to `zone_gmt/4 | |
| ZZZZZ | "+01:00:10" | ISO8601 Extended format with optional seconds | |
| ISO8601 plus Z | X | "+01" | ISO8601 Basic Format with hours and optional minutes or "Z" |
| XX | "+0100" | ISO8601 Basic Format with hours and minutes or "Z" | |
| XXX | "+0100" | ISO8601 Basic Format with hours and minutes, optional seconds or "Z" | |
| XXXX | "+010059" | ISO8601 Basic Format with hours and minutes, optional seconds or "Z" | |
| XXXXX | "+01:00:10" | ISO8601 Extended Format with hours and minutes, optional seconds or "Z" | |
| ISO8601 minus Z | x | "+0100" | ISO8601 Basic Format with hours and optional minutes |
| xx | "-0800" | ISO8601 Basic Format with hours and minutes | |
| xxx | "+01:00" | ISO8601 Extended Format with hours and minutes | |
| xxxx | "+010059" | ISO8601 Basic Format with hours and minutes, optional seconds | |
| xxxxx | "+01:00:10" | ISO8601 Extended Format with hours and minutes, optional seconds | |
| GMT Format | O | "+0100" | Short localised GMT format |
| OOOO | "+010059" | Long localised GMT format |
The hour of day can be formatted differently depending whether a 12- or 24-hour day is being represented and depending on the way in which midnight and noon are represented. The following table illustrates the differences:
| Symbol | Midn. | Morning | Noon | Afternoon | Midn. |
|---|---|---|---|---|---|
| h | 12 | 1...11 | 12 | 1...11 | 12 |
| K | 0 | 1...11 | 0 | 1...11 | 0 |
| H | 0 | 1...11 | 12 | 13...23 | 0 |
| k | 24 | 1...11 | 12 | 13...23 | 24 |
The primary API for formatting relative dates and datetimes is MyApp.Cldr.DateTime.Relative.to_string/2. Some examples:
iex> MyApp.Cldr.DateTime.Relative.to_string(-1)
{:ok, "1 second ago"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1)
{:ok, "in 1 second"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day)
{:ok, "tomorrow"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
{:ok, "demain"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1, unit: :day, format: :narrow)
{:ok, "tomorrow"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1234, unit: :year)
{:ok, "in 1,234 years"}
iex> MyApp.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
{:ok, "dans 1 234 ans"}
iex> MyApp.Cldr.DateTime.Relative.to_string(31)
{:ok, "in 31 seconds"}
iex> MyApp.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
{:ok, "in 3 days"}
iex> MyApp.Cldr.DateTime.Relative.to_string(310, format: :short, locale: "fr")
{:ok, "dans 5 min"}
iex> MyApp.Cldr.DateTime.Relative.to_string(310, format: :narrow, locale: "fr")
{:ok, "+5 min"}
iex> MyApp.Cldr.DateTime.Relative.to_string 2, unit: :wed, format: :short
{:ok, "in 2 Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string 1, unit: :wed, format: :short
{:ok, "next Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :wed, format: :short
{:ok, "last Wed."}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :wed
{:ok, "last Wednesday"}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :quarter
{:ok, "last quarter"}
iex> MyApp.Cldr.DateTime.Relative.to_string -1, unit: :mon, locale: "fr"
{:ok, "lundi dernier"}
iex> MyApp.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
{:error, {Cldr.UnknownTimeUnit,
"Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}}
Interval formats allow for software to format intervals like "Jan 10-12, 2008" as a shorter and more natural format than "Jan 10, 2008 - Jan 12, 2008". They are designed to take a start and end date, time or datetime plus a formatting pattern and use that information to produce a localized format.
An interval is expressed as either a from and to date, time or datetime. Or it can also be a Date.Range or CalendarInterval from the calendar_interval library.
Cldr.Interval.to_string/3 function to format an interval based upon the type of the arguments: date, datetime or time. The modules Cldr.Date.Interval, Cldr.Time.Interval and Cldr.DateTime.Interval also provide a to_string/3 function for when the desired output format is more specific.
Some examples:
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-31], MyApp.Cldr
{:ok, "Jan 1 – Dec 31, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12], MyApp.Cldr
{:ok, "Jan 1 – 12, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12], MyApp.Cldr,
...> format: :long
{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-01], MyApp.Cldr,
...> format: :long, style: :year_and_month
{:ok, "January – December 2020"}
iex> use CalendarInterval
iex> Cldr.Interval.to_string ~I"2020-01-01/12", MyApp.Cldr,
...> format: :long
{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-12-01 10:05:00.0Z], MyApp.Cldr,
...> format: :long
{:ok, "January 1, 2020 at 12:00:00 AM UTC – December 1, 2020 at 10:05:00 AM UTC"}
iex> Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:05:00.0Z], MyApp.Cldr,
...> format: :long
{:ok, "January 1, 2020 at 12:00:00 AM UTC – 10:05:00 AM UTC"}
Although largely complete (with respect to the CLDR data), there are some known limitations as of release 2.0.
v, V, x, X, z, Z, O) not all localisations are performed. Only that data available within a t:DateTime.t/0 struct is used to format timezone data.Elixir
98.7%
Erlang
1.2%