Skip to content

DateTime comparisons do not work #51

Description

@TylerPachal

Here is an example of where DateTime values are not being considered equal, I suppose because under-the-hood a regular == comparison is being done:

# DateTime with no milliseconds
iex(1)> dt_1 = ~U[2020-01-01T00:00:00Z]    
~U[2020-01-01 00:00:00Z]

# DateTime with milliseconds
iex(2)> dt_2 = ~U[2020-01-01T00:00:00.000Z]
~U[2020-01-01 00:00:00.000Z]

# Putting them in maps, they are not equal
iex(3)> MapDiff.diff(%{dt: dt_1}, %{dt: dt_2})
%{
  added: %{dt: ~U[2020-01-01 00:00:00.000Z]},
  changed: :map_change,
  removed: %{dt: ~U[2020-01-01 00:00:00Z]},
  value: %{
    dt: %{
      added: ~U[2020-01-01 00:00:00.000Z],
      changed: :map_change,
      removed: ~U[2020-01-01 00:00:00Z],
      struct_name: DateTime,
      value: %{
        calendar: %{changed: :equal, value: Calendar.ISO},
        day: %{changed: :equal, value: 1},
        hour: %{changed: :equal, value: 0},
        microsecond: %{
          added: {0, 3},
          changed: :primitive_change,
          removed: {0, 0}
        },
        minute: %{changed: :equal, value: 0},
        month: %{changed: :equal, value: 1},
        second: %{changed: :equal, value: 0},
        std_offset: %{changed: :equal, value: 0},
        time_zone: %{changed: :equal, value: "Etc/UTC"},
        utc_offset: %{changed: :equal, value: 0},
        year: %{changed: :equal, value: 2020},
        zone_abbr: %{changed: :equal, value: "UTC"}
      }
    }
  }
}

# Comparing them using == they are not equal
iex(4)> dt_1 == dt_2
false

# Comparing them with DateTime.compare/2 works as expected
iex(5)> DateTime.compare(dt_1, dt_2)
:eq

Possible solutions

  1. Add an option for common structs like this to be compared using their own compare functions:
MapDiff.diff(map1, map2, compare_carefully: [DateTime, NaiveDateTime])
  1. Add a callback to let users do their own comparisons for specific types:
MapDiff.diff(map1, map2, compare: {DateTime, fn a, b -> DateTime.compare(a, b) == :eq end})

If you let me know what your preference is I can prepare a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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