Skip to content

The typespecs of Timex.Format.DateTime.Formatters.Relative do not correspond with supported types #774

@HansGlimmerfors

Description

@HansGlimmerfors

Steps to reproduce

iex(1)> Timex.Format.DateTime.Formatters.Relative.format(~T[12:00:00], "{relative}")
** (ArithmeticError) bad argument in arithmetic expression: div({:error, :invalid_date}, 31104000)
    :erlang.div({:error, :invalid_date}, 31104000)
    (timex 3.7.11) lib/format/datetime/formatters/relative.ex:227: Timex.Format.DateTime.Formatters.Relative.do_format/5
    iex:1: (file)

iex(1)> Timex.format(~T[12:00:00], "{relative}", :relative)
** (ArithmeticError) bad argument in arithmetic expression: div({:error, :invalid_date}, 31104000)
    :erlang.div({:error, :invalid_date}, 31104000)
    (timex 3.7.11) lib/format/datetime/formatters/relative.ex:227: Timex.Format.DateTime.Formatters.Relative.do_format/5
    iex:1: (file)

iex(1)> Timex.Format.DateTime.Formatters.Relative.lformat(~T[12:00:00], "{relative}", "en")
** (ArithmeticError) bad argument in arithmetic expression: div({:error, :invalid_date}, 31104000)
    :erlang.div({:error, :invalid_date}, 31104000)
    (timex 3.7.11) lib/format/datetime/formatters/relative.ex:227: Timex.Format.DateTime.Formatters.Relative.do_format/5
    iex:1: (file)

iex(1)> Timex.lformat(~T[12:00:00], "{relative}", "en", :relative)
** (ArithmeticError) bad argument in arithmetic expression: div({:error, :invalid_date}, 31104000)
    :erlang.div({:error, :invalid_date}, 31104000)
    (timex 3.7.11) lib/format/datetime/formatters/relative.ex:227: Timex.Format.DateTime.Formatters.Relative.do_format/5
    iex:1: (file)

Description of issue

Timex.Types.calendar_types() and Timex.Types.valid_datetime() include Time.t() since 2a912f3.
However no support for Time.t() was ever added to align with the updated typespec changes. The docs in e.g. Timex.Format.DateTime.Formatter correctly state that the datetime formatter only supports DateTime.t(), Date.t() and NaiveDateTime.t(). This means that typespecs of the following functions don't correspond to what they actually support:

  • Timex.Format.DateTime.Formatters.Relative.format/2
  • Timex.Format.DateTime.Formatters.Relative.format!/2
  • Timex.Format.DateTime.Formatters.Relative.lformat/3
  • Timex.Format.DateTime.Formatters.Relative.lformat!/3

The errors seen above in Steps to reproduce are caused by a call to Timex.Protocol.to_naive_datetime/1 (which is referenced by both Timex.Format.DateTime.Formatters.Relative.lformat/3 and Timex.Format.DateTime.Formatters.Relative.relative_to/4) because the protocol is not implemented for Time.

Ways to solve

Option 1:

  • Remove Time.t() from the typespecs
  • Remove Time from the guard in Timex.Format.DateTime.Formatter.lformat/3 such that the function call instead returns {:error, :invalid_date} when a Time-struct is passed

Option 2:

  • Add support for Time.t()
    I would expect such support to act like the behaviour of a passed 'today'-value of type DateTime or NaiveDateTime, i.e. returning values such as {:ok, "8 hours ago"} or {:ok, "in 1 hour"}.
    I'm not sure if it makes sense to implement Timex.Protocol for Time since a lot of the functions are date-related, so maybe it makes sense to instead make a separate clause of Timex.Format.DateTime.Formatters.Relative.lformat/3 which handles Time just slightly differently to how Date, DateTime and NaiveDateTime are handled.
    (Very similar function clause, but call do_format/5 with the passed Time-struct and Time.utc_now() instead of Timex.Protocol.to_naive_datetime(date) and Timex.Protocol.now()?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions