Closed jzabinski-dolios closed 2 years ago
This isn't a bug. By default in Luxon, DateTimes are in the system zone. That's why the zone constructed by DateTime.now()
is a the system zone:
DateTime.now().zone //=> SystemZone
When you're rebuilding the string, you're setting the zone explicitly to an IANA zone, and thus setting that zone property. Luxon DateTimes are only equivalent if they're in different zones:
const now = DateTime.now()
const iso = now.toISO()
DateTime.fromISO(iso).equals(now) // => true (both system zone)
DateTime.fromISO(iso, { zone: "Europe/London" }).equals(now.setZone("Europe/London")) //=> true (both the same IANA zone)
Now there is one confusing thing, which is that you're passing in the zone you're already in, which makes it seem like it should work. But an IANA zone of "America/New_York" and a system zone that happens to be America/New_York are different things. The reason for this is performance: the native Date functionality is a lot faster than Luxon computing times in an explicit zone.
In principle, we could fix this by making Luxon aware that the System zone is equivalent to some particular IANA zone and treating those as the same for the purposes of comparison. But I think that also has some drawbacks that would make debugging Luxon harder in other scenarios.
You have a few workarounds to compare system zoned dates to IANA zoned dates:
Settings.defaultZone = SystemZone.instance.name
. I don't recommend this.America/New_York
Describe the bug If a
DateTime
is generated usingDateTime.now()
, and is transformed to a string usingtoISO()
, and newDateTime
s are made with those strings, the resultingDateTime
s are not seen as equal to the original when usingDateTime.equals
because they have differing metadata.To Reproduce
DateTime
usingDateTime.now()
. Example:const now = DateTime.now();
DateTime.toISO()
. Example:const nowStr = now.toISO();
DateTime
usingDateTime.fromISO([string from #2], {zone: [#1.zoneName]})
. Example:const now2 = DateTime.fromISO(nowStr, {zone: now.zoneName})
now.equals(now2)
.Equivalency will fail. They fail because
now
's metadata includeszone
asSystemZone
.now2
has anIANAZone
.See this Stackblitz.
Actual vs Expected behavior On
DateTime
s defined usingDateTime.now()
, it is strange to me thatzoneName
refers to anIANAZone
, whilezone
refers to'system'
. I would expect thezoneName
andzone
to match. In other words, when usingDateTime.now()
, either:zone
is'system'
, andzoneName
is'system'
, so that it is clear that the system's time zone was used to generate the time, orzone
is explicitly defined asIANAZone {zoneName: [zoneName], valid: true}
, andzoneName
is[zoneName]
Desktop (please complete the following information):
Additional context I'm not sure if this is a bug, or an intentional limitation of
DateTime.now()
. The workaround seems to be to explicitly define the timezone by usingDateTime.local({zone: [zoneName]})
instead ofDateTime.now()
when it is important to be able to have the ability to transform theDateTime
to and from a string.