       :eq
 
   """
-  @spec compare(Calendar.date, Calendar.date) :: :lt | :eq | :gt
-  def compare(%{calendar: calendar, year: year1, month: month1, day: day1},
-              %{calendar: calendar, year: year2, month: month2, day: day2}) do
+  @spec compare(Calendar.date(), Calendar.date()) :: :lt | :eq | :gt
+  def compare(%{calendar: calendar, year: year1, month: month1, day: day1}, %{
+        calendar: calendar,
+        year: year2,
+        month: month2,
+        day: day2
+      }) do
     case {{year1, month1, day1}, {year2, month2, day2}} do
       {first, second} when first > second -> :gt
       {first, second} when first < second -> :lt
       _ -> :eq
     end
   end
+
   def compare(date1, date2) do
     if Calendar.compatible_calendars?(date1.calendar, date2.calendar) do
       case {to_iso_days(date1), to_iso_days(date2)} do

      {:error, :invalid_date}

  """
  @spec from_iso8601(String.t) :: {:ok, t} | {:error, atom}
  def from_iso8601(string, calendar \\ Calendar.ISO)

  def from_iso8601(<<year::4-bytes, ?-, month::2-bytes, ?-, day::2-bytes>>, calendar) do
    with {year, ""} <- Integer.parse(year),
         {month, ""} <- Integer.parse(month),
         {day, ""} <- Integer.parse(day) do
      with {:ok, date} <- new(year, month, day, Calendar.ISO),
           do: convert(date, calendar)
    else
      _ -> {:error, :invalid_format}
    end

      iex> Date.from_iso8601!("2015:01:23")
      ** (ArgumentError) cannot parse "2015:01:23" as date, reason: :invalid_format
  """
  @spec from_iso8601!(String.t()) :: t
  def from_iso8601!(string, calendar \\ Calendar.ISO) do
    case from_iso8601(string, calendar) do
      {:ok, value} ->
        value

      {:error, reason} ->
        raise ArgumentError, "cannot parse #{inspect(string)} as date, reason: #{inspect(reason)}"
    end
  end

