luxon icon indicating copy to clipboard operation
luxon copied to clipboard

#1165: Fixing and Testing "Duration.diff returns negative number"

Open JoaoAugustoPansani opened this issue 2 years ago • 4 comments

On the file ./scripts/src/impl/diff.js there's a function dayDiff:

function dayDiff(earlier, later) {
  const utcDayStart = (dt) => dt.toUTC(0, { keepLocalTime: true }).startOf("day").valueOf(),
    ms = utcDayStart(later) - utcDayStart(earlier);
  return Math.floor(Duration.fromMillis(ms).as("days"));
}

What I did for solving this issue, was delete the second argument inside .toUTC:

function dayDiff(earlier, later) {
  const utcDayStart = (dt) => dt.toUTC(0).startOf("day").valueOf(),
    ms = utcDayStart(later) - utcDayStart(earlier);
  return Math.floor(Duration.fromMillis(ms).as("days"));
}

Then I wrote a test inside ./scripts/test/datetime/diff.test.js:

test("DateTime#diff works when date has a zone object", () => {
  const start = DateTime.fromISO("2022-05-05T23:00", { zone: "UTC" });
  const end = DateTime.fromISO("2022-05-10T00:00", { zone: "Europe/Madrid" });

  const diff = end.diff(start, ["days", "hours", "minutes"]).toObject();
  expect(diff.days).toBe(3);
  expect(diff.hours).toBe(23);
  expect(diff.minutes).toBe(0);
});

JoaoAugustoPansani avatar Apr 21 '22 14:04 JoaoAugustoPansani

CLA Signed

The committers listed above are authorized under a signed CLA.

  • :white_check_mark: login: JoaoAugustoPansani / name: João Augusto Mendonça Pansani (c55a8bed649819a76549372c8071f6966dad05eb, 65124dab34162bbb7299e0651877b6f7bc0f4528)

Sorry for the slow response. I don't think this fix is correct, though. That second argument ensures that diff compares local times, not absolute ones. You can see the problem by trying these dates instead:

const start = DateTime.fromISO("2022-05-06T00:00", { zone: "UTC" });
const end = DateTime.fromISO("2022-05-10T00:00", { zone: "Europe/Madrid" });

dayDiff(start, end) // returns 3, not 4

icambron avatar May 08 '22 23:05 icambron

No problem @icambron, that's fine. I'll work on that, thanks for the response!

JoaoAugustoPansani avatar May 11 '22 13:05 JoaoAugustoPansani

Sorry I've only briefly looked at this but why not just convert both datetimes toMillis() and subtract? Then convert millis to Duration and shiftTo() back to requested units?

omasback avatar Jun 02 '22 02:06 omasback