Skip to content

Commit

Permalink
Update changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
kipcole9 committed Jul 6, 2024
2 parents 62d3450 + 1ca6a3a commit a173236
Show file tree
Hide file tree
Showing 34 changed files with 2,823 additions and 1,108 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

**Note that `ex_cldr_dates_times` version 2.18.0 and later are supported on Elixir 1.12 and later only.**

## Cldr_Dates_Times v2.19.0

This is the changelog for Cldr_Dates_Times v2.19.0 released on _____, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr_cldr_dates_times/tags)

### Bug Fixes

* Fix `Cldr.Date.to_string/2` with the option `era: :variant` to correctly render the variant "AD"/"CE"/"BC"/"BCE" text.

* Fix `Cldr.Date.to_string/2` with the option `period: :variant` to correctly render the variant "am"/"pm" text.

### Enhancements

* Adds support for partial dates in `Cldr.Date.to_string/2`. Partial dates are maps with one or more of the fields `:year`, `:month`, `:day` and `:calendar`.

* Adds support for deriving the "best match" format for a date based upon the users requested format or deriving from the available date fields.

* Adds support for formatting using format IDs (atoms that are keys to locale-independent formats) in `Cldr.Date.to_string/2` and `Cldr.Time.to_string/2`. They have been previously supported in `Cldr.DateTime.to_string/2` only.

* Improve the error message if `:hour` is outside the valid range.

## Cldr_Dates_Times v2.18.1

This is the changelog for Cldr_Dates_Times v2.18.1 released on July 1st, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr_cldr_dates_times/tags)
Expand Down
19 changes: 1 addition & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Installation

**Note that `ex_cldr_dates_times` requires Elixir 1.11 or later.**
**Note that `ex_cldr_dates_times` requires Elixir 1.12 or later.**

Add `ex_cldr_dates_time` as a dependency to your `mix` project:

Expand Down Expand Up @@ -52,23 +52,6 @@ A `backend` module is required that is used to host the functions that manage CL
default_backend: MyApp.Cldr
```

### Migration from Cldr.DatesTimes Version 1

1. In modules where there are calls to `Cldr.DateTime.to_string/2` (or the `Date` and `Time` equivalents), add `alias MyApp.Cldr` to the top of the module. That will ensure that calls are directed to the backend with minimal code change. This is the preferred approach.


2. Alternatively, update any calls to `Cldr.Date.to_string/2` to call `Cldr.Date.to_string/3` with the second parameter being a backend module. The same applies for migrating to `Cldr.DateTime.to_string/3`, `Cldr.Time.to_string/3` and `Cldr.DateTime.Relative.to_string/3`. For example:

```elixir
# Change from to_string/2 to to_string/3
# Old version
iex> Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], format: :short

