var { DateTime } = require("luxon")
const zone = 'America/Curacao'
d = DateTime.utc(1, 1, 1, 0, 0, 0)
console.log(d.toISO())
console.log(d.setZone(zone, { keepLocalTime: true }).toISO())
Output:
"0001-01-01T00:00:00.000Z"
"0001-01-02T00:00:00.000+8779:24.216666666674428"
Is this expected behaviour?
That is certainly odd. No, it should be returning a local time with a different offset but the same date and time. I suspect that the historic timezone being used here has something really strange about it that's confusing Luxon, but I'll need to dig deeper
Fun one.
First, v8's historic date math here is bonkers. Without Luxon:
> new Intl.DateTimeFormat("en", { timeZone: "America/Curacao", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false}).format(new Date("0001-01-01"))
'12/31/1, 19:24:13'
That is almost a year off! That's what leads Luxon to think that time zone has an absurd offset of 8755 hours; it does the math in reverse to compute the offset. It's hard to imagine why the browser does that, but well, it does.
But while that's absurd, the math should still work out, meaning that it's not immediately obvious why Luxon won't shift the date back for keepLocalTime, regardless of the offset's size. So where are those extra 24 hours coming from?
Well, what Luxon actually does is subtract back off the offset for Jan 1 UTC to produce a whole new time, in this case, almost a year before. When we want to see the date in the local zone, it then plugs that into Intl with the zone setting, which in this case produces Jan 2, 1 AD instead of the expected Jan 1. I think the fundamental problem is that Luxon is making the hidden assumption that the "real" date (Jan 1, UTC) and the shifted date (8755 hours before Jan 1, UTC) have the same local offset, and in this case it isn't true: the date from almost a year before that we expect to have the local date of Jan 1 has an offset even 24 hours greater (8779 hours instead of 8755 horus), and when that offset is applied, we get a local date of Jan 2. This assumption is problematic in general and probably causes some bugs with keepLocalTime near DST shifts, but it's very likely to happen with gigantic offsets like the one here, since the chances that the offset spans a change in the offset itself is high.
I'm going to leave this open. The next step would be to reproduce this issue under more sane conditions, since if it happens there (and I don't see why it wouldn't), it's important to fix, whereas if it's just about wack historic date data, I would probably not fix it. Luxon has some code designed to handle this kind of thing, but it isn't being applied to the calculation here, and I bet it could be.
Turned out to be pretty easy. Fixed in 1a7f1fe. Will release shortly.
See 1.13.3