From 97760114cc4a533db0f697143fc57e666f6b1d56 Mon Sep 17 00:00:00 2001 From: Kip Cole Date: Sat, 31 Aug 2019 14:21:05 +0800 Subject: [PATCH] Return error tuple immediate if a format can't be fulfilled --- CHANGELOG.md | 12 +++++ lib/cldr/date.ex | 13 ++++- lib/cldr/datetime.ex | 15 ++++-- lib/cldr/datetime/exception.ex | 12 +++++ lib/cldr/datetime/relative.ex | 78 ++++++++++++++++----------- lib/cldr/format/datetime_formatter.ex | 30 +++++++++-- lib/cldr/time.ex | 15 ++++-- mix.exs | 15 +++--- mix.lock | 6 +-- test/exceptions_test.exs | 13 +++-- 10 files changed, 151 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60381a5..8763dfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# Changelog for Cldr_Dates_Times v2.2.2 + +This is the changelog for Cldr_Dates_Times v2.2.2 released on August 31st, 2019. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr_dates_times/tags) + +### Changes & Deprecations + +* Deprecates the option `:format` on `Cldr.DateTime.Relative.to_string/3` in favour of `:style`. `:format` will be removed with `ex_cldr_dates_times` version 3.0 + +### Bug Fixes + +* Return an error tuple immediately when a format code is used but no data is available to fulfill it + # Changelog for Cldr_Dates_Times v2.2.1 This is the changelog for Cldr_Dates_Times v2.2.1 released on August 23rd, 2019. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-cldr/cldr_dates_times/tags) diff --git a/lib/cldr/date.ex b/lib/cldr/date.ex index 6800f0d..e5cf34d 100644 --- a/lib/cldr/date.ex +++ b/lib/cldr/date.ex @@ -78,7 +78,8 @@ defmodule Cldr.Date do {:ok, "10 Julie 2017"} """ - @spec to_string(map, Cldr.backend() | Keyword.t(), Keyword.t()) :: {:ok, String.t()} | {:error, {module, String.t()}} + @spec to_string(map, Cldr.backend() | Keyword.t(), Keyword.t()) :: + {:ok, String.t()} | {:error, {module, String.t()}} def to_string(date, backend \\ Cldr.default_backend(), options \\ []) @@ -103,6 +104,9 @@ defmodule Cldr.Date do else {:error, reason} -> {:error, reason} end + rescue + e in [Cldr.DateTime.UnresolvedFormat] -> + {:error, {e.__struct__, e.message}} end def to_string(date, _backend, _options) do @@ -200,9 +204,14 @@ defmodule Cldr.Date do end defp error_return(map, requirements) do + requirements = + requirements + |> Enum.map(&inspect/1) + |> Cldr.DateTime.Formatter.join_requirements() + {:error, {ArgumentError, - "Invalid date. Date is a map that requires at least #{inspect(requirements)} fields. " <> + "Invalid date. Date is a map that contains at least #{requirements}. " <> "Found: #{inspect(map)}"}} end end diff --git a/lib/cldr/datetime.ex b/lib/cldr/datetime.ex index 01b98cc..80a4f33 100644 --- a/lib/cldr/datetime.ex +++ b/lib/cldr/datetime.ex @@ -83,7 +83,8 @@ defmodule Cldr.DateTime do {:ok, "samedi 1 janvier 2000 à 23:59:59 UTC"} """ - @spec to_string(map, Cldr.backend() | Keyword.t(), Keyword.t()) :: {:ok, String.t()} | {:error, {module, String.t()}} + @spec to_string(map, Cldr.backend() | Keyword.t(), Keyword.t()) :: + {:ok, String.t()} | {:error, {module, String.t()}} def to_string(datetime, backend \\ Cldr.default_backend(), options \\ []) @@ -106,9 +107,10 @@ defmodule Cldr.DateTime do {:ok, format_string} <- format_string(options[:format], locale, cldr_calendar, backend), {:ok, formatted} <- format_backend.format(datetime, format_string, locale, options) do {:ok, formatted} - else - {:error, reason} -> {:error, reason} end + rescue + e in [Cldr.DateTime.UnresolvedFormat] -> + {:error, {e.__struct__, e.message}} end def to_string(datetime, _backend, _options) do @@ -230,9 +232,14 @@ defmodule Cldr.DateTime do end defp error_return(map, requirements) do + requirements = + requirements + |> Enum.map(&inspect/1) + |> Cldr.DateTime.Formatter.join_requirements() + {:error, {ArgumentError, - "Invalid date_time. Date_time is a map that requires at least #{inspect(requirements)} fields. " <> + "Invalid DateTime. DateTime is a map that contains at least #{requirements}. " <> "Found: #{inspect(map)}"}} end end diff --git a/lib/cldr/datetime/exception.ex b/lib/cldr/datetime/exception.ex index 2166538..2770a49 100644 --- a/lib/cldr/datetime/exception.ex +++ b/lib/cldr/datetime/exception.ex @@ -20,3 +20,15 @@ defmodule Cldr.DateTime.Compiler.ParseError do %__MODULE__{message: message} end end + +defmodule Cldr.DateTime.UnresolvedFormat do + @moduledoc """ + Exception raised when formatting and there is no + data for the given format. + """ + defexception [:message] + + def exception(message) do + %__MODULE__{message: message} + end +end diff --git a/lib/cldr/datetime/relative.ex b/lib/cldr/datetime/relative.ex index 42582d7..7ae517b 100644 --- a/lib/cldr/datetime/relative.ex +++ b/lib/cldr/datetime/relative.ex @@ -28,7 +28,7 @@ defmodule Cldr.DateTime.Relative do @other_units [:mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter] @unit_keys Map.keys(@unit) ++ @other_units - @known_formats [:default, :narrow, :short] + @known_styles [:default, :narrow, :short] @doc """ Returns a `{:ok, string}` representing a relative time (ago, in) for a given @@ -47,7 +47,7 @@ defmodule Cldr.DateTime.Relative do * `:locale` is the locale in which the binary is formatted. The default is `Cldr.get_locale/0` - * `:format` is the format of the binary. Format may be `:default`, `:narrow` or `:short` + * `:style` is the style of the binary. Style may be `:default`, `:narrow` or `:short` * `:unit` is the time unit for the formatting. The allowable units are `:second`, `:minute`, `:hour`, `:day`, `:week`, `:month`, `:year`, `:mon`, `:tue`, `:wed`, `:thu`, `:fri`, `:sat`, @@ -77,7 +77,7 @@ defmodule Cldr.DateTime.Relative do iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day, locale: "fr") {:ok, "demain"} - iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day, format: :narrow) + iex> Cldr.DateTime.Relative.to_string(1, MyApp.Cldr, unit: :day, style: :narrow) {:ok, "tomorrow"} iex> Cldr.DateTime.Relative.to_string(1234, MyApp.Cldr, unit: :year) @@ -92,19 +92,19 @@ defmodule Cldr.DateTime.Relative do iex> Cldr.DateTime.Relative.to_string(~D[2017-04-29], MyApp.Cldr, relative_to: ~D[2017-04-26]) {:ok, "in 3 days"} - iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, format: :short, locale: "fr") + iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, style: :short, locale: "fr") {:ok, "dans 5 min"} - iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, format: :narrow, locale: "fr") + iex> Cldr.DateTime.Relative.to_string(310, MyApp.Cldr, style: :narrow, locale: "fr") {:ok, "+5 min"} - iex> Cldr.DateTime.Relative.to_string 2, MyApp.Cldr, unit: :wed, format: :short, locale: "en" + iex> Cldr.DateTime.Relative.to_string 2, MyApp.Cldr, unit: :wed, style: :short, locale: "en" {:ok, "in 2 Wed."} - iex> Cldr.DateTime.Relative.to_string 1, MyApp.Cldr, unit: :wed, format: :short + iex> Cldr.DateTime.Relative.to_string 1, MyApp.Cldr, unit: :wed, style: :short {:ok, "next Wed."} - iex> Cldr.DateTime.Relative.to_string -1, MyApp.Cldr, unit: :wed, format: :short + iex> Cldr.DateTime.Relative.to_string -1, MyApp.Cldr, unit: :wed, style: :short {:ok, "last Wed."} iex> Cldr.DateTime.Relative.to_string -1, MyApp.Cldr, unit: :wed @@ -121,6 +121,9 @@ defmodule Cldr.DateTime.Relative do "Unknown time unit :ziggeraut. Valid time units are [:day, :hour, :minute, :month, :second, :week, :year, :mon, :tue, :wed, :thu, :fri, :sat, :sun, :quarter]"}} """ + + # TODO deprecate the option :format in favour of using :style in version 3.9 + @spec to_string(integer | float | Date.t() | DateTime.t(), Cldr.backend(), Keyword.t()) :: {:ok, String.t()} | {:error, {module, String.t()}} @@ -137,7 +140,7 @@ defmodule Cldr.DateTime.Relative do with {:ok, locale} <- Cldr.validate_locale(locale), {:ok, unit} <- validate_unit(unit), - {:ok, _format} <- validate_format(options[:format]) do + {:ok, _style} <- validate_style(options[:style] || options[:format]) do {relative, unit} = define_unit_and_relative_time(relative, unit, options[:relative_to]) string = to_string(relative, unit, locale, backend, options) {:ok, string} @@ -145,15 +148,17 @@ defmodule Cldr.DateTime.Relative do end defp default_options do - [locale: Cldr.get_locale(), format: :default] + [locale: Cldr.get_locale(), style: :default] end + # No unit or relative_to is specified so we derive them defp define_unit_and_relative_time(relative, nil, nil) when is_number(relative) do unit = unit_from_relative_time(relative) relative = scale_relative(relative, unit) {relative, unit} end + # Take two datetimes and calculate the seconds between them defp define_unit_and_relative_time( %{year: _, month: _, day: _, hour: _, minute: _, second: _, calendar: Calendar.ISO} = relative, @@ -166,6 +171,7 @@ defmodule Cldr.DateTime.Relative do define_unit_and_relative_time(relative_time, unit, nil) end + # Take two dates and calculate the days between them defp define_unit_and_relative_time( %{year: _, month: _, day: _, calendar: Calendar.ISO} = relative, unit, @@ -187,6 +193,7 @@ defmodule Cldr.DateTime.Relative do define_unit_and_relative_time(relative_time, unit, nil) end + # Anything else just return the values defp define_unit_and_relative_time(relative_time, unit, _relative_to) do {relative_time, unit} end @@ -210,7 +217,7 @@ defmodule Cldr.DateTime.Relative do * `:locale` is the locale in which the binary is formatted. The default is `Cldr.get_locale/0` - * `:format` is the format of the binary. Format may be `:default`, `:narrow` or `:short`. + * `:style` is the format of the binary. Style may be `:default`, `:narrow` or `:short`. The default is `:default` * `:unit` is the time unit for the formatting. The allowable units are `:second`, `:minute`, @@ -240,26 +247,34 @@ defmodule Cldr.DateTime.Relative do @spec to_string(integer | float, atom(), Cldr.LanguageTag.t(), Cldr.backend(), Keyword.t()) :: String.t() + defp to_string(relative, unit, locale, backend, options) + # For the case when its relative by one unit, for example "tomorrow" or "yesterday" + # or "last" defp to_string(relative, unit, locale, backend, options) when relative in -1..1 do + style = options[:style] || options[:format] + result = locale |> get_locale(backend) - |> get_in([unit, options[:format], :relative_ordinal]) + |> get_in([unit, style, :relative_ordinal]) |> Enum.at(relative + 1) if is_nil(result), do: to_string(relative / 1, unit, locale, backend, options), else: result end + # For the case when its more than one unit away. For example, "in 3 days" + # or "2 days ago" defp to_string(relative, unit, locale, backend, options) when is_float(relative) or is_integer(relative) do direction = if relative > 0, do: :relative_future, else: :relative_past + style = options[:style] || options[:format] rules = locale |> get_locale(backend) - |> get_in([unit, options[:format], direction]) + |> get_in([unit, style, direction]) rule = Module.concat(backend, Number.Cardinal).pluralize(trunc(relative), locale, rules) @@ -270,24 +285,25 @@ defmodule Cldr.DateTime.Relative do |> Enum.join() end - defp to_string(span, unit, locale, backend, options) do - do_to_string(span, unit, locale, backend, options) - end - - defp do_to_string(seconds, unit, locale, backend, options) do - seconds - |> scale_relative(unit) - |> to_string(unit, locale, backend, options) - end + # For all other cases + # defp to_string(span, unit, locale, backend, options) do + # do_to_string(span, unit, locale, backend, options) + # end + # + # defp do_to_string(seconds, unit, locale, backend, options) do + # seconds + # |> scale_relative(unit) + # |> to_string(unit, locale, backend, options) + # end defp time_unit_error(unit) do {Cldr.UnknownTimeUnit, "Unknown time unit #{inspect(unit)}. Valid time units are #{inspect(@unit_keys)}"} end - defp format_error(format) do - {Cldr.UnknownFormatError, - "Unknown format #{inspect(format)}. Valid formats are #{inspect(@known_formats)}"} + defp style_error(style) do + {Cldr.UnknownStyleError, + "Unknown style #{inspect(style)}. Valid styles are #{inspect(@known_styles)}"} end @doc """ @@ -374,16 +390,16 @@ defmodule Cldr.DateTime.Relative do {:error, time_unit_error(unit)} end - def known_formats do - @known_formats + def known_styles do + @known_styles end - defp validate_format(format) when format in @known_formats do - {:ok, format} + defp validate_style(style) when style in @known_styles do + {:ok, style} end - defp validate_format(format) do - {:error, format_error(format)} + defp validate_style(style) do + {:error, style_error(style)} end defp get_locale(locale, backend) do diff --git a/lib/cldr/format/datetime_formatter.ex b/lib/cldr/format/datetime_formatter.ex index 0d410ad..9b68e83 100644 --- a/lib/cldr/format/datetime_formatter.ex +++ b/lib/cldr/format/datetime_formatter.ex @@ -3339,9 +3339,31 @@ defmodule Cldr.DateTime.Formatter do defp number_of_digits(n), do: Enum.count(Integer.digits(n)) defp error_return(map, symbol, requirements) do - {:error, - "The format symbol '#{symbol}' requires at least #{inspect(requirements)}. Found: #{ - inspect(map) - }"} + requirements = + requirements + |> Enum.map(&inspect/1) + |> join_requirements + + raise Cldr.DateTime.UnresolvedFormat, + "The format symbol '#{symbol}' requires at map with at least #{requirements}. Found: #{ + inspect(map) + }" + end + + @doc false + def join_requirements([]) do + "" + end + + def join_requirements([head]) do + head + end + + def join_requirements([head, tail]) do + "#{head} and #{tail}" + end + + def join_requirements([head | tail]) do + to_string(head) <> ", " <> join_requirements(tail) end end diff --git a/lib/cldr/time.ex b/lib/cldr/time.ex index b4cbcc5..dd891b5 100644 --- a/lib/cldr/time.ex +++ b/lib/cldr/time.ex @@ -83,7 +83,8 @@ defmodule Cldr.Time do {:ok, "11:59:59 PM UTC"} """ - @spec to_string(map, module() | Keyword.t(), Keyword.t()) :: {:ok, String.t()} | {:error, {module, String.t()}} + @spec to_string(map, module() | Keyword.t(), Keyword.t()) :: + {:ok, String.t()} | {:error, {module, String.t()}} def to_string(time, backend \\ Cldr.default_backend(), options \\ []) @@ -106,9 +107,10 @@ defmodule Cldr.Time do {:ok, format_string} <- format_string(options[:format], locale, cldr_calendar, backend), {:ok, formatted} <- format_backend.format(time, format_string, locale, options) do {:ok, formatted} - else - {:error, reason} -> {:error, reason} end + rescue + e in [Cldr.DateTime.UnresolvedFormat] -> + {:error, {e.__struct__, e.message}} end def to_string(time, _backend, _options) do @@ -218,9 +220,14 @@ defmodule Cldr.Time do end defp error_return(map, requirements) do + requirements = + requirements + |> Enum.map(&inspect/1) + |> Cldr.DateTime.Formatter.join_requirements() + {:error, {ArgumentError, - "Invalid time. Time is a map that requires at least #{inspect(requirements)} fields. " <> + "Invalid time. Time is a map that contains at least #{requirements} fields. " <> "Found: #{inspect(map)}"}} end end diff --git a/mix.exs b/mix.exs index b88e295..e847e54 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule CldrDatesTimes.Mixfile do use Mix.Project - @version "2.2.1" + @version "2.2.2" def project do [ @@ -22,7 +22,8 @@ defmodule CldrDatesTimes.Mixfile do defp description do """ - Date, Time and DateTime localization and formatting functions for the Common Locale Data Repository (CLDR). + Date, Time and DateTime localization, internationalization and formatting + functions using the Common Locale Data Repository (CLDR). """ end @@ -56,13 +57,13 @@ defmodule CldrDatesTimes.Mixfile do defp deps do [ - {:ex_cldr, "~> 2.7"}, + {:ex_cldr, "~> 2.8"}, {:ex_cldr_numbers, "~> 2.6"}, - {:ex_cldr_calendars, "~> 1.0"}, - {:ex_doc, "~> 0.18", optional: true, only: [:dev, :release]}, + {:ex_cldr_calendars, "~> 1.2"}, + {:ex_doc, "~> 0.18", optional: true, only: [:dev, :release], runtime: false}, {:jason, "~> 1.0", optional: true}, - {:benchee, "~> 1.0", optional: true, only: :dev}, - {:dialyxir, "~> 1.0.0-rc.6", only: [:dev], runtime: false} + {:benchee, "~> 1.0", optional: true, only: :dev, runtime: false}, + {:dialyxir, "~> 1.0.0-rc", only: [:dev], runtime: false} ] end diff --git a/mix.lock b/mix.lock index a9ef986..63d2e58 100644 --- a/mix.lock +++ b/mix.lock @@ -1,13 +1,13 @@ %{ "benchee": {:hex, :benchee, "1.0.1", "66b211f9bfd84bd97e6d1beaddf8fc2312aaabe192f776e8931cb0c16f53a521", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}], "hexpm"}, - "cldr_utils": {:hex, :cldr_utils, "2.3.0", "e7e8b5ad7494a929c1b620cc489c3aa3f6e7e5299584c1a934bbdb56d1a53c70", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"}, + "cldr_utils": {:hex, :cldr_utils, "2.4.0", "53609273da803395e12f288cc25587ddb2238b533633b432471193c5f8b0d96a", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"}, "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"}, "dialyxir": {:hex, :dialyxir, "1.0.0-rc.6", "78e97d9c0ff1b5521dd68041193891aebebce52fc3b93463c0a6806874557d7d", [:mix], [{:erlex, "~> 0.2.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.3.5", "0db71c8290b5bc81cb0101a2a507a76dca659513984d683119ee722828b424f6", [:mix], [], "hexpm"}, "erlex": {:hex, :erlex, "0.2.4", "23791959df45fe8f01f388c6f7eb733cc361668cbeedd801bf491c55a029917b", [:mix], [], "hexpm"}, - "ex_cldr": {:hex, :ex_cldr, "2.8.1", "0132fc86cc640507d31e14513e6ede47a3a40270d9c97909e2fce5243c914612", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"}, - "ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.0.0", "e7d86c484ae008b93d630c0511571f8028333504fc6503d5874c5e6dc97df967", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.7", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_cldr": {:hex, :ex_cldr, "2.10.1", "cfa37fce29789b01bc6676694c8f7152d470824f59e98281f88ac11ef9b46ff2", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"}, + "ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.2.0", "c9cd3704590081bb7bea5d6e5279766f0815b17e6db4ea28ccba90a49f3172eb", [:mix], [{:ex_cldr, "~> 2.8", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.4", [hex: :ex_cldr_lists, repo: "hexpm", optional: true]}, {:ex_cldr_units, "~> 2.0", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.3.0", "bffae489416b8b05d4683403263f5d62aae17de70c24ff915a533541fea514de", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, "ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.7.0", "a5a339be352840b95251aeb5380ca9118441a436c508b9ba04d6a935a204c669", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.3", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.21.1", "5ac36660846967cd869255f4426467a11672fec3d8db602c429425ce5b613b90", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, diff --git a/test/exceptions_test.exs b/test/exceptions_test.exs index bdb35e1..0420eba 100644 --- a/test/exceptions_test.exs +++ b/test/exceptions_test.exs @@ -3,21 +3,28 @@ defmodule Cldr.Exceptions.Test do test "that an invalid datetime raises" do assert_raise ArgumentError, - ~r/Invalid date_time. Date_time is a map that requires at least .*/, + ~r/Invalid DateTime. DateTime is a map that contains at least .*/, fn -> Cldr.DateTime.to_string!("not a date") end end test "that an invalid date raises" do - assert_raise ArgumentError, ~r/Invalid date. Date is a map that requires at least .*/, fn -> + assert_raise ArgumentError, ~r/Invalid date. Date is a map that contains at least .*/, fn -> Cldr.Date.to_string!("not a date") end end test "that an invalid time raises" do - assert_raise ArgumentError, ~r/Invalid time. Time is a map that requires at least .*/, fn -> + assert_raise ArgumentError, ~r/Invalid time. Time is a map that contains at least .*/, fn -> Cldr.Time.to_string!("not a time") end end + + test "that an unfulfilled format directive returns an error" do + assert Cldr.Date.to_string(~D[2019-01-01], format: "x") == + {:error, + {Cldr.DateTime.UnresolvedFormat, + "The format symbol 'x' requires at map with at least :utc_offset. Found: %Date{calendar: Cldr.Calendar.Gregorian, day: 1, month: 1, year: 2019}"}} + end end