Frozen Date objects?
On Wed, Jul 17, 2013 at 11:44 AM, Anne van Kesteren <annevk at annevk.nl> wrote:
Is it intentional that Date objects cannot be frozen?
Use case: exposing the time of an event through a Date object while not allowing fiddling with it.
I was told frozen is only for properties. That doesn't seem ideal.
Then IDL defines to always return a new Date object, which seems bad:
% <video>.startDate != <video>.startDate
true
Is there a better way?
Domenic Denicola wrote:
From: Anne van Kesteren [annevk at annevk.nl]
Is there a better way?
<video>.startDate() !==<video>.startDate()
Using a method instead of a getter is better style where the result is generated on each call, but doesn't get at Anne's question.
IIRC Mark has thoughts about freezing of Date objects, since inability to freeze Date.prototype leaves a side channel.
(BTW, Anne's righteous != and your !== are equivalent per that invariant :=P. More significant, neither will work as wanted with reference-type objects such as Dates. But that no-value-type-for-Date issue is a different topic from the one at issue, I hope!)
I believe exposing [[DateValue]]
as a (non-private) symbol-keyed property would do the trick, since Object.freeze
seems to set all property keys to non-writable/non-configurable.
This seems like it would be a backward-compatible change. But it's so simple I imagine it's been discussed before. I await hearing where it falls down...
From: Domenic Denicola [domenic at domenicdenicola.com]
This seems like it would be a backward-compatible change.
Well, OK, this is actually just false: code that previously did Object.freeze(dateObj); dateObj.setDays(3);
would no longer work as expected. I guess that might kill this idea?
Or can we hope that few enough people are freezing dates that this is an allowable break in backward-compat?
Can you explain why startDate was specified was a Date object? I've just
read the relevant portions of specification and I don't see any compelling
rationale. I did see the word "timestamp" used in a number of places, but
that contradicts the value type of event.timeStamp, which is |readonly
attribute DOMTimeStamp|—I make this comparison, because I would assume all
things described as "timestamp" would have the same value type. If
startDate were readonly attribute DOMTimeStamp
(or more appropriately:
{[[Value]]: ..., [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false}
), then user code could create a Date object if it
needed to or calculate the difference between some event's timeStamp and
the startDate, etc.
Exposing [[DateValue]] as a property does not really scale. What about [[MapData]]? What about private state stored in a closure or a WeakMap?
This can either be done by exposing an object that has the same interface as Date. This could throw on set or it could skip the set methods entirely. If you want instanceof to work then all the methods needs to be overridden.
On Jul 17, 2013, at 12:41 PM, Brendan Eich wrote:
Domenic Denicola wrote:
From: Anne van Kesteren [annevk at annevk.nl]
Is there a better way?
<video>.startDate() !==<video>.startDate()
Using a method instead of a getter is better style where the result is generated on each call, but doesn't get at Anne's question.
IIRC Mark has thoughts about freezing of Date objects, since inability to freeze Date.prototype leaves a side channel.
Didn't we discuss making the [[DateValue]] immutable when a Date object is non-extensible? I see this isn't currently in the ES6 draft. Also, thinking about it now, that seems like quite a one-off hack.
One of the ES6 "issues" I have on the agenda for the next TC39 meeting is "Does Object.freeze need an extensibility hook?"
This issue was motivated by the fact that Object.freeze([1,2,3]) gives you a read-only array, while Object.freeze(new Float64Array([1,2,3])) at best gives you a typed array instance with writable elements (some existing implementations actually throw when you try to freeze a typed array).
This seems like a surprising inconsistency if you are thinking in terms of array abstractions. If Object.freeze is how you make an "array" immutable why shouldn't it work on typed arrays? Isn't whether elements are implemented as properties or as slots in a buffer just an implementation detail from the perspective of the abstraction.
This is similar to the Date issue.
On possibility is to add an extensibility hook to Object.freeze. It could be specified to call a @@freeze method on the target object (if it has one). A hook method could then take any appropriate action, such as setting an internal immutable flag.
On 7/17/2013 1:30 PM, Allen Wirfs-Brock wrote:
Didn't we discuss making the [[DateValue]] immutable when a Date object is non-extensible? I see this isn't currently in the ES6 draft. Also, thinking about it now, that seems like quite a one-off hack.
It also brings up the question of, for example, should freezing a Map
cause [[MapData]] to be frozen? I think the argument for [[MapData]] and
[[DateValue]] is the same, either way. Similarly, what about freezing a
RegExp? Should that not prevent regexp.compile()
?
On Wed, Jul 17, 2013 at 1:04 PM, Rick Waldron <waldron.rick at gmail.com> wrote:
Can you explain why startDate was specified was a Date object?
Because that's how JavaScript represents time? Event.timeStamp was supposed to be a Date object too: www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html Not sure why it was not implemented that way.
I don't really follow your line of reasoning. Existing APIs use a mix of callbacks and events. Should we not switch to promises where we can, but rather stick with precedent?
Anne van Kesteren wrote:
On Wed, Jul 17, 2013 at 1:04 PM, Rick Waldron<waldron.rick at gmail.com> wrote:
Can you explain why startDate was specified was a Date object?
Because that's how JavaScript represents time?
No, time is stored as milliseconds after the epoch in a number (IEEE double).
A Date object includes position on planet and timezone politics (see getTimezoneOffset).
A Date object can be constructed from a timestamp number. A timestamp number is cheaper in fast VMs. So perhaps a timestamp number wins.
A timestamp number gives a universal time coordinate, as noted, though, so the question may come down to whether video elements should have timezone-specific start dates, for some reason I'm missing (interop or developer ergonomics or whatever; interop would seem to want UTC).
Event.timeStamp was supposed to be a Date object too: www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html Not sure why it was not implemented that way.
That spec says it is a Date object:
timeStamp This read-only property is a Date object.
I don't really follow your line of reasoning. Existing APIs use a mix of callbacks and events. Should we not switch to promises where we can, but rather stick with precedent?
See above. Who says all precedents in specs are good hasn't been paying attention :-P. And in particular, a Date object is not merely a representation of time.
On Wed, Jul 17, 2013 at 4:40 PM, Anne van Kesteren <annevk at annevk.nl> wrote:
On Wed, Jul 17, 2013 at 1:04 PM, Rick Waldron <waldron.rick at gmail.com> wrote:
Can you explain why startDate was specified was a Date object?
Because that's how JavaScript represents time?
Brendan's response is much nicer then mine.
Event.timeStamp was supposed to be a Date object too: www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html Not sure why it was not implemented that way.
I don't fully understand the point your trying to make, are you telling me that these:
...Are not correct?
I don't really follow your line of reasoning.
I apologize, let me try to clarify:
Time and/or timestamps represented as milliseconds since epoch, in the form of a number, is useful for:
- calculating time differences with math (without coercing the object into a milliseconds number)
- creating new Date objects if such a thing is necessary for the program
- being the value of a property on a frozen object
- being the value of a property who's descriptor is {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}
3 & 4 seem to be what you were looking for? 2 & 3 are just nice to have.
Existing APIs use a mix of callbacks and events. Should we not switch to promises where we can, but rather stick with precedent?
The right paradigm for the job? I don't know what this has to do with the subject of Date objects and epoch times, but if I had to guess, I'd say you're trying to make my previous comments appear poorly conceived (in the name of progress) because I used the word "precedent". Are you sure you want to pick that fight?
From the perspective of someone with extensive practitioner experience developing software for a variety of platforms, including web based video programming with Popcorn.js (and without) and a variety of products built on that framework, I had hoped to offer my sincerest, most constructive feedback—but you're the boss, applesauce.
On Wed, Jul 17, 2013 at 1:58 PM, Brendan Eich <brendan at mozilla.com> wrote:
Anne van Kesteren wrote:
Because that's how JavaScript represents time?
No, time is stored as milliseconds after the epoch in a number (IEEE double).
A Date object includes position on planet and timezone politics (see getTimezoneOffset).
A Date object can be constructed from a timestamp number. A timestamp number is cheaper in fast VMs. So perhaps a timestamp number wins.
A timestamp number gives a universal time coordinate, as noted, though, so the question may come down to whether video elements should have timezone-specific start dates, for some reason I'm missing (interop or developer ergonomics or whatever; interop would seem to want UTC).
That makes sense. I think we moved towards Date because it exposes more time-oriented API than number (doh). I didn't know number was the preferred format for something without timezone.
Event.timeStamp was supposed to be a Date object too: www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html Not sure why it was not implemented that way.
That spec says it is a Date object:
timeStamp This read-only property is a Date object.
Right, but we all use a number (and newer specs reflect that). Per your explanation above that makes sense and I guess we should continue to do that then. Not sure if startTime can still be changed.
On Wed, Jul 17, 2013 at 2:50 PM, Rick Waldron <waldron.rick at gmail.com> wrote:
On Wed, Jul 17, 2013 at 4:40 PM, Anne van Kesteren <annevk at annevk.nl> wrote:
Event.timeStamp was supposed to be a Date object too: www.w3.org/TR/DOM-Level-2-Events/ecma-script-binding.html Not sure why it was not implemented that way.
I don't fully understand the point your trying to make, are you telling me that these:
...Are not correct?
I merely tried to illustrate we were not the first to consider using Date for these things. At least on the non-TC39 side, Event.timeStamp not being Date is seen as not that great. Now this point-of-view might be horribly mistaken, but it exists. Should be easy to do the way Brendan outlined for anything new though.
Also, I very much appreciate your feedback (and I'm not the boss), I just don't always grasp it right away ;-) Give these miscommunications some time, eventually this web platform thing will be better for it.
Anne van Kesteren wrote:
Right, but we all use a number (and newer specs reflect that). Per your explanation above that makes sense and I guess we should continue to do that then. Not sure if startTime can still be changed.
I hope so. At the very least, can you forward my reply to the editors responsible for those Date uses?
On Wed, Jul 17, 2013 at 3:24 PM, Brendan Eich <brendan at mozilla.com> wrote:
Anne van Kesteren wrote:
Right, but we all use a number (and newer specs reflect that). Per your explanation above that makes sense and I guess we should continue to do that then. Not sure if startTime can still be changed.
I hope so. At the very least, can you forward my reply to the editors responsible for those Date uses?
www.w3.org/Bugs/Public/show_bug.cgi?id=22714 (I'm not aware of usage beyond HTML, but I'll be on the lookout.)
Having gone through all this, for the case I was considering it for it still seems relevant and the questions remain. Namely, communicating to the end-user notification system at what point an event for which the notification is generated will be happening or has happened. And exposing the communicated time back to the developer.
On Wed, Jul 17, 2013 at 3:37 PM, Anne van Kesteren <annevk at annevk.nl> wrote:
Having gone through all this, for the case I was considering it for it still seems relevant and the questions remain. Namely, communicating to the end-user notification system at what point an event for which the notification is generated will be happening or has happened. And exposing the communicated time back to the developer.
I'm still confused as to when it's correct for an API to return a Date object.
At least in SpiderMonkey it's impossible to create Date objects that represent a timezone other than the user's current timezone. I.e. getTimezoneOffset returns the same value for all object instances. Maybe that's a limitation that's implementation specific and is there because no current JS APIs happen to need it?
But that makes it impossible to create, for example a Calendar API which returns a Date object which represents the time and timezone of when a particular event is going to happen.
So at least in SpiderMonkey a Date object is not a time+timezone, but rather simply a timestamp whose API always represents that timestamp in a particular (but possibly changing) timezone.
Is this simply a SpiderMonkey bug? Do we expect JS code to be able to handle Date objects representing timezones other than the user's current timezone?
Another question is if it's wrong of the Task Scheduler API to use Date objects in the ScheduledTask API since the time that a task is scheduled sometimes represents a point-in-time rather than a particular time+timezone
On 7/17/2013 4:36 PM, Jonas Sicking wrote:
Is this simply a SpiderMonkey bug? Do we expect JS code to be able to handle Date objects representing timezones other than the user's current timezone?
What happens if the timezone changes between the creation of two Date objects, such as for daylight savings or the user changes their system timezone?
On Jul 17, 2013, at 13:58 , Brendan Eich <brendan at mozilla.com> wrote:
No, time is stored as milliseconds after the epoch in a number (IEEE double).
A Date object includes position on planet and timezone politics (see getTimezoneOffset).
No, it doesn't. Any time zone information used by getTimeZoneOffset and other non-UTC Date API is based on time zone information in the environment: the "local time zone" is typically what the user has told the OS to use. A Date object itself only wraps the time value.
On 7/17/2013 4:42 PM, Brandon Benvie wrote:
On 7/17/2013 4:36 PM, Jonas Sicking wrote:
Is this simply a SpiderMonkey bug? Do we expect JS code to be able to handle Date objects representing timezones other than the user's current timezone?
What happens if the timezone changes between the creation of two Date objects, such as for daylight savings or the user changes their system timezone?
Having just tested this, it is possible in SM to get two Dates that report different values from getTimezoneOffset.
On Jul 17, 2013, at 16:51 , Brandon Benvie <bbenvie at mozilla.com> wrote:
On 7/17/2013 4:42 PM, Brandon Benvie wrote:
What happens if the timezone changes between the creation of two Date objects, such as for daylight savings or the user changes their system timezone?
Having just tested this, it is possible in SM to get two Dates that report different values from getTimezoneOffset.
How?
On Wed, Jul 17, 2013 at 4:42 PM, Brandon Benvie <bbenvie at mozilla.com> wrote:
What happens if the timezone changes between the creation of two Date objects, such as for daylight savings or the user changes their system timezone?
I believe SpiderMonkey in Firefox Desktop until recently would grab the snapshot of the user's timezone on browser startup, and then never change it until the browser was shut down.
Now it seems to update that snapshot now and then in some pattern that isn't obvious to me. When that happens the timezone offset for all Date instances all change.
On 7/17/2013 4:54 PM, Norbert Lindenberg wrote:
On Jul 17, 2013, at 16:51 , Brandon Benvie <bbenvie at mozilla.com> wrote:
Having just tested this, it is possible in SM to get two Dates that report different values from getTimezoneOffset.
How?
Create a Date object, change the system timezone, create a second Date object. They reflect the timezone at time of Date object creation, not a static one.
On Thu, Jul 18, 2013 at 1:55 AM, Jonas Sicking <jonas at sicking.cc> wrote:
I believe SpiderMonkey in Firefox Desktop until recently would grab the snapshot of the user's timezone on browser startup, and then never change it until the browser was shut down.
Now it seems to update that snapshot now and then in some pattern that isn't obvious to me. When that happens the timezone offset for all Date instances all change.
We update the timezone info each time a new global is created: mxr.mozilla.org/mozilla-central/source/js/src/jscompartment.cpp#90
On Wed, Jul 17, 2013 at 7:55 PM, Brandon Benvie <bbenvie at mozilla.com> wrote:
Create a Date object, change the system timezone, create a second Date object. They reflect the timezone at time of Date object creation, not a static one.
That doesn't reflect what I'm seeing. I see the timezone of all Date objects changing whenever the timezone is update. Existing instances are also changed.
On 7/17/2013 4:55 PM, Jonas Sicking wrote:
I believe SpiderMonkey in Firefox Desktop until recently would grab the snapshot of the user's timezone on browser startup, and then never change it until the browser was shut down.
Now it seems to update that snapshot now and then in some pattern that isn't obvious to me. When that happens the timezone offset for all Date instances all change.
Oh I see what happened. The time zone reported from getTimezoneOffset
wasn't updated until a new Date object is created. So the original one
would report the old timezone up until the first time you do new Date
and then both the old one and the new one are changed.
On Jul 17, 2013, at 16:59 , Jonas Sicking <jonas at sicking.cc> wrote:
That doesn't reflect what I'm seeing. I see the timezone of all Date objects changing whenever the timezone is update. Existing instances are also changed.
Seeing getTimezoneOffset change for all Date objects is what I expect because none of them actually have a time zone - getTimezoneOffset uses the one local time zone that the JavaScript engine maintains somewhere.
This is unfortunate. It does answer Anne's question though, in an unpleasant way: Date instances cannot be immutable; they can be at best readonly. Despite lack of any authorization to track the user's position, Date instances make visible their machine's mutable current position, as coarsened to the timezone.
Just as a Date instance snapshots the time when it was created, I think it should also snapshot the timezone where it was created. Then it would be possible to contemplate immutable Date instances. Only the Date constructor should give the ability to sense changes to time and place, not the instances it makes. Virtualizing the Date constructor (replacing it with a faux Date constructor) should be adequate to create illusory paths through time and space, without needing to wrap all the instances it creates with faux Date instances.
On Jul 17, 2013, at 16:48 , Jonas Sicking <jonas at sicking.cc> wrote:
And then there is the thread started at 3, and this particular email 4 which seems to conclude that Date objects in fact are just timestamps, and not timezone+timestamp.
And then there was this thread, which ended with your largely correct idea for how to implement floating time alarms:
On Jul 17, 2013, at 17:27 , Mark S. Miller <erights at google.com> wrote:
This is unfortunate. It does answer Anne's question though, in an unpleasant way: Date instances cannot be immutable; they can be at best readonly. Despite lack of any authorization to track the user's position, Date instances make visible their machine's mutable current position, as coarsened to the timezone.
Just as a Date instance snapshots the time when it was created, I think it should also snapshot the timezone where it was created. Then it would be possible to contemplate immutable Date instances. Only the Date constructor should give the ability to sense changes to time and place, not the instances it makes. Virtualizing the Date constructor (replacing it with a faux Date constructor) should be adequate to create illusory paths through time and space, without needing to wrap all the instances it creates with faux Date instances.
If you want to lock down the behavior of getTimezoneOffset, or create illusory behavior, you don't need to do anything to Date instances - all you need to do is change the implementation of LocalTZA and DaylightSavingTA.
On the other hand, the behavior in Firefox was made more dynamic under the assumption that users prefer to see date and time information in their current time zone, not in the time zone they were in when they launched their browser. bugzilla.mozilla.org/show_bug.cgi?id=796523
Norbert Lindenberg wrote:
On Jul 17, 2013, at 13:58 , Brendan Eich<brendan at mozilla.com> wrote:
No, time is stored as milliseconds after the epoch in a number (IEEE double).
A Date object includes position on planet and timezone politics (see getTimezoneOffset).
No, it doesn't. Any time zone information used by getTimeZoneOffset and other non-UTC Date API is based on time zone information in the environment: the "local time zone" is typically what the user has told the OS to use. A Date object itself only wraps the time value.
No. This is not well-specified by ECMA-262, implementations do crack time to date fields in Date instances, and one's timezone can change in a running system (say a Firefox OS phone one takes on a plane).
Jonas Sicking wrote:
And then there is the thread started at 3, and this particular email 4 which seems to conclude that Date objects in fact are just timestamps, and not timezone+timestamp.
First, this is not well-specified and implementations do extract Date "fields" from time number based on current timezone and DST offset (which can change).
Second, a Date is a pretty fat and inefficient way to represent a time number. Let the consumer decide whether to create a new object. Some web specs get this right.
Norbert Lindenberg wrote:
On Jul 17, 2013, at 17:27 , Mark S. Miller<erights at google.com> wrote:
This is unfortunate. It does answer Anne's question though, in an unpleasant way: Date instances cannot be immutable; they can be at best readonly. Despite lack of any authorization to track the user's position, Date instances make visible their machine's mutable current position, as coarsened to the timezone.
Just as a Date instance snapshots the time when it was created, I think it should also snapshot the timezone where it was created. Then it would be possible to contemplate immutable Date instances. Only the Date constructor should give the ability to sense changes to time and place, not the instances it makes. Virtualizing the Date constructor (replacing it with a faux Date constructor) should be adequate to create illusory paths through time and space, without needing to wrap all the instances it creates with faux Date instances.
If you want to lock down the behavior of getTimezoneOffset, or create illusory behavior,
Mark wants to do this from JS, not from under the hood (usually via C++) using VM internal APIs.
you don't need to do anything to Date instances - all you need to do is change the implementation of LocalTZA and DaylightSavingTA.
Those are spec-internal helper functions, analogous to hidden-from-JS-"user-code" VM internal functions.
On the other hand, the behavior in Firefox was made more dynamic under the assumption that users prefer to see date and time information in their current time zone, not in the time zone they were in when they launched their browser. bugzilla.mozilla.org/show_bug.cgi?id=796523
Right. People travel. DST happens (too early these days in the US!) and ends.
On Jul 17, 2013, at 20:29 , Brendan Eich <brendan at mozilla.com> wrote:
Norbert Lindenberg wrote:
On Jul 17, 2013, at 13:58 , Brendan Eich<brendan at mozilla.com> wrote:
No, time is stored as milliseconds after the epoch in a number (IEEE double).
A Date object includes position on planet and timezone politics (see getTimezoneOffset).
No, it doesn't. Any time zone information used by getTimeZoneOffset and other non-UTC Date API is based on time zone information in the environment: the "local time zone" is typically what the user has told the OS to use. A Date object itself only wraps the time value.
No. This is not well-specified by ECMA-262, implementations do crack time to date fields in Date instances, and one's timezone can change in a running system (say a Firefox OS phone one takes on a plane).
Implementations are free to cache all kinds of things to improve performance, but they still have to produce the specified behavior. The behavior of Date non-UTC methods is defined in terms of a single time value and conversion functions that rely on local time zone adjustment and local daylight saving time adjustment. The spec text varies a bit between ES5 and ES6, but my interpretation of both would be that when the local time zone changes, the results of LocalTZA, DaylightSavingTA, and LocalTime all change, so caches based on them have to be invalidated.
If some or all implementations have interpreted that differently, then the spec needs to be clarified one way or another.
Norbert
On Jul 17, 2013, at 20:35 , Brendan Eich <brendan at mozilla.com> wrote:
Norbert Lindenberg wrote:
On Jul 17, 2013, at 17:27 , Mark S. Miller<erights at google.com> wrote:
This is unfortunate. It does answer Anne's question though, in an unpleasant way: Date instances cannot be immutable; they can be at best readonly. Despite lack of any authorization to track the user's position, Date instances make visible their machine's mutable current position, as coarsened to the timezone.
Just as a Date instance snapshots the time when it was created, I think it should also snapshot the timezone where it was created. Then it would be possible to contemplate immutable Date instances. Only the Date constructor should give the ability to sense changes to time and place, not the instances it makes. Virtualizing the Date constructor (replacing it with a faux Date constructor) should be adequate to create illusory paths through time and space, without needing to wrap all the instances it creates with faux Date instances.
If you want to lock down the behavior of getTimezoneOffset, or create illusory behavior,
Mark wants to do this from JS, not from under the hood (usually via C++) using VM internal APIs.
Sorry, I missed that bit.
In that case, you'd have to replace the Date function and all Date methods that depend on the local time zone: Date as a function; the Date constructor for 2 or more arguments; parse; toString & friends; getFullYear, getMonth, and their non-UTC friends; getTimezoneOffset, setMilliseconds, setSeconds, and their non-UTC friends. That's a lot more work, but it still doesn't affect Date instances directly.
Norbert
On Thu, Jul 18, 2013 at 12:44 PM, Norbert Lindenberg < ecmascript at lindenbergsoftware.com> wrote:
On Jul 17, 2013, at 20:35 , Brendan Eich <brendan at mozilla.com> wrote:
Norbert Lindenberg wrote:
On Jul 17, 2013, at 17:27 , Mark S. Miller<erights at google.com> wrote:
This is unfortunate. It does answer Anne's question though, in an unpleasant way: Date instances cannot be immutable; they can be at best readonly. Despite lack of any authorization to track the user's position, Date instances make visible their machine's mutable current position, as coarsened to the timezone.
Just as a Date instance snapshots the time when it was created, I think it should also snapshot the timezone where it was created. Then it would be possible to contemplate immutable Date instances. Only the Date constructor should give the ability to sense changes to time and place, not the instances it makes. Virtualizing the Date constructor (replacing it with a faux Date constructor) should be adequate to create illusory paths through time and space, without needing to wrap all the instances it creates with faux Date instances.
If you want to lock down the behavior of getTimezoneOffset, or create illusory behavior,
Mark wants to do this from JS, not from under the hood (usually via C++) using VM internal APIs.
Sorry, I missed that bit.
In that case, you'd have to replace the Date function and all Date methods that depend on the local time zone: Date as a function; the Date constructor for 2 or more arguments; parse; toString & friends; getFullYear, getMonth, and their non-UTC friends; getTimezoneOffset, setMilliseconds, setSeconds, and their non-UTC friends. That's a lot more work, but it still doesn't affect Date instances directly.
Or the spec could redefine those functions to use an instance property
lookup which defines the appropriate timezone. I'd suggested this several
months back, and partly for this reason (it's also a much needed feature,
and more idiomatically javascripty). Having Dates depend on an implicit
global timezone is madness. Using a prototype property would allow Date
objects to have their timezone explicitly set or modified, and they'd be
possible to freeze. Date.prototype.timezone
(or whatever it would be
called) could then float with the system's timezone (or be explicitly set
and/or frozen too). Oh, and this could be cleanly polyfilled to make dates
and timezones suck less today. I still can't think of any downsides.
+1. We should do something along these lines. I especially agree with "Having [X] depend on an implicit global [Y] is madness" for any X and Y.
Domenic Denicola wrote:
I believe exposing
[[DateValue]]
as a (non-private) symbol-keyed property would do the trick, sinceObject.freeze
seems to set all property keys to non-writable/non-configurable.This seems like it would be a backward-compatible change. But it's so simple I imagine it's been discussed before. I await hearing where it falls down...
Last time I asked, Object.freeze
& friends don't affect existing symbol properties on an object (though new ones can't be added). I think this is pretty important. Has this changed?
Nathan
Erik Arvidsson wrote:
This can either be done by exposing an object that has the same interface as Date. This could throw on set or it could skip the set methods entirely. If you want instanceof to work then all the methods needs to be overridden.
Overriding the methods on a real date object (or one that inherits from Date but was constructed with the Date constructor) won't work because then Date.prototype.set* methods would still be able to mutate the internal date by calling them explicitly:
var readOnlyDate = getReadOnlyDate(); readOnlyDate.setHours !== Date.prototype.setHours; // => true Date.prototype.setHours.call(readOnlyDate, 2); // oops
Also, I don't think insanceof
should be used to check Dates. If Object.prototype.toString is used, the object just needs to be tagged as a "Date" and the function used to determine whether an object is a date needs to take into consideration "~Date" as well.
Nathan
On Jul 19, 2013, at 7:53 AM, Nathan Wall wrote:
Domenic Denicola wrote:
I believe exposing
[[DateValue]]
as a (non-private) symbol-keyed property would do the trick, sinceObject.freeze
seems to set all property keys to non-writable/non-configurable.This seems like it would be a backward-compatible change. But it's so simple I imagine it's been discussed before. I await hearing where it falls down...
Last time I asked,
Object.freeze
& friends don't affect existing symbol properties on an object (though new ones can't be added). I think this is pretty important. Has this changed?
Object.freeze and friends affect all properties in the same way, including symbol keyed properties.
Allen Wirfs-Brock wrote:
Nathan Wall wrote:
Last time I asked,
Object.freeze
& friends don't affect existing symbol properties on an object (though new ones can't be added). I think this is pretty important. Has this changed?Object.freeze and friends affect all properties in the same way, including symbol keyed properties.
Am I thinking of the behavior that was discussed for private symbols when they were a possibility?
Nathan
Yes
On Wed, Jul 17, 2013 at 5:11 PM, Norbert Lindenberg <ecmascript at lindenbergsoftware.com> wrote:
On Jul 17, 2013, at 16:59 , Jonas Sicking <jonas at sicking.cc> wrote:
On Wed, Jul 17, 2013 at 7:55 PM, Brandon Benvie <bbenvie at mozilla.com> wrote:
On 7/17/2013 4:54 PM, Norbert Lindenberg wrote:
On Jul 17, 2013, at 16:51 , Brandon Benvie <bbenvie at mozilla.com> wrote:
On 7/17/2013 4:42 PM, Brandon Benvie wrote:
On 7/17/2013 4:36 PM, Jonas Sicking wrote:
Is this simply a SpiderMonkey bug? Do we expect JS code to be able to handle Date objects representing timezones other than the user's current timezone?
What happens if the timezone changes between the creation of two Date objects, such as for daylight savings or the user changes their system timezone?
Having just tested this, it is possible in SM to get two Dates that report different values from getTimezoneOffset.
How?
Norbert
Create a Date object, change the system timezone, create a second Date object. They reflect the timezone at time of Date object creation, not a static one.
That doesn't reflect what I'm seeing. I see the timezone of all Date objects changing whenever the timezone is update. Existing instances are also changed.
Seeing getTimezoneOffset change for all Date objects is what I expect because none of them actually have a time zone - getTimezoneOffset uses the one local time zone that the JavaScript engine maintains somewhere.
I still don't feel like I have a clear answer to two fundamental questions when designing DOM specs:
- Is it ever appropriate to return Date objects from methods in the DOM? If so, in what circumstances. Two cases where we are currently considering using Date objects are:
- When the event related to a Notification [1] happened, or is set to happen. What we need here is a timezone-less timestamp.
- When expressing when a scheduled task [2] is set to fire. The task is set to fire at a designated point in time. I.e. a timezone-less timestamp. Though in the future it would be nice to support scheduled tasks that are set to happen in a particular time+timezone.
- Is it ever appropriate to return a Date object from a "readonly" property. This seems like a bad idea if we can't freeze it since it would mean that if someone modifies the Date object, all other consumers would see a changed date, and the property wouldn't really be readonly. We could return a new Date instance each time the getter is run, but that would mean that x.prop !== x.prop which seems surprising.
However this thread does seem to make it clear that it is inappropriate to design an API which accepts Date objects as input, if that API wants to enable the caller to provide a time+timezone. This since it is not possible to create Date objects for arbitrary timezones, but rather only for the users current timezone. So a caller couldn't specify timezone.
Possibly this will be remedied in the future. But for APIs that are shipping in the near future, this limitation seems to exist.
Such an API could instead separate the timestamp and timezone inputs. Potentially the timestamp part could use a Date object. Again, it's unclear if using a Date object to represent the timestamp would be appropriate.
A concrete example here is the create-new-scheduled-task API in [3]. If we wanted to expand this API to support specifying a timezone in addition to the timestamp, we would have to add a separate argument, rather than simply relying on Date objects. And possibly we should stop using Date objects entirely, even if we don't want timezone support.
[1] notifications.spec.whatwg.org/#notification [2] www.w3.org/2012/sysapps/web-alarms/#interface-scheduledtask [3] www.w3.org/2012/sysapps/web-alarms/#taskscheduler
/ Jonas
For all of these, what benefits to Date objects provide over just using numbers?
On Jul 21, 2013, at 11:05 PM, Jonas Sicking wrote:
I still don't feel like I have a clear answer to two fundamental questions when designing DOM specs:
- Is it ever appropriate to return Date objects from methods in the DOM? If so, in what circumstances. Two cases where we are currently considering using Date objects are: ...
- Is it ever appropriate to return a Date object from a "readonly" property.
How about :
- Is it ever appropriate for a DOM API to accept and retain a reference to a Date object?
The timevalue of a Date object that was passed to a DOM API can be modified by the original client after the DOM call returns. If the DOM has retained and uses a reference to the Date object it will see the modified timevalue rather than the originally pass timevalue.
On Mon, Jul 22, 2013 at 7:07 AM, Mark S. Miller <erights at google.com> wrote:
For all of these, what benefits to Date objects provide over just using numbers?
That is indeed the question. I think we attempted to use Date objects in an effort to be more "javascripty" and less "DOM doing it's own thing".
But this thread is leading me to believe that using Date objects in the DOM is possibly never appropriate.
/ Jonas
On Mon, Jul 22, 2013 at 7:42 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
On Jul 21, 2013, at 11:05 PM, Jonas Sicking wrote:
I still don't feel like I have a clear answer to two fundamental questions when designing DOM specs:
- Is it ever appropriate to return Date objects from methods in the DOM? If so, in what circumstances. Two cases where we are currently considering using Date objects are:
...
- Is it ever appropriate to return a Date object from a "readonly" property.
How about :
- Is it ever appropriate for a DOM API to accept and retain a reference to a Date object?
We could even generalize it to:
- Is it ever appropriate for a DOM API to accept a reference to a Date object.
Even if we just take a snapshot of the value returned by .getTime() and retain that snapshot, is that really beneficial to taking a numeric timestamp?
The feedback in this thread seems to indicate "no" on all three?
/ Jonas
On Jul 22, 2013, at 9:42 AM, Jonas Sicking wrote:
On Mon, Jul 22, 2013 at 7:42 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
- Is it ever appropriate for a DOM API to accept and retain a reference to a Date object?
We could even generalize it to:
- Is it ever appropriate for a DOM API to accept a reference to a Date object.
Even if we just take a snapshot of the value returned by .getTime() and retain that snapshot, is that really beneficial to taking a numeric timestamp?
The feedback in this thread seems to indicate "no" on all three?
However, just like you you guys trying to define DOM APIs, many JavaScript programmers will not be aware of these subtleties and expect to be able to use Date objects with these APIs. I would suggest, the following conventions:
- APIs should accept Date objects as inputs, but when doing do so they should only retain and use the timevalue wrapped by the date object.
- APIs may return Date objects but they should always be newly created instances and never retain references to them. An API client might mutate such returned Date objects but that's really the clients business and it will have no impact upon the DOM.
In addition, for APIs that take "dates" as input might consider accepting both Date objects and Numbers that are interpreted as timevalues. That should probably be a design decision that is consistently applied to all DOM APIS.
Allen's suggesting for accepting Date objects should fall out pretty naturally as long as the APIs stick to the standard JS style of doing ToNumber on expected-to-be-number arguments.
On Mon, Jul 22, 2013 at 10:28 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
- APIs should accept Date objects as inputs, but when doing do so they should only retain and use the timevalue wrapped by the date object.
Makes sense. And in fact, like Dominic points out, that will simply follow automatically when accepting a numeric timestamp since WebIDL will always use ToNumber to coerce any passed in value to a number.
- APIs may return Date objects but they should always be newly created instances and never retain references to them. An API client might mutate such returned Date objects but that's really the clients business and it will have no impact upon the DOM.
The emails in this thread seems to indicate that we should in fact not return Date objects ever (though like any rule, I could imagine there being exceptions). Instead we should simply return numeric timestamps.
However, we should of course expect other APIs, such as ones in JS libraries, will use Date objects. The best ways to deal with that is through your rule 1) above. I.e. accepting Date objects in addition to numeric timestamps in input.
On Monday, July 22, 2013, Jonas Sicking wrote:
The emails in this thread seems to indicate that we should in fact not return Date objects ever (though like any rule, I could imagine there being exceptions). Instead we should simply return numeric timestamps.
However, we should of course expect other APIs, such as ones in JS libraries, will use Date objects. The best ways to deal with that is through your rule 1) above. I.e. accepting Date objects in addition to numeric timestamps in input.
Yes, just as I said very early on in this thread (with regard to returned values). Is it possible to retroactively apply Allen's recommendation to existing APIs that accept one or the other, allowing them to accept both as the same? Is it worth doing so (it may not be)?
Jonas Sicking wrote:
- APIs may return Date objects but they should always be newly created instances and never retain references to them. An API client might mutate such returned Date objects but that's really the clients business and it will have no impact upon the DOM.
The emails in this thread seems to indicate that we should in fact not return Date objects ever (though like any rule, I could imagine there being exceptions). Instead we should simply return numeric timestamps.
Yup.
Dave has a sad history. Cloned from JDK1.0 java.util.Date, y2k-bugs and all, with hidden mutable state, it still vexes. On top of the legacy smell, the question arises: why create an object with mutable state when you are expressing a universal time coordinate?
A number wins in almost all cases, for economy and precision, if not economy of expression for code that will (somewhere) use the timestamp to create a Date object to present some strings to a user.
Brendan Eich wrote:
Dave has a sad history
LOL! Date, not Dave.
Dave has a great history (I know many Daves).
And if it ever goes back to the drawing board, make it immutable of course and please remember that months are numbered from 1 to 12!
I filed www.w3.org/Bugs/Public/show_bug.cgi?id=22824 to have Date object support removed from WebIDL.
Note that this doesn't mean that Date objects can't be returned from DOM APIs (or any other APIs). It just means that we stop actively encouraging it. But no APIs are ever forced to limit themselves to the capabilities of WebIDL.
/ Jonas
Is it intentional that Date objects cannot be frozen?
Use case: exposing the time of an event through a Date object while not allowing fiddling with it.