   end
 
   @doc """
+  Parses the extended "Date and time of day" format described by ISO8601:2004.
+
+  Raises it the format is invalid.
+
+  ## Examples
+
+      iex> Date.from_iso8601!("2015-01-23")
+      %Date{year: 2015, month: 01, day: 23}
+      iex> Date.from_iso8601!("2015:01:23")
+      ** (ArgumentError) cannot parse "2015:01:23" as date, reason: :invalid_format
+  """
+  @spec from_iso8601!(String.t) :: Date.t | no_return
+  def from_iso8601!(string) do
+    case from_iso8601(string) do
+      {:ok, value} ->
+        value
+      {:error, reason} ->
+        raise ArgumentError, "cannot parse #{inspect string} as date, reason: #{inspect reason}"
+    end
+  end
+
+  @doc """
   Converts the given date time to ISO8601.
 
   Only supports converting date times which are in the ISO calendar,

      iex> NaiveDateTime.from_erl({{2000, 13, 1},{13, 30, 15}})
      {:error, :invalid_date}
  """
  @spec from_erl(:calendar.datetime(), Calendar.microsecond) :: {:ok, __MODULE__.t} | {:error, atom}
  def from_erl({{year, month, day}, {hour, minute, second}}, microsecond \\ 0) do
    new(year, month, day, hour, minute, second, microsecond)
  end
end


  @spec from_erl(:calendar.date()) :: {:ok, Date.t} | {:error, atom}
  def from_erl({year, month, day}) do
    new(year, month, day)
  end

  @doc """
  Converts an Erlang date tuple but raises for invalid dates.

  ## Examples

      iex> Date.from_erl!({2000, 1, 1})
      %Date{year: 2000, month: 1, day: 1}
      iex> Date.from_erl!({2000, 13, 1})
      ** (ArgumentError) cannot convert {2000, 13, 1} to date, reason: :invalid_date
  """
  @spec from_erl!(:calendar.date()) :: Date.t | no_return
  def from_erl!(tuple) do
    case from_erl(tuple) do
      {:ok, value} ->
        value
      {:error, reason} ->
        raise ArgumentError, "cannot convert #{inspect tuple} to date, reason: #{inspect reason}"
    end
  end
end

