Cldr.DateTime.Format.Match (Cldr Dates & Times v2.25.0)

View Source

Implements best match for a requested skeleton to an available format ID.

A “best match” from requested skeleton to the id portion of a Cldr.DateTime.Format.date_time_available_formats/3 map is found using a closest distance match as follows:

Matching process

  • Skeleton symbols requesting a best choice for the locale are replaced. This allows a user to specify a desired hour cycle in the locale using the -u-hc option and to use the j and C fields in the skeleton itself. For example:

    j → one of {H, k, h, K}; C → one of {a, b, B}

  • For skeleton and id fields with symbols representing the same type (year, month, day, etc), calculate a distance from the desired field to the available field:

    • Most symbols have a small distance from each other. For example:

      M ≅ L; E ≅ c; a ≅ b ≅ B; H ≅ k ≅ h ≅ K; ...

    • Width differences among fields, other than those marking text vs numeric, are given small distance from each other. For example:

      MMM ≅ MMMM MM ≅ M

    • Numeric and text fields are given a larger distance from each other. For example:

      MMM ≈ MM

    • Symbols representing substantial differences (week of year vs week of month) are given a much larger distance from each other.

  • [Stated in the spec, not currently implemented] A requested skeleton that includes both seconds and fractional seconds (e.g. “mmssSSS”) is allowed to match a dateFormatItem skeleton that includes seconds but not fractional seconds (e.g. “ms”). In this case the requested sequence of ‘S’ characters (or its length) should be retained separately and used when adjusting the pattern.

  • Otherwise, missing or extra fields between requested skeleton and id cause a match to fail. In those cases, an attempt is made to separate the skeleton into separate time skeletons and date skeletons and an attempt is made to best match each of them independently.

  • See the specification for further information.

Deviations from the specification

Some additional steps post matching are described in the specification that are not currently implemented in this library. The relevant sections are reproduced here:

Once a best match is found between requested skeleton and dateFormatItem id, the corresponding dateFormatItem pattern is used, but with adjustments primarily to make the pattern field lengths match the skeleton field lengths. However, the pattern field lengths should not be matched in some cases:

  • When the best-match dateFormatItem has an alphabetic field (such as MMM or MMMM) that corresponds to a numeric field in the pattern (such as M or MM), that numeric field in the pattern should not be adjusted to match the skeleton length, and vice versa; i.e. adjustments should never convert a numeric element in the pattern to an alphabetic element, or the opposite. See the second set of examples below.

  • When the pattern field corresponds to an availableFormats skeleton with a field length that matches the field length in the requested skeleton, the pattern field length should not be adjusted.

  • Pattern field lengths for hour, minute, and second should by default not be adjusted to match the requested field length (i.e. locale data takes priority). However APIs that map skeletons to patterns should provide the option to override this behavior for cases when a client really does want to force a specific pattern field length.

Summary

Functions

best_match(original_skeleton, locale \\ Cldr.get_locale(), calendar \\ Cldr.Calendar.default_cldr_calendar(), backend \\ Cldr.Date.default_backend())

(since 2.19.0)

Find the best match format ID for a requested skeleton.

Arguments

Returns

  • {:ok, format_id} or

  • {:ok, {date_format_id, time_format_id}}

  • {:error, reason}.

Examples

iex> Cldr.DateTime.Format.Match.best_match("hms", "en", :gregorian, MyApp.Cldr)
{:ok, :hms}

iex> Cldr.DateTime.Format.Match.best_match("yMdhms", "en", :gregorian, MyApp.Cldr)
{:ok, {:yMd, :hms}}

iex> Cldr.DateTime.Format.Match.best_match("EMdyv", "en", :gregorian, MyApp.Cldr)
{:error,
 {Cldr.DateTime.UnresolvedFormat, "No available format resolved for \"EMdyv\""}}

different_but_compatible(token_a, token_b)

(macro)

different_types(token_a, token_b)

(macro)

same_types(token_a, token_b)

(macro)