DEV Community

Kai Mercer
Kai Mercer

Posted on

Days between dates in America/Los_Angeles: when one day becomes zero

A reader suggested running my days-between-dates check with a timezone behind UTC, such as America/Los_Angeles. I had only tested the calculator logic in one zone. So here is the same small test run under three zones, with the results as they came out.

Setup: Node v22 (V8, the engine behind Chrome), run as TZ=<zone> node test.js. Not a browser, and no UI. I used US daylight saving dates: clocks went forward on March 8, 2026 and back on November 1, 2026. Three ways to get days between two YYYY-MM-DD strings:

const ms = 86400000;
// 1. parse the strings directly
(new Date(b) - new Date(a)) / ms;
// 2. build local midnight from the parts
const local = s => { const [y,m,d] = s.split("-").map(Number); return new Date(y, m-1, d); };
(local(b) - local(a)) / ms;
// 3. build UTC midnight from the parts
const utc = s => { const [y,m,d] = s.split("-").map(Number); return Date.UTC(y, m-1, d); };
(utc(b) - utc(a)) / ms;
Enter fullscreen mode Exit fullscreen mode

Results

Mar 7 to Mar 9, 2026 (expected 2):

Method UTC America/Los_Angeles Australia/Adelaide
1. parse strings 2 2 2
2. local midnight 2 1.9583 2
3. UTC parts 2 2 2

Mar 8 to Mar 9, 2026 (expected 1), method 2 only: UTC 1, Los Angeles 0.9583, Adelaide 1. Nov 1 to Nov 2, 2026 (expected 1), method 2 in Los Angeles: 1.0417.

So local midnight is the one that breaks. A 23-hour day gives 0.9583, and Math.floor turns that into 0: one day apart reported as zero days. Math.round would hide it.

A second trap: parsing a date-only string

new Date("2026-03-08") is read as UTC midnight. In Los Angeles that prints as Sat Mar 07 2026 16:00 local, and .getDate() returns 7, not 8. In UTC and Adelaide it returns 8. If you parse a date-only string and then read local parts to display it, the day shifts for anyone behind UTC. new Date("2026-03-08T00:00") (no zone suffix) is local time and returned 8 in all three.

What I would do

  • For whole days between calendar dates, use method 3. It never touches local time, so DST cannot move it.
  • Do not floor a millisecond difference of local dates. If you must, Math.round it, and know why.
  • If you display a parsed date-only string, format it in UTC or build it from parts.

Not tested

Browsers other than the V8 runtime above, Safari's date parsing, zones that skip a whole day, and any specific calculator's source. This is about the arithmetic, not a particular app.

Related: the days-between-dates article this came from.

Top comments (0)