Proposal-temporal: Eliminate OffsetDateTime & ZonedDateTime

Created on 25 Sep 2019  路  9Comments  路  Source: tc39/proposal-temporal

Based on #139 and #156 the second thought is to eliminate ZonedDateTime & OffsetDateTime entirely.

I've tried that experiment at https://github.com/std-proposal/temporal/tree/reduced

Pros:

  • Clear conceptual differentiation between absolute point in time and date/time-like things

( @devjgm @devbww can you elaborate on learnings from abseil)

Similar question to before:

Give me all the reasons why ZonedDateTime & OffsetDateTime should actually be a thing

( @gibson042 please comment! )

behavior question

Most helpful comment

I'm in two minds about this. On one hand, there was a large discussion in #84 about how useful the concept of ZonedDateTime was, so it seems strange that it's now getting dumped. On the other hand, I agree that it's better to have no ZonedDateTime at all, and be able to add it in later, than to lock in a version that people don't agree on.

What I'm most concerned about here, though, is the process by which it was dropped. The removal of 2 API objects was proposed with just a single "pro" and no "cons" as justification, which seems pretty weak from where I sit. Then the burden of proof for keeping them was put on to everyone else. That's the inverse of how it should go.

Unfortunately, many of the large API changes are being done with an almost complete absence of practical examples (something I raised in https://github.com/tc39/proposal-temporal/issues/26#issuecomment-513208398, and will continue to harp on about). It would be far easier to make decisions about the impacts of a proposed API change if there were before/after code samples for real-world use cases.

All 9 comments

I don't think we have much to add beyond what @devjgm said in #139.

One thing I can say is that I don't believe we have ever had a request to add a type beyond our absolute-time, absolute-duration, and time-zone ones (absl::Time, absl::Duration, and absl::TimeZone), and our set and civil-time ones (absl::CivilSecond and friends).

People may have created their own hybrids, I guess, but they have never risen to the level of noticeability.

FWIW, I think this is a good idea. I maintain rSchedule, a typescript recurring events library. Through some trial and error, I arrived at a similar abstraction for implementing the recurrence logic.

When a user provides a date, it is converted into a custom absolute time object (which mostly relies on the standard Date in UTC). All logic is processed using these absolute times. Then, before yielding a date back to the user, the absolute time is re-combined with the original time zone.

The rrulejs recurrence library uses a similar (albeit, more crudely implemented) strategy where the user is required to convert provided dates into an absolute time format (basically, the user needs to handle the conversion rather than the library doing it for them -- but the idea is the same).

Clear conceptual differentiation between absolute point in time and date/time-like things

^ Agreed. This format is much easier to reason over while also avoiding timezone issues.

This decision also leaves open the possibility of adding a ZonedDateTime object to the temporal module in a future update. In the meantime, if a ZonedDateTime object is found to be desirable, users will be able to create their own ZonedDateTime object relatively easily using the tools in the 1.0 temporal module.

Just fyi this is what I'm presenting as an update at TC39

Give me all the reasons why ZonedDateTime & OffsetDateTime should actually be a thing

@pipobscure maybe this should be a separate issue, but one area that is unclear when looking at the code for the current polyfill (which has eliminated ZonedDateTime & OffsetDateTime), is what happens when the user attempts to combine a zoneless DateTime with a time zone and the result is invalid? E.g. if a DST shift results in 3am immediately becoming 4am, so 3:30am doesn't exist, what happens if you combine a DateTime at 3:30am with that time zone?

  • Personally, as a library implementor, what I would find most useful is for a special error to be thrown indicating that the current time is invalid because of DST. The error would contain a property indicating when the DST time-skip started (e.g. 3am) and a separate property indicating how much time was skipped (e.g. 1 hour). This would be enough information for a developer to easily handle the issue (e.g. they could prompt the user for a new date, or they could add 1 hour to the time (producing 4:30am), or they could get the next valid time (4am) or the most recently valid time in the past (3am - 1 nanosecond).

Depends on how you do it.

TZ.getAbsoluteFor(DT) => []
DT.withZone(TZ) => throws

for the case a datetime exists twice (DST)

TZ.getAbsoluteFor(DT) => [earlier, later]
DT.withZone(TZ, Temporal.EARLIER) => earlier
DT.withZone(TZ, Temporal.LATER) => later
DT.withZone(TZ, offset) => the one with that offset or throw otherwise
default second prameter is Temporal.EARLIER

For what it's worth, the Abseil (C++, no exceptions) absl::CivilSecond +
absl::TimeZone function returns three absl::Time values:

struct TimeInfo {
enum CivilKind {
UNIQUE, // the civil time was singular (pre == trans == post)
SKIPPED, // the civil time did not exist (pre >= trans > post)
REPEATED, // the civil time was ambiguous (pre < trans <= post)
} kind;
Time pre; // time calculated using the pre-transition offset
Time trans; // when the civil-time discontinuity occurred
Time post; // time calculated using the post-transition offset
};

Abseil also has a helper function that returns a single, "order preserving"
absl::Time value, which we believe is what most simple applications want:

// FromCivil()
//
// Helper for TimeZone::At(CivilSecond) that provides "order-preserving
// semantics." If the civil time maps to a unique time, that time is
// returned. If the civil time is repeated in the given time zone, the
// time using the pre-transition offset is returned. Otherwise, the
// civil time is skipped in the given time zone, and the transition time
// is returned. This means that for any two civil times, ct1 and ct2,
// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case
// being when two non-existent civil times map to the same transition
time.
inline Time FromCivil(CivilSecond ct, TimeZone tz) {
const auto ti = tz.At(ct);
if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;
return ti.pre;
}

>

Thanks! That sounds very much like what we鈥檙e doing adjusted for different idioms.

Working with a state flag like that sounds just right for C/C++ but would be weird in JS. But being able to get 0, 1 or 2 results sounds right and exactly like what we鈥檙e thinking for TZ. getAbsoluteFor(DT)

For the DT.withZone(TZ) where a single result is expected, throwing seems idiomatic for JS.

I'm in two minds about this. On one hand, there was a large discussion in #84 about how useful the concept of ZonedDateTime was, so it seems strange that it's now getting dumped. On the other hand, I agree that it's better to have no ZonedDateTime at all, and be able to add it in later, than to lock in a version that people don't agree on.

What I'm most concerned about here, though, is the process by which it was dropped. The removal of 2 API objects was proposed with just a single "pro" and no "cons" as justification, which seems pretty weak from where I sit. Then the burden of proof for keeping them was put on to everyone else. That's the inverse of how it should go.

Unfortunately, many of the large API changes are being done with an almost complete absence of practical examples (something I raised in https://github.com/tc39/proposal-temporal/issues/26#issuecomment-513208398, and will continue to harp on about). It would be far easier to make decisions about the impacts of a proposed API change if there were before/after code samples for real-world use cases.

On Mon, May 18, 2020 at 2:21 PM Justin Grant notifications@github.com
wrote:

>

I'm afraid I don't grok "duration balancing". Still, the sentences you
refer to in absl/time/duration.cc only concern an implementation detail
... we could have represented a duration differently, and may still.

>

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ptomato picture ptomato  路  5Comments

pipobscure picture pipobscure  路  6Comments

Ms2ger picture Ms2ger  路  6Comments

justingrant picture justingrant  路  4Comments

sffc picture sffc  路  5Comments