Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Can you provide a concrete example? Ideally using Temporal to show where it's going wrong. Like, if you created `2025-06-20T17:00:00+02[Europe/Dublin]` (the instant) in 1760, then its civil representation would be different, to account for the rules in place at the time. And then if you went to deserialize it today, Temporal would reject it. You'd get an error, because the rules in place when the string was serialized don't match the rules in place today for that instant.

To be clear, I might be misunderstanding what you're saying. So that's why I'm asking for a concrete example. That will cut through everything. And if you didn't, I would strongly suggest you take a look at https://tc39.es/proposal-temporal/docs/zoneddatetime.html and search for "conflict". I think that will help explain things.

> I get that it’s more correct

We can chase perfection, but perfection isn't the goal. All models are wrong, but some are useful. In other words, the question isn't whether Temporal's model of interaction with time is wrong (it is!), it's how wrong it is and what its impact is that matters.



I must be misunderstanding what you’re saying. How does Temporal know to reject something serialized from before a rule was changed when the creation time of the serialized representation isn’t encoded? You’re saying in 1760 [Europe/Dublin] would be a different string vs today? A more concrete example is normal time-zone rule changes - `2025-06-20T17:00:00+02[Europe/Dublin]` would represent different instants if Dubling passed a new DST rule adjusting the clock back by 15 minutes at 2025-06-20T16:50:00+02[Europe/Dublin] - then the meaning of the instant is different because now there’s 2 different `2025-06-20T17:00:00+02[Europe/Dublin]` and which one you get will depend on when you deserialize.


Can you check out the Brazil example in the docs I linked? That really should clear everything up. It explains how a datetime in the future gets serialized, but after a DST change, that serialized datetime becomes invalid.

The way this works is by looking at offsets. Think of a time zone as a function mapping between civil time and physical time. Or, another way to think about it is a mapping from a civil time to an offset (which may not exist for gaps or may not be unique for folds) and a mapping from physical time to an offset (of which there is a bijection). With RFC 9557, you encode both the offset and the time zone into the serialized representation. Consider a case when you encode an offset corresponding to DST, and then DST is abolished. Your tzdb is updated. Then you go to deserialize this datetime. Its offset no longer matches the rules. This can be detected and Temporal reports an error. This is all explained in the docs.

Note that DST is only an example here, because it's a common manifestation of how this error arises. But it can happen with any change in offset.

So if you're in 1760 and you write down a datetime in the future using the rules of that time (of which, I'm not even sure that's a sensible question to ask), then you'd have a particular offset encoded in that future datetime. Now fast forward to the future and the rules have changed and are no longer consistent with the offset encoded in the datetime. Thus, you get an error.

Here's another take on the idea that I wrote for Jiff: https://docs.rs/jiff/latest/jiff/tz/enum.OffsetConflict.html

Think of it like this. In an RFC 9557 timestamp, you have an offset and you have a time zone. Those two pieces of information may be inconsistent with one another. For example, `2025-01-30T17:00+10[US/Eastern]`. When that happens, you can report an error. That's pretty much it.

> then the meaning of the instant is different because now there’s 2 different `2025-06-20T17:00:00+02[Europe/Dublin]` and which one you get will depend on when you deserialize.

If the region adjusted their close back by 15 minutes, then the offset would change. As for `2025-06-20T17:00:00+02[Europe/Dublin]`, it can only feasibly have two different interpretations: you can either interpret it as the instant `2025-06-20T17:00:00+02`, or you can interpret it as the civil time `2025-06-20T17:00:00` in the time zone `Europe/Dublin`, ignoring the offset. Or you can reject it. Temporal supports all of these modes, and it will by default reject such strings when the offset and time zone are inconsistent.

(There's a fourth mode, "prefer offset," that I won't get into here... It's not usually used for deserialization/parsing.)


So in my use cases, there's three types of dates that matter:

1. Past dates. These can be stored UTC, and just rendered in the appropriate timezone as a matter of formatting.

2. Future non-human dates: e.g. the next execution time of a job that runs every hour. These can just be UTC

3. Future human dates: I care about the human selected timezone so that events happen on the wall clock time the user expects. The UTC time and UTC offset are meaningless.

So in cases 1 and 2, having a non-UTC date is not required, while for case 3, the only thing that UTC offset is doing is adding information that could be inconsistent or confusing.

e.g. If the concert is on at 2026-01-31T18:00:00[Europe/Dublin] , that's all that matters, whether that ends up being 2026-01-31T18:00:00+00:00 or 2026-01-31T18:00:00+01:00 is unimportant for whether the building is going to be open at the time. So the system failing to give customers on the day of the concert a countdown because `2026-01-31T18:00:00+00:00[Europe/Dublin]` has become inconsistent because e.g. the EU actually did go ahead and abolish DST is suboptimal.


For that specific use case, sure! But Temporal isn't for Macha's 3 use cases. Not all future datetimes are only concerned with civil time. Some are concerned with the precise instant in time. So how do you choose which one? There is no one universal right answer, so IMO, the right default is to reject.

But if you know your use cases and know you always want to adhere to civil time even if it means a change in the precise instant, then Temporal supports that too:

    >> zdt = Temporal.ZonedDateTime.from("2025-06-20T17:00+08[US/Eastern]")
    Uncaught RangeError: Offset +08:00 is invalid for 2025-06-20T17:00:00 in US/Eastern
        InterpretISODateTimeOffset ecmascript.mjs:1467
        ToTemporalZonedDateTime ecmascript.mjs:1531
        from zoneddatetime.mjs:478
        <anonymous> debugger eval code:1
    >> zdt = Temporal.ZonedDateTime.from("2025-06-20T17:00+08[US/Eastern]", {offset: 'ignore'})
    >> zdt.toString()
    "2025-06-20T17:00:00-04:00[US/Eastern]"
> So in cases 1 and 2, having a non-UTC date is not required

If the only operation you need is formatting, then I agree, you can apply the time zone to the instant right before it's displayed. But there are many other operations (such as arithmetic or computing durations between datetimes) you might want to do that do required a time zone. You might still be able to get away with only storing a UTC date, but it really depends on what you're doing.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: