Should DateTime.diff/3 round numbers?

I noticed some weird anomalies in a dataset.
Turns out I was mixing Postgres and Elixir numbers.

DateTime.diff(~U[2026-03-18 05:50:08.653909Z], ~U[2026-03-18 05:50:04.655608Z], :second)
# 3

DateTime.diff(~U[2026-03-18 05:50:08.653909Z], ~U[2026-03-18 05:50:04.655608Z], :millisecond)
# 3998

select extract(epoch from ('2026-03-18 05:50:08.653909Z'::timestamptz - '2026-03-18 05:50:04.655608Z'::timestamptz))::integer
# 4

The Postgres number (4) seems reasonable.

The docs for DateTime.diff state the current behaviour:

Fractional results are not supported and are truncated.

You could always implement your own rounding or propose adding an option to DateTime.diff, but changing the default behaviour would be a breaking change.

3 Likes

Tnx. I overlooked that somewhat cryptic disclaimer.
Maybe “meaning all numbers are rounded down” could be added.
I’ll go with the millisecond option.

Truncate is a common name used for that operation, e.g. on Kernel — Elixir v1.19.5. While it matches the rounding-towards-zero rounding strategy (one of many) it tries to tell that no rounding is happening. It’s not looking a the fractional remain to determine what needs to happen, but it ignores it outright of it is calculated in the first place.

2 Likes

Look what I found :wink:

  `div/2` performs *truncated* integer division. This means that
  the result is always rounded towards zero.

Actually I was referring to “Fractional results are not supported” as a somewhat crypic disclaimer. “Results are truncated” would be more transparent (for us “alpha” thinkers).