Skip to content

Commit

Permalink
Add a timezonechange event to Window/WorkerGlobalScope
Browse files Browse the repository at this point in the history
The current timezone is visible to JavaScript and changes over time.
Changes may be useful to note, e.g., in a long-running calendar or mail
application that may want to update dates and times without refreshing
when the user resumes using the application after travel.
Currently, to accomplish that, a webapp would have to poll, e.g.,
by repeatedly calling `Intl.DateTimeFormat().resolvedOptions().timeZone`.
With this patch, an event would instead notify the application.

In this patch, the event has to run to completion before the new time zone
is visible to JavaScript. These semantics are taken to give users the
most consistency and ensure that UIs don't get in inconsistent states with
parts rendered wtih one timezone and parts with another.

This choice for consistency might be a relatively large burden for
implementations and may need to be revised. Some JavaScript implementations
do timezone calculations for Date by using OS APIs. These OS APIs are
always operating on the current timezone. To implement the semantics
that the new timezone does not take effect until the event handler starts
running, it would be necessary for these implementations to use an alternate
library for timezone calculations. Several such libraries exist.
  • Loading branch information
littledan committed Sep 15, 2017
1 parent 4aaacb7 commit 03f1dfc
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -2894,6 +2894,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-copydatablockbytes">CopyDataBlockBytes</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-createbytedatablock">CreateByteDataBlock</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-createdataproperty">CreateDataProperty</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment">DaylightSavingsTA</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma402/#sec-defaulttimezone">DefaultTimeZone</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-detacharraybuffer">DetachArrayBuffer</dfn> abstract operation</li>
<li>The <dfn data-x="js-EnqueueJob" data-x-href="https://tc39.github.io/ecma262/#sec-enqueuejob">EnqueueJob</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-enumerableownproperties">EnumerableOwnProperties</dfn> abstract operation</li>
Expand All @@ -2905,12 +2907,14 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x="js-HostPromiseRejectionTracker" data-x-href="https://tc39.github.io/ecma262/#sec-host-promise-rejection-tracker">HostPromiseRejectionTracker</dfn> abstract operation</li>
<li>The <dfn data-x="js-HostResolveImportedModule" data-x-href="https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule">HostResolveImportedModule</dfn> abstract operation</li>
<li>The <dfn data-x="js-InitializeHostDefinedRealm" data-x-href="https://tc39.github.io/ecma262/#sec-initializehostdefinedrealm">InitializeHostDefinedRealm</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma402/#datetimeformat-objects">Intl.DateTimeFormat</dfn> constructor</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-isaccessordescriptor">IsAccessorDescriptor</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-iscallable">IsCallable</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-isconstructor">IsConstructor</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-isdatadescriptor">IsDataDescriptor</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-isdetachedbuffer">IsDetachedBuffer</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-issharedarraybuffer">IsSharedArrayBuffer</dfn> abstract operation</li>
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-local-time-zone-adjustment">LocalTZA</dfn> abstract operation</li>
<li>The <dfn data-x="js-NewObjectEnvironment" data-x-href="https://tc39.github.io/ecma262/#sec-newobjectenvironment">NewObjectEnvironment</dfn> abstract operation</li>
<!-- the next set of Ordinary* abstract operations are in order of appearance -->
<li>The <dfn data-x-href="https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof">OrdinaryGetPrototypeOf</dfn> abstract operation</li>
Expand Down Expand Up @@ -15111,6 +15115,7 @@ interface <dfn>HTMLStyleElement</dfn> : <span>HTMLElement</span> {
<dd><code data-x="handler-window-onbeforeunload">onbeforeunload</code></dd>
<dd><code data-x="handler-window-onhashchange">onhashchange</code></dd>
<dd><code data-x="handler-window-onlanguagechange">onlanguagechange</code></dd>
<dd><code data-x="handler-window-ontimezonechange">ontimezonechange</code></dd>
<dd><code data-x="handler-window-onmessage">onmessage</code></dd>
<dd><code data-x="handler-window-onmessageerror">onmessageerror</code></dd>
<dd><code data-x="handler-window-onoffline">onoffline</code></dd>
Expand Down Expand Up @@ -88420,6 +88425,25 @@ dictionary <dfn>PromiseRejectionEventInit</dfn> : <span>EventInit</span> {

</ol>

<h5>Time zone changes</h5>

<p>JavaScript programs can observe the current time zone. <code>Date</code> uses the time zone
through the <code>LocalTZA</code> and <code>DaylightSavingsTA</code> algorithms.
<code>Intl.DateTimeFormat</code> uses the time zone in its <code>DefaultTimeZone</code> algorithm.
Although it is not explicitly stated in the JavaScript specification, user agents may update the
current time zone over the execution of a page as the user's time zone changes, providing
different results for these algorithms over time.</p>

<p>When a UA has a new time zone to present to JavaScript, as would be observable by any of
those algorithms, the user agent must first
<span>queue a task</span> to <span data-x="concept-event-fire">fire an event</span> named <code
data-x="event-timezonechange">timezonechange</code> at the <code>Window</code> or
<code>WorkerGlobalScope</code> object and wait until that task begins to be executed before
actually returning a new value.</p>

<p>The <span>task source</span> for this <span data-x="concept-task">task</span> is the
<span>DOM manipulation task source</span>.</p>

<div w-nodev>

<h4>Event loops</h4> <!-- <dfn>event loop</dfn> -->
Expand Down Expand Up @@ -89749,6 +89773,7 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn>OnBeforeUnloadEvent
<tr><td><dfn><code data-x="handler-window-onbeforeunload">onbeforeunload</code></dfn> <td> <code data-x="event-beforeunload">beforeunload</code>
<tr><td><dfn><code data-x="handler-window-onhashchange">onhashchange</code></dfn> <td> <code data-x="event-hashchange">hashchange</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onlanguagechange">onlanguagechange</code></dfn> <td> <code data-x="event-languagechange">languagechange</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-ontimezonechange">ontimezonechange</code></dfn> <td> <code data-x="event-timezonechange">timezonechange</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onmessage">onmessage</code></dfn> <td> <code data-x="event-message">message</code> <!-- new for postMessage -->
<tr><td><dfn><code data-x="handler-window-onmessageerror">onmessageerror</code></dfn> <td> <code data-x="event-messageerror">messageerror</code> <!-- new for SAB -->
<tr><td><dfn><code data-x="handler-window-onoffline">onoffline</code></dfn> <td> <code data-x="event-offline">offline</code> <!-- new -->
Expand Down Expand Up @@ -89876,6 +89901,7 @@ interface <dfn>WindowEventHandlers</dfn> {
attribute <span>OnBeforeUnloadEventHandler</span> <span data-x="handler-window-onbeforeunload">onbeforeunload</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onhashchange">onhashchange</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onlanguagechange">onlanguagechange</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-ontimezonechange">ontimezonechange</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onmessage">onmessage</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onmessageerror">onmessageerror</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onoffline">onoffline</span>;
Expand Down Expand Up @@ -96276,6 +96302,7 @@ interface <dfn>WorkerGlobalScope</dfn> : <span>EventTarget</span> {

attribute <span>OnErrorEventHandler</span> <span data-x="handler-WorkerGlobalScope-onerror">onerror</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onlanguagechange">onlanguagechange</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-ontimezonechange">ontimezonechange</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onoffline">onoffline</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-ononline">ononline</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onrejectionhandled">onrejectionhandled</span>;
Expand Down Expand Up @@ -96383,6 +96410,7 @@ interface <dfn>WorkerGlobalScope</dfn> : <span>EventTarget</span> {
<tbody>
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onerror">onerror</code></dfn> <td> <code data-x="event-error">error</code>
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onlanguagechange">onlanguagechange</code></dfn> <td> <code data-x="event-languagechange">languagechange</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-ontimezonechange">ontimezonechange</code></dfn> <td> <code data-x="event-timezonechange">timezonechange</code>
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onoffline">onoffline</code></dfn> <td> <code data-x="event-offline">offline</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-ononline">ononline</code></dfn> <td> <code data-x="event-online">online</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onrejectionhandled">onrejectionhandled</code></dfn> <td> <code data-x="event-rejectionhandled">rejectionhandled</code>
Expand Down Expand Up @@ -115083,6 +115111,7 @@ interface <dfn>External</dfn> {
<code data-x="handler-window-onbeforeunload">onbeforeunload</code>;
<code data-x="handler-window-onhashchange">onhashchange</code>;
<code data-x="handler-window-onlanguagechange">onlanguagechange</code>;
<code data-x="handler-window-ontimezonechange">ontimezonechange</code>;
<code data-x="handler-window-onmessage">onmessage</code>;
<code data-x="handler-window-onmessageerror">onmessageerror</code>;
<code data-x="handler-window-onoffline">onoffline</code>;
Expand Down Expand Up @@ -118123,6 +118152,12 @@ interface <dfn>External</dfn> {
<td> <code data-x="event-languagechange">languagechange</code> event handler for <code>Window</code> object
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-window-ontimezonechange"> <code data-x="">ontimezonechange</code>
<td> <code data-x="handler-window-ontimezonechange">body</code>
<td> <code data-x="event-timezonechange">timezonechange</code> event handler for <code>Window</code> object
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-onload"> <code data-x="">onload</code>
<td> <span data-x="handler-onload">HTML elements</span>
Expand Down Expand Up @@ -118998,6 +119033,12 @@ INSERT INTERFACES HERE
<td> Global scope objects
<td> Fired at the global scope object when the user's preferred languages change

<tr> <!-- timezonechange -->
<td> <dfn data-dfn-type="event" data-dfn-for="Window,WorkerGlobalScope" data-export=""><code data-x="event-timezonechange">timezonechange</code></dfn>
<td> <code>Event</code>
<td> Global scope objects
<td> Fired at the global scope object when the user's current timezone changes

<tr> <!-- load -->
<td> <dfn data-dfn-type="event" data-dfn-for="Window,HTMLElement" data-export=""><code data-x="event-load">load</code></dfn>
<td> <code>Event</code>
Expand Down

0 comments on commit 03f1dfc

Please sign in to comment.