Skip to content

Commit

Permalink
Interval formats may have variants
Browse files Browse the repository at this point in the history
  • Loading branch information
kipcole9 committed Jul 24, 2024
1 parent d46e34d commit 1c917f6
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 37 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

**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.3

This is the changelog for Cldr_Dates_Times v2.19.3 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.Time.available_formats/3` when the locale parameter is a binary.

### Enhancements

* Modify the `:prefer` option of `to_string/2` to take a list of preferences. Time formats may sometimes have a `:unicode` or `:ascii` preference. Date formats may have a `:default` or `:variant` preference. The `:prefer` option can no be specified with one or both of these options.

## Cldr_Dates_Times v2.19.2

This is the changelog for Cldr_Dates_Times v2.19.2 released on July 9th, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr_cldr_dates_times/tags)
Expand All @@ -16,7 +28,7 @@ This is the changelog for Cldr_Dates_Times v2.19.1 released on July 8th, 2024.

### Bug Fixes

* Include `:skeleton_tokenizer.xrl` to the hex package definition.
* Include `:skeleton_tokenizer.xrl` to the hex package definition.

## Cldr_Dates_Times v2.19.0

Expand Down
4 changes: 2 additions & 2 deletions lib/cldr/backend/format.ex
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ defmodule Cldr.DateTime.Format.Backend do
## Examples:
iex> #{inspect(__MODULE__)}.time_available_formats "en"
iex> #{inspect(__MODULE__)}.time_available_formats :en
"""
@spec time_available_formats(Locale.locale_reference(), calendar) :: {:ok, formats}
Expand All @@ -464,7 +464,7 @@ defmodule Cldr.DateTime.Format.Backend do

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)
time_available_formats(locale, calendar)
end
end

Expand Down
21 changes: 12 additions & 9 deletions lib/cldr/date.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule Cldr.Date do
alias Cldr.Locale

import Cldr.DateTime,
only: [resolve_plural_format: 4, apply_unicode_or_ascii_preference: 2]
only: [resolve_plural_format: 4, apply_preference: 2]

@format_types [:short, :medium, :long, :full]
@default_format_type :medium
Expand Down Expand Up @@ -148,12 +148,13 @@ defmodule Cldr.Date do

locale = options.locale
format = options.format
prefer = List.wrap(options.prefer)

with {:ok, locale} <- Cldr.validate_locale(locale, backend),
{:ok, cldr_calendar} <- Cldr.DateTime.type_from_calendar(calendar),
{:ok, _} <- Cldr.Number.validate_number_system(locale, number_system, backend),
{:ok, format} <- find_format(date, format, locale, cldr_calendar, backend),
{:ok, format} <- apply_unicode_or_ascii_preference(format, options.prefer),
{:ok, format} <- apply_preference(format, prefer),
{:ok, format_string} <- resolve_plural_format(format, date, backend, options) do
format_backend.format(date, format_string, locale, options)
end
Expand Down Expand Up @@ -260,18 +261,19 @@ defmodule Cldr.Date do
defp normalize_options(date, backend, []) do
{locale, _backend} = Cldr.locale_and_backend_from(nil, backend)
number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
format = format_from_options(date, nil, @default_format_type)
prefer = List.wrap(@default_prefer)
format = format_from_options(date, nil, @default_format_type, prefer)

%{locale: locale, number_system: number_system, format: format, prefer: @default_prefer}
%{locale: locale, number_system: number_system, format: format, prefer: prefer}
end

defp normalize_options(date, backend, options) do
{locale, _backend} = Cldr.locale_and_backend_from(options[:locale], backend)
locale_number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
number_system = Keyword.get(options, :number_system, locale_number_system)
prefer = options[:prefer] || @default_prefer
prefer = Keyword.get(options, :prefer, @default_prefer) |> List.wrap()
format_option = options[:date_format] || options[:format] || options[:style]
format = format_from_options(date, format_option, @default_format_type)
format = format_from_options(date, format_option, @default_format_type, prefer)

options
|> Keyword.put(:locale, locale)
Expand All @@ -283,17 +285,18 @@ defmodule Cldr.Date do
end

# Full date, no option, use the default format
defp format_from_options(date, nil, default_format) when is_full_date(date) do
defp format_from_options(date, nil, default_format, _prefer) when is_full_date(date) do
default_format
end

# Partial date, no option, derive the format from the date
defp format_from_options(date, nil, _default_format) do
defp format_from_options(date, nil, _default_format, _prefer) do
derive_format_id(date)
end

# If a format is requested, use it
defp format_from_options(_date, format, _default_format) do
defp format_from_options(_time, format, _default_format, prefer) do
{:ok, format} = apply_preference(format, prefer)
format
end

Expand Down
26 changes: 17 additions & 9 deletions lib/cldr/date_time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ defmodule Cldr.DateTime do
{:ok, _} <- Cldr.Number.validate_number_system(locale, options.number_system, backend),
{:ok, format, options} <-
find_format(datetime, options.format, locale, cldr_calendar, backend, options),
{:ok, format} <- apply_unicode_or_ascii_preference(format, options.prefer),
{:ok, format} <- apply_preference(format, options.prefer),
{:ok, format_string} <- resolve_plural_format(format, datetime, backend, options) do
format_backend.format(datetime, format_string, locale, options)
end
Expand Down Expand Up @@ -486,7 +486,7 @@ defmodule Cldr.DateTime do
date_format: date_format,
time_format: time_format,
style: @default_style,
prefer: @default_prefer
prefer: [@default_prefer]
}

{:ok, datetime, options}
Expand All @@ -499,7 +499,7 @@ defmodule Cldr.DateTime do
datetime = Map.put_new(datetime, :calendar, calendar)

style = options[:style] || @default_style
prefer = options[:prefer] || @default_prefer
prefer = Keyword.get(options, :prefer, @default_prefer) |> List.wrap()

format = options[:format]
date_format = options[:date_format]
Expand Down Expand Up @@ -790,7 +790,7 @@ defmodule Cldr.DateTime do
defp preferred_format(formats, format, prefer) do
case Map.fetch(formats, format) do
{:ok, format} ->
apply_unicode_or_ascii_preference(format, prefer)
apply_preference(format, prefer)

:error ->
{:error,
Expand All @@ -801,15 +801,23 @@ defmodule Cldr.DateTime do
end

@doc false
def apply_unicode_or_ascii_preference(%{unicode: _unicode, ascii: ascii}, :ascii) do
{:ok, ascii}
def apply_preference(%{unicode: unicode, ascii: ascii}, preference) do
if :ascii in preference do
{:ok, ascii}
else
{:ok, unicode}
end
end

def apply_unicode_or_ascii_preference(%{unicode: unicode, ascii: _ascii}, _) do
{:ok, unicode}
def apply_preference(%{default: default, variant: variant}, preference) do
if :variant in preference do
{:ok, variant}
else
{:ok, default}
end
end

def apply_unicode_or_ascii_preference(format, _) do
def apply_preference(format, _) do
{:ok, format}
end

Expand Down
12 changes: 11 additions & 1 deletion lib/cldr/format/date_time_format.ex
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ defmodule Cldr.DateTime.Format do
def format_list(config) do
locale_names = Cldr.Locale.Loader.known_locale_names(config)
backend = config.backend

((known_formats(&all_date_formats(&1, backend), locale_names) ++
known_formats(&all_time_formats(&1, backend), locale_names) ++
known_formats(&all_date_time_formats(&1, backend), locale_names) ++
Expand All @@ -69,6 +68,7 @@ defmodule Cldr.DateTime.Format do
defp precompile_interval_formats(config) do
config.precompile_interval_formats
|> Enum.flat_map(&split_interval!/1)
|> List.flatten()
end

@doc """
Expand Down Expand Up @@ -622,6 +622,10 @@ defmodule Cldr.DateTime.Format do
|> Map.values()
|> Enum.filter(&is_map/1)
|> Enum.flat_map(&Map.values/1)
|> Enum.map(fn
%{default: default, variant: variant} -> [default, variant]
other -> other
end)
end)
|> List.flatten()
|> Enum.uniq()
Expand Down Expand Up @@ -937,6 +941,12 @@ defmodule Cldr.DateTime.Format do
{Cldr.DateTime.IntervalFormatError, "Invalid datetime interval format #{inspect(left)}"}}
end

# Handle default/variant maps

defp do_split_interval(%{default: default, variant: variant}, _acc, _left) do
%{default: do_split_interval(default, [], ""), variant: do_split_interval(variant, [], "")}
end

# Quoted strings pass through. This assumes the quotes
# are correctly closed.

Expand Down
6 changes: 5 additions & 1 deletion lib/cldr/interval/date.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Cldr.Date.Interval do
"""
alias Cldr.DateTime.Format
import Cldr.Calendar, only: [date: 0]
import Cldr.DateTime, only: [apply_preference: 2]

# Date styles not defined
# by a grouping but can still
Expand Down Expand Up @@ -64,6 +65,7 @@ defmodule Cldr.Date.Interval do

@default_format :medium
@default_style :date
@default_prefer :default

def styles do
@style_map
Expand Down Expand Up @@ -384,6 +386,7 @@ defmodule Cldr.Date.Interval do
format = Keyword.get(options, :format, @default_format)
locale_number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
number_system = Keyword.get(options, :number_system, locale_number_system)
prefer = Keyword.get(options, :prefer, @default_prefer) |> List.wrap()

options =
options
Expand All @@ -396,7 +399,8 @@ defmodule Cldr.Date.Interval do
{:ok, _} <- Cldr.Number.validate_number_system(locale, number_system, backend),
{:ok, calendar} <- Cldr.Calendar.validate_calendar(from.calendar),
{:ok, formats} <- Format.interval_formats(locale, calendar.cldr_calendar_type(), backend),
{:ok, [left, right]} <- resolve_format(from, to, formats, options),
{:ok, format} <- resolve_format(from, to, formats, options),
{:ok, [left, right]} <- apply_preference(format, prefer),
{:ok, left_format} <- formatter.format(from, left, locale, options),
{:ok, right_format} <- formatter.format(to, right, locale, options) do
{:ok, left_format <> right_format}
Expand Down
6 changes: 5 additions & 1 deletion lib/cldr/interval/time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Cldr.Time.Interval do
"""

alias Cldr.DateTime.Format
import Cldr.DateTime, only: [apply_preference: 2]

import Cldr.Date.Interval,
only: [
Expand Down Expand Up @@ -78,6 +79,7 @@ defmodule Cldr.Time.Interval do

@default_format :medium
@default_style :time
@default_prefer :default

def styles do
@style_map
Expand Down Expand Up @@ -240,6 +242,7 @@ defmodule Cldr.Time.Interval do
format = Keyword.get(options, :format, @default_format)
locale_number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
number_system = Keyword.get(options, :number_system, locale_number_system)
prefer = Keyword.get(options, :prefer, @default_prefer)

options =
options
Expand All @@ -251,7 +254,8 @@ defmodule Cldr.Time.Interval do
{:ok, _} <- Cldr.Number.validate_number_system(locale, number_system, backend),
{:ok, calendar} <- Cldr.Calendar.validate_calendar(from.calendar),
{:ok, formats} <- Format.interval_formats(locale, calendar.cldr_calendar_type(), backend),
{:ok, [left, right]} <- resolve_format(from, to, formats, locale, options),
{:ok, format} <- resolve_format(from, to, formats, locale, options),
{:ok, [left, right]} <- apply_preference(format, prefer),
{:ok, left_format} <- formatter.format(from, left, locale, options),
{:ok, right_format} <- formatter.format(to, right, locale, options) do
{:ok, left_format <> right_format}
Expand Down
14 changes: 8 additions & 6 deletions lib/cldr/time.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule Cldr.Time do
alias Cldr.Locale

import Cldr.DateTime,
only: [resolve_plural_format: 4, apply_unicode_or_ascii_preference: 2]
only: [resolve_plural_format: 4, apply_preference: 2]

@format_types [:short, :medium, :long, :full]
@default_format_type :medium
Expand Down Expand Up @@ -155,12 +155,13 @@ defmodule Cldr.Time do

locale = options.locale
format = options.format
prefer = List.wrap(options.prefer)

with {:ok, locale} <- Cldr.validate_locale(locale, backend),
{:ok, cldr_calendar} <- Cldr.DateTime.type_from_calendar(calendar),
{:ok, _} <- Cldr.Number.validate_number_system(locale, number_system, backend),
{:ok, format} <- find_format(time, format, locale, cldr_calendar, backend),
{:ok, format} <- apply_unicode_or_ascii_preference(format, options.prefer),
{:ok, format} <- apply_preference(format, prefer),
{:ok, format_string} <- resolve_plural_format(format, time, backend, options) do
format_backend.format(time, format_string, locale, options)
end
Expand Down Expand Up @@ -265,16 +266,17 @@ defmodule Cldr.Time do
defp normalize_options(time, backend, []) do
{locale, _backend} = Cldr.locale_and_backend_from(nil, backend)
number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
format = format_from_options(time, nil, @default_format_type, @default_prefer)
default_prefer = List.wrap(@default_prefer)
format = format_from_options(time, nil, @default_format_type, default_prefer)

%{locale: locale, number_system: number_system, format: format, prefer: @default_prefer}
%{locale: locale, number_system: number_system, format: format, prefer: default_prefer}
end

defp normalize_options(time, backend, options) do
{locale, _backend} = Cldr.locale_and_backend_from(options[:locale], backend)
locale_number_system = Cldr.Number.System.number_system_from_locale(locale, backend)
number_system = Keyword.get(options, :number_system, locale_number_system)
prefer = Keyword.get(options, :prefer, @default_prefer)
prefer = Keyword.get(options, :prefer, @default_prefer) |> List.wrap()
format_option = options[:time_format] || options[:format] || options[:style]
format = format_from_options(time, format_option, @default_format_type, prefer)

Expand All @@ -299,7 +301,7 @@ defmodule Cldr.Time do

# If a format is requested, use it
defp format_from_options(_time, format, _default_format, prefer) do
{:ok, format} = apply_unicode_or_ascii_preference(format, prefer)
{:ok, format} = apply_preference(format, prefer)
format
end

Expand Down
2 changes: 2 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ defmodule Cldr.DatesTimes.Mixfile do

defp deps do
[
{:ex_cldr, path: "../cldr", override: true},

{:ex_cldr_calendars, "~> 1.25"},
{:calendar_interval, "~> 0.2", optional: true},
{:ex_doc, "~> 0.25", optional: true, only: [:dev, :release], runtime: false},
Expand Down
Loading

0 comments on commit 1c917f6

Please sign in to comment.