# New version. Note the addition of a backend module as
# the second parameter.
iex> Cldr.DateTime.to_string ~U[2020-05-30 03:52:56Z], MyApp.Cldr, format: :short
```

## Usage Introduction

`ex_cldr_dates_times` is an addon library application for [ex_cldr](https://hex.pm/packages/ex_cldr) that provides localisation and formatting for dates, times and date_times.
Expand Down
3 changes: 1 addition & 2 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ config :ex_cldr,
default_locale: "en",
default_backend: MyApp.Cldr

config :elixir,
:time_zone_database, Tz.TimeZoneDatabase
config :elixir, :time_zone_database, Tz.TimeZoneDatabase
1 change: 0 additions & 1 deletion config/release.exs
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

298 changes: 194 additions & 104 deletions lib/cldr/backend/date_time.ex

Large diffs are not rendered by default.

204 changes: 191 additions & 13 deletions lib/cldr/backend/format.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,50 @@ defmodule Cldr.DateTime.Format.Backend do

@standard_formats [:short, :medium, :long, :full]

@doc "A struct of the format types and formats"
@date_symbols [
"Y",
"y",
"G",
"M",
"L",
"D",
"d",
"U",
"u",
"Q",
"q",
"F",
"g",
"W",
"w",
"E",
"e",
"c"
]

@time_symbols [
"H",
"h",
"K",
"k",
"C",
"m",
"s",
"S",
"A",
"Z",
"z",
"V",
"v",
"X",
"x",
"O"
]

@doc "A struct from a format id as an atom to a format string"
@type formats :: map()

@doc "The CLDR calendar type as an atome"
@doc "The CLDR calendar type as an atom"
@type calendar :: atom()

@doc """
Expand Down Expand Up @@ -192,7 +232,7 @@ defmodule Cldr.DateTime.Format.Backend do
"""
@spec date_time_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
{:ok, map()} | {:error, {module(), String.t()}}

def date_time_formats(
locale \\ unquote(backend).get_locale(),
Expand Down Expand Up @@ -245,7 +285,7 @@ defmodule Cldr.DateTime.Format.Backend do
"""
@spec date_time_at_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
{:ok, map()} | {:error, {module(), String.t()}}

def date_time_at_formats(
locale \\ unquote(backend).get_locale(),
Expand All @@ -263,7 +303,7 @@ defmodule Cldr.DateTime.Format.Backend do
end

@doc """
Returns a map of the available non-standard datetime formats for a
Returns a map of the available datetime formats for a
given locale and calendar.
## Arguments
Expand Down Expand Up @@ -356,6 +396,97 @@ defmodule Cldr.DateTime.Format.Backend do
end
end

@doc """
Returns a map of the available date formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_available_formats "en"
"""
@spec date_available_formats(Locale.locale_reference(), calendar) :: {:ok, formats}
def date_available_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)

def date_available_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_available_formats(cldr_locale_name, calendar)
end

def date_available_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_available_formats(locale, calendar)
end
end

@doc """
Returns a map of the available time formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.time_available_formats "en"
"""
@spec time_available_formats(Locale.locale_reference(), calendar) :: {:ok, formats}
def time_available_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)

def time_available_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
time_available_formats(cldr_locale_name, calendar)
end

def time_available_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_available_formats(locale, calendar)
end
end

@doc false
def date_time_available_format_tokens(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)

def date_time_available_format_tokens(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_time_available_format_tokens(cldr_locale_name, calendar)
end

def date_time_available_format_tokens(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_available_format_tokens(locale, calendar)
end
end

@doc """
Returns a map of the interval formats for a
given locale and calendar.
Expand Down Expand Up @@ -602,7 +733,7 @@ defmodule Cldr.DateTime.Format.Backend do
"""
@spec gmt_zero_format(Locale.locale_reference()) ::
{:ok, String.t()} | {:error, {module(), String.t()}}
{:ok, String.t()} | {:error, {module(), String.t()}}

def gmt_zero_format(locale \\ unquote(backend).get_locale())

Expand Down Expand Up @@ -687,9 +818,10 @@ defmodule Cldr.DateTime.Format.Backend do
|> get_in([:date_time_formats, :available_formats])
|> Enum.map(fn
{name, %{other: _other} = plurals} ->
{:ok, tokens, _} = Cldr.DateTime.Compiler.tokenize(to_string(name))
{:ok, tokens, _} = Cldr.DateTime.Format.Compiler.tokenize(to_string(name))
[{pluralize, _, _} | _rest] = Enum.reverse(tokens)
{name, Map.put(plurals, :pluralize, pluralize)}

other ->
other
end)
Expand All @@ -699,16 +831,58 @@ defmodule Cldr.DateTime.Format.Backend do
{:ok, unquote(Macro.escape(available_formats))}
end

formats = get_in(calendar_data, [:date_time_formats, :interval_formats])
date_available_formats =
Enum.filter(available_formats, fn {format_id, _} ->
remaining =
format_id
|> to_string()
|> String.replace(@date_symbols, "")

remaining == ""
end)
|> Map.new()

def date_available_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(date_available_formats))}
end

time_available_formats =
Enum.filter(available_formats, fn {format_id, _} ->
remaining =
format_id
|> to_string()
|> String.replace(@time_symbols, "")

remaining == ""
end)
|> Map.new()

def time_available_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(time_available_formats))}
end

available_format_tokens =
Enum.map(available_formats, fn {format_id, format} ->
{:ok, tokens} = Cldr.DateTime.Format.Compiler.tokenize_skeleton(format_id)
{format_id, tokens}
end)
|> Map.new()

def date_time_available_format_tokens(unquote(locale), unquote(calendar)) do
unquote(Macro.escape(available_format_tokens))
end

interval_formats =
get_in(calendar_data, [:date_time_formats, :interval_formats])

interval_format_fallback =
get_in(
calendar_data,
[:date_time_formats, :interval_formats, :interval_format_fallback]
)

formats =
formats
interval_formats =
interval_formats
|> Map.delete(:interval_format_fallback)
|> Enum.map(fn {k, v} ->
split_formats =
Expand All @@ -723,7 +897,7 @@ defmodule Cldr.DateTime.Format.Backend do
|> Map.new()

def date_time_interval_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(formats))}
{:ok, unquote(Macro.escape(interval_formats))}
end

def date_time_interval_fallback(unquote(locale), unquote(calendar)) do
Expand Down Expand Up @@ -802,7 +976,10 @@ defmodule Cldr.DateTime.Format.Backend do
:evening1
"""
@spec day_period_for(Elixir.Calendar.time(), LanguageTag.t() | String.t() | Locale.locale_name()) ::
@spec day_period_for(
Elixir.Calendar.time(),
LanguageTag.t() | String.t() | Locale.locale_name()
) ::
atom
def day_period_for(time, language)

Expand Down Expand Up @@ -831,7 +1008,8 @@ defmodule Cldr.DateTime.Format.Backend do
false
"""
@spec language_has_noon_and_midnight?(LanguageTag.t() | String.t() | Locale.locale_name()) :: boolean
@spec language_has_noon_and_midnight?(LanguageTag.t() | String.t() | Locale.locale_name()) ::
boolean
def language_has_noon_and_midnight?(locale)

def language_has_noon_and_midnight?(%LanguageTag{language: language}) do
Expand Down
Loading

0 comments on commit a173236

Please sign in to comment.