# `Cldr.DateTime.Format.Match`
[🔗](https://github.com/elixir-cldr/cldr_dates_times/blob/v2.25.6/lib/cldr/format/match.ex#L1)

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](https://www.unicode.org/reports/tr35/tr35-dates.html#Matching_Skeletons)
  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.

# `best_match`
*since 2.19.0* 

```elixir
@spec best_match(
  skeleton :: Cldr.DateTime.Format.format_skeleton() | String.t(),
  locale :: Cldr.Locale.locale_reference(),
  calendar :: Cldr.Calendar.calendar(),
  backend :: Cldr.backend()
) ::
  {:ok, Cldr.DateTime.Format.format_id()}
  | {:ok, {Cldr.DateTime.Format.format_id(), Cldr.DateTime.Format.format_id()}}
  | {:error, {module(), String.t()}}
```

Find the best match format ID for a requested skeleton.

### Arguments

* `skeleton` is a string or atom composed of format fields.

* `locale` is any valid locale name returned by `Cldr.known_locale_names/0`
  or a `t:Cldr.LanguageTag.t/0` struct. The default is `Cldr.get_locale/0`.
  The default is `Cldr.get_locale/0`.

* `calendar` is any CLDR calendar type. The default is `:gregorian`.
  See `Cldr.DateTime.Format.calendars_for/1` for the available calendars.

### 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`
*macro* 

# `different_types`
*macro* 

# `same_types`
*macro* 

---

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