Re: [calsify] RFC 5545/JSCalendar questions from ECMAScript TC39 "Temporal" working group
Justin Grant <justingrant.ietf.public@gmail.com> Sun, 02 August 2020 03:04 UTC
Return-Path: <justingrant.ietf.public@gmail.com>
X-Original-To: calsify@ietfa.amsl.com
Delivered-To: calsify@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id BBDCE3A09B0 for <calsify@ietfa.amsl.com>; Sat, 1 Aug 2020 20:04:46 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.197
X-Spam-Level:
X-Spam-Status: No, score=-0.197 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id SdZ6xc1emjIU for <calsify@ietfa.amsl.com>; Sat, 1 Aug 2020 20:04:44 -0700 (PDT)
Received: from mail-ed1-x52a.google.com (mail-ed1-x52a.google.com [IPv6:2a00:1450:4864:20::52a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 683173A090C for <calsify@ietf.org>; Sat, 1 Aug 2020 20:04:44 -0700 (PDT)
Received: by mail-ed1-x52a.google.com with SMTP id v22so14139522edy.0 for <calsify@ietf.org>; Sat, 01 Aug 2020 20:04:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=zOiYrvsfhgi7JNZc1U7IT0xwC/x06GNdf72jiewpf/M=; b=ennt7U+YmSZjygnwWuEZ/gJzu3GNjZxNbb2sMOmMo1alPI+2q5npibshZMO4nIj9Yz B5Pt9h2BiI0vhEHaDpCEA8Ns5DJvK0GpGXYc8nNjvM5GhptjD2RFIB8ZJKnIV/R6VznS i0v/dPWQjDRk8272gI/BhecdgxKroxgUdILD00bJwV+Je2vRQwfpg0miX55Tggb/T1Om CsMhD+MUcaY84njdazmvWGIJ51AcQP6e8dR18WqmGt5uDenq8nHaCxN1NMG3M6oTEpEL IZP13B3vrxkLExGvjbu5tDz+wWNEmHxOlzDsJkEHwGW3GpGkS6g8gTuimZiCxYKSeCtq bTlg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=zOiYrvsfhgi7JNZc1U7IT0xwC/x06GNdf72jiewpf/M=; b=PtjJ+BQZuutdMZhsL3E166WyAlmQeFtyUzX6Y0Vn9n5ltzL3PslMm406iNPllU/bUp QkgCXOpElZPgJ/kllxtStflnL51g9aeJogBhZWNwnvU4l9bnKQEvHQ8PxeFMgBdxicsY jYLk4B6I5ZOOxTuA7xDiRldCUWzC5Ch8p2Em0qrwOdkxSH6nAOhldB7g6gTpRU1w5mjo CddE6uBm0bX1bOXtgOUxb6OUsPOIB1oL4DXNTlIEZQojwlxCE/lF35e9IHFI2hn7niEO VQed8Wy4/1yok//IzcJBJJ082h1dak+PUHpCjEnm6UyR1WgNtD6d7UjGwgq8x5y4LQQ+ hp2w==
X-Gm-Message-State: AOAM5312tmzd/wvhS94Wnmcm7oKsVETvXoLA3UojXK3DIlK2IkSe22Pe zt/YIGJVV49uXOnEebZUCD+a25wmwxbeKDR3yoA00XCJ
X-Google-Smtp-Source: ABdhPJwRb//6QxzWd2ANgoA2m6VUGtlYH8mPv1QFqXaFpFptfEc3cOze5czfvAz9R8S11rbnuTqfhb6rkFuTJADLTKA=
X-Received: by 2002:a50:ef08:: with SMTP id m8mr3029944eds.339.1596337482542; Sat, 01 Aug 2020 20:04:42 -0700 (PDT)
MIME-Version: 1.0
From: Justin Grant <justingrant.ietf.public@gmail.com>
Date: Sat, 01 Aug 2020 20:04:31 -0700
Message-ID: <CACy7CficiNXA_tb01c0=PWQTnXPVu_e7TgWAKUVPY-ow9C=3SQ@mail.gmail.com>
To: calsify@ietf.org
Content-Type: multipart/alternative; boundary="00000000000096b1a905abdc4816"
Archived-At: <https://mailarchive.ietf.org/arch/msg/calsify/JYBnpZVFtr6A0r5-l2gUv1pXGZo>
Subject: Re: [calsify] RFC 5545/JSCalendar questions from ECMAScript TC39 "Temporal" working group
X-BeenThere: calsify@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: <calsify.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/calsify>, <mailto:calsify-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/calsify/>
List-Post: <mailto:calsify@ietf.org>
List-Help: <mailto:calsify-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/calsify>, <mailto:calsify-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sun, 02 Aug 2020 03:04:47 -0000
Hi Neil - Daniel helped me get my calsify email subscription fixed, so I'm replying on the public list. Reading your response, I realize that I forgot to add one important piece of context: all my questions focus on a specific type (placeholder name is "LocalDateTime'-- see https://github.com/tc39/proposal-temporal/issues/700) that we're adding to Temporal which represents a specific UTC instant in a specific time zone. This is closest to "DATE-TIME - FORM #3: DATE WITH LOCAL TIME AND TIME ZONE REFERENCE" in RFC 5545, although there's a small difference in that Temporal's LocalDateTime type will know its UTC value and will derive the local date/time from the time zone and the UTC value. This was done so that this type could represent all real-world instants (other than leap seconds), including times during the "repeated hour" after a Fall DST transition. Temporal also has types that correspond to FORM #2: DATE WITH UTC TIME (called "Absolute" in Temporal) and FORM #1: DATE WITH LOCAL TIME (called "DateTime" in Temporal). Math with these types is straightforward because neither of them have any awareness of time zones or DST. The questions in https://github.com/tc39/proposal-temporal/issues/702 only relate to the LocalDateTime type where the time zone is known and DST transitions must be accounted for. > Q1. [...] If I'm understanding it correctly, I do not think your proposed alternative is acceptable because it applies the time component to the wall-clock time, which means that if you had an event with duration PT1H that started on a 1-hour DST-transition point it would be translated into an absolute duration of 0 hours or 2 hours, which is clearly wrong! e.g. I have an event that starts at 2019-03-31T02:45 in Europe/Berlin. I add a duration of PT1H in wall clock time to get 2019-03-31T03:45 in Europe/Berlin. However, those are the same time in UTC due to the DST transition, so the absolute duration becomes 0! Yep, to avoid that problem you can either add the time portion using exact time, or you can do the time-portion math with wall-clock time and then adjust the result for the difference in time zone offset. Either one works to adjust for the impact of the DST transition. The advantage of the latter approach is that if there's a DST disambiguation required, it happens at the endpoint rather than at the intermediate value. This used to be important because when I wrote that GitHub issue, LocalDateTime offered user-customizable disambiguation behavior in its arithmetic functions. Since then, we've decided to simply use the "use the earlier offset" disambiguation method that RFC 5545 uses, so Q1 is probably a non-issue now. It still matters when calculating differences between LocalDateTime values (Q4/Q5), though. > Q1. [...] I'm not sure why you think the disambiguation in the middle is going to be problematic for users; surely they generally won't notice where it happens? Here's an example: what should be the result of adding P1DT12H to 2020-03-07T02:30-08:00[America/Los_Angeles]. My understanding of RFC5545's algorithm is that we'd use the following steps: A) Add 1 calendar day. B) Add 12 exact hours (not clock hours) But the after step A, the local time is not valid because 2020-03-08T02:30 is in the middle of the hour skipped by a DST transition. My interpretation of RFC 5545 is that we'd interpret the invalid intermediate time by using the offset before the transition, so we'd end up with an intermediate value of 2020-03-08T03:30-07:00[America/Los_Angeles] and a final result of 2020-03-08T15:30-07:00[America/Los_Angeles]. Is this correct? > Q3. I don't think subtraction is well specified and probably wasn't deeply considered; it is basically only used for the offset of alerts before the start of the event and I think your proposal of subtracting absolute components first is very reasonable for the reason you gave. We should clarify this in the JSCalendar spec. Sounds great. We'll plan to continue using smallest-units-first order-of-operations for subtraction. > Q4. [...] Subtract hours/minutes first to get the same wall clock time, then calculate number of days difference to get a duration in weeks/days/hours/minutes/seconds. What should we do when the "same wall clock time" happens to be in the middle of an hour skipped by a Spring DST transition? See Q5 discussion below for more details. > Q5. I don't think I quite understand your question. You say you are "calculating differences between UTC values" but then the "difference ends inside a DST discontinuity" – UTC doesn't have DST, so this doesn't make sense. Could you please clarify? This is the inverse of Q1. In Q1 we add a Duration to a LocalDateTime and have to deal with a DST transition in the middle. Q5 is about calculating the Duration between two LocalDateTime values with a DST transition in the middle. My understanding of RFC 5545 is that there are two possible ways to calculate the Duration between two LocalDateTime values X and Y in the same time zone. Let's call them the "Addition Path" and "Subtraction Path". Addition Path A) Let D = Y - X ignoring any changes in time zone offset between X and Y B) Truncate the time portion of D, leaving only a date-only duration C) Let I = X+D. If I is an invalid time (e.g. the hour skipped when DST starts) then resolve by using the earlier offset, which will yield a time later than the discontinuity. D) Let T = the exact clock time difference between I and Y. E) Merge N and T into the result Duration Subtraction Path A) Let D = Y - X ignoring any changes in time zone offset between X and Y B) Truncate the time portion of D, leaving only a date-only duration C) Let I = Y-D. (Hence the name "Subtraction Path"). If I is an invalid time (e.g. the hour skipped when DST starts) then resolve by using the earlier offset, which will yield a time later than the discontinuity. D) Let T = the exact clock time difference between X and I. (The other path uses I and Y) E) Merge N and T into the result Duration Are both of these compliant with your understanding of RFC 5545? Is only one correct? Or is neither correct? One problem is that the Addition Path and the Subtraction Path can return different results when an endpoint is in the "repeated hour" after DST ends in the fall. For example, assume that X is 2020-10-31T01:30-07:00[America/Los_Angeles] and Y is 2020-11-01T01:30-08:00[America/Los_Angeles] (the "second" 1:30AM on the day DST ends). If we start from X, then we'd add one nominal day to get 2020-11-01T01:30-07:00[America/Los_Angeles] (the "first" 1:30AM), and then add one exact hour to get to the end. So the result is P1DT1H. But if we start from Y, then subtracting one nominal day from 2020-11-01T01:30-08:00[America/Los_Angeles] yields 2020-10-31T01:30-07:00[America/Los_Angeles]. There is no time remainder. So the result is P1D. Another problem is that the logic above can deliver unexpected results depending on the local time of the endpoints, even if neither of those endpoints are close to a DST transition. For example, using the "Addition Path" logic above, here's the durations that the following pairs of LocalDateTime values will return: - 2020-03-07T01:30-08:00[America/Los_Angeles] to 2020-03-08T13:30-07:00[America/Los_Angeles] => P1D12H - 2020-03-07T02:30-08:00[America/Los_Angeles] to 2020-03-08T14:30-07:00[America/Los_Angeles] => P1D11H (1 hour less because the intermediate time 2020-03-08T02:30 is resolved to 2020-03-08T03:30-07:00[America/Los_Angeles] before the exact time difference is calculated) - 2020-03-07T03:30-08:00[America/Los_Angeles] to 2020-03-08T15:30-07:00[America/Los_Angeles] => P1D12H Users probably won't be surprised to see divergent results in cases where the endpoints are within an hour of a DST transition. But what's unexpected is the variation in results caused by the intermediate result landing on an invalid time, even though neither of the endpoints are very close to the transition. Does this clarify the problems we're trying to resolve with Q5? *From: *<snip> *Date: *Thursday, July 30, 2020 at 6:49 PM *To: <snip>* *Subject: *Re: RFC 5545/JSCalendar questions from ECMAScript TC39 "Temporal" working group On Fri, 31 Jul 2020, at 05:10, Justin Grant wrote: Hi JSCalendar team – I’m part of the TC39 working group that’s working on the Temporal <https://github.com/tc39/proposal-temporal> proposal which will be the future date/time API for JavaScript. We’re planning to follow RFC 5545 for operations that add or subtract durations from date/time values. But we have some questions about how to interpret the iCalendar spec around edge cases when there’s a DST transition during the added or subtracted duration. [...] Hi Justin, I'm happy to answer some questions; your link was to the GitHub project rather than a specific issue, but I'm presuming it's https://github.com/tc39/proposal-temporal/issues/702 that you were referring to. I've copied this to the calsify (Calext WG) list <https://www.ietf.org/mailman/listinfo/calsify>, but encourage people to reply-all as you have had difficulty joining it. In answer to the questions in that issue, my understanding is: Q1. As specified in RFC5545 (and JSCalendar): - A duration does not have a time zone associated with it. It is just an abstract number of weeks/days/hours etc. - If you want to determine how long in absolute terms a duration with days/weeks is, this question only makes sense when you have a start date-time to apply it to. - A duration may be added or subtracted from a date-time. If the date-time does not have an associated time zone then this is very easy (it's just like UTC: 1 day is always exactly 24h). - Otherwise, as per the spec, you would add the weeks/days first to the calendar day/month/year. If the result is an ambiguous time due to DST, you resolve at this point. Then you add the absolute hours/minutes/seconds etc. – this cannot result in another ambiguity. There is only ambiguity mapping from TZ -> UTC, not UTC -> TZ. I think your implementation in (1) seems similar to this, but I have not looked at the source closely to confirm. I'm not sure why you think the disambiguation in the middle is going to be problematic for users; surely they generally won't notice where it happens? You just add the duration to the date-time and get a result. If I'm understanding it correctly, I do not think your proposed alternative is acceptable because it applies the time component to the wall-clock time, which means that if you had an event with duration PT1H that started on a 1-hour DST-transition point it would be translated into an absolute duration of 0 hours or 2 hours, which is clearly wrong! e.g. I have an event that starts at 2019-03-31T02:45 in Europe/Berlin. I add a duration of PT1H in wall clock time to get 2019-03-31T03:45 in Europe/Berlin. However, those are the same time in UTC due to the DST transition, so the absolute duration becomes 0! Q2. I don't think this issue arises when following the RFC5545 semantics above. Q3. I don't think subtraction is well specified and probably wasn't deeply considered; it is basically only used for the offset of alerts before the start of the event and I think your proposal of subtracting absolute components first is very reasonable for the reason you gave. We should clarify this in the JSCalendar spec. Q4. This is really an implementation question. The result is clearly only correct if you can add it to the start date and get back the end date again with the already defined semantics. You can either: - Just find the difference in absolute time and represent this as a duration in hours/minutes/seconds. - Subtract hours/minutes first to get the same wall clock time, then calculate number of days difference to get a duration in weeks/days/hours/minutes/seconds. Q5. I don't think I quite understand your question. You say you are "calculating differences between UTC values" but then the "difference ends inside a DST discontinuity" – UTC doesn't have DST, so this doesn't make sense. Could you please clarify? Cheers, Neil.
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Neil Jenkins
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Neil Jenkins
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Neil Jenkins
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Justin Grant
- Re: [calsify] RFC 5545/JSCalendar questions from … Neil Jenkins