A similar argument was made when renaming NSCharacterSet (to CharacterSet rather than UnicodeScalarSet).
"Wall time" may be a term of art, but a physical wall clock usually displays local time in hours and minutes. A radio-controlled wall clock can display an accurate date and time, automatically adjusted for daylight savings, leap seconds, etc. WallClock doesn't do any of this. MonotonicClock and UptimeClock are also misnamed, if they have the opposite meaning for Darwin and Linux users.
ClockProtocol doesn't seem useful at the moment. Should its sleep(until:) method be implemented by calling Task.sleep(nanoseconds:), or would clocks be expected to reimplement that behavior?
Does moving Foundation.Date to the standard library make back-deployment of concurrency APIs easier or more difficult?
"Midnight" is a calendrical concept. Given the actual number of seconds elapsed since some reference point in time, you cannot infer the time of day it represents. You need to consider that in the context of a calendar (and timezone), which has your leap second information for you.
A second is defined to be the time it takes a cesium-133 atom to oscillate 9,192,631,770 times between between its two hyperfine levels of the fundamental unperturbed ground-state (at zero kelvin).
You can think of the Date type encapsulating the number of oscillations of such an atom since a reference date. â It is not the number of earth revolutions multiplied by 86400 since that point in time.
When we add a leap second, the atom keeps oscillating undisturbed. When we remove a second, it doesn't stop a beat. When we change our clocks, the atom keeps humming away.
But when you want to known when the Nth oscillation happened, you have to consider the leap seconds. That is the task of a Calendar type to help you with.
Apple are also not completely consistent with terminology all the time - from NSTableView to the (kinda similar, but also very different) UITableView, to SwiftUI's List, or UIKit's UISwitch vs. SwiftUI's Toggle.
Swift developers also deal with multiple spellings for the same type - from sugar ([UInt8] is Array<UInt8>, Foo? is Optional<Foo>, etc) to type-aliases (Float64 is Double), to associated types (Array<UInt8>.Index is Int).
So it happens, and it's not a big deal. We can use a more appropriate name for Date.
And in terms of overall language complexity, this wouldn't even come close. I don't think it's credible to say, on the one hand, that people can understand result builders, but having Date be aliased to a more appropriate name has such a great cognitive burden that it isn't worth doing.
I agree that it would advance the status quo to make these relationships clearer, except that the name Date leaves us in a strange situation, where WallClock is a clock which tells you a "date". That muddies the advancement significantly - clocks tell time, not dates.
I think it's pretty clear that Date has the wrong name.
On reflection, I think that decision was the right one: CharacterSet was designed at a different time in the evolution of Unicode, and that pervades the API designâmerely renaming doesnât change that, and keeping the name actually advertises the discordance. The type wasnât being given a different underlying storage, sunk into the standard library, and made the flagship âcurrencyâ type for a new Unicode scalar protocol in Swiftâs next generation of string processing APIs. This is what weâre talking about here.
After reading this entire pitch and thread I like where this is going, and look forward to improving these APIs.
However I'm still unclear about why the Clock protocol has a sleep method, especially given the initial definition of clock being:
My expectation of calling .sleep(...) on a clock would not be that the current thread/etc would sleep, I would expect an API that takes a Clock/Duration. My initial thought is that the clock would sleep similar to how some clocks "sleep" when the system does, which doesn't make sense for a wall clock but may for custom clocks (although there are probably better names).
Is there more context/reasoning for this that I missed and/or can someone clarify?
Also wanted to agree with several of the recent posts that we should take this opportunity to rename Date to something like Timestamp.
The name Time has not been used as a typename in any Apple APIs, but I also don't think it would fit at this level. "Time" is a complicated name because it has varying meanings. It can refer to the general concept of experienced temporal flow, but it can also refer to something like "9:41 AM". The former might be OK for the standard library, but the latter definitely is not. So my personal vote would be to avoid the potential confusion and not use Time nor Date at this level.
I don't think Timestamp or Time is any more clear than Date. It has the exact same potential for confusion, because a time is something people generally associate with a point inside a given day. Who really thinks of the current "time" as something that has incremented from some value starting in 1970 instead of "9:42 AM"?
Even if we could all agree on a name for a new type, we will not be wholesale replacing every instance of Date in Apple's SDKs with this new type, because Swift values source and binary compatibility. In my opinion, requiring an explicit conversion between this new type and others is a non-starter. Every new API from this point on would have to decide if it takes one of the two or both (doubling the API surface).
Let's say we then made them something equivalent to a typealias. API authors from this point on would have to make a decision if they want to appear to fit in with the SDK API and use Date or use the new name. Having participated in quite a few discussions about these APIs, I believe the SDK authors will choose to stick with Date for consistency, therefore leaving a permanent bifurcation of names and a splintering of what feels "right for Swift" vs "right for the SDK." Even on platforms with less history, this will still happen. One of the noted benefits of using Swift on server is its compatibility (both conceptually and in source) with the Swift you would write for the client side.
Believe it or not, I too wish we could go back and time and pick new names for some of our API, including Date. However, I think it is best to use the opportunity of sinking date to build this better infrastructure around it and to support it in the most compatible way possible.
I respectfully disagree with this. I've never heard of anyone seeing the name "timestamp" and wondering "does this mean 'October 12, 2021'?" But that happens all the time with Date.
For everyone interested; moving Date down and then renaming it and making it source compatible via a typealias would potentially be source compatible but it would not be ABI compatible. There are no facilities I am aware of that we have at our disposal to account for a rename like that.
I don't think that meets the bar for ABI breaking changes (even for Swift 6).
Thereâs ample precedent from other languages to make this type Instant or Momentâindeed, this is the terminology used in the proposal text.
I am much more sanguine than you as to the consequences either of a typealias approach or of having a entirely separate new API co-exist with legacy APIs.
Additionally, if we need a CGFloat-like mechanism to smooth the way, it is clearly doable. Moreover, such a design has been envisioned in this very pitch for Duration and TimeInterval. And indeed, that conversion has been critiqued for being not nearly as common as CGFloat conversion is, a weakness that would not apply to any hypothetical Date to DistinctTypeConformingToInstantProtocol conversion.
The debate on name got a bit heated there so I missed this part. Basically any sort of clock mechanism needs a wakeup to make it usable other than measuring things. So in order to allow Task to sleep the clock provides a way to wake up after a given instant. This becomes the crux of the real functionality behind this proposal; in order to do things like throttling, or have a deadline in async/await code we need a way to wake up after a given instant which the only source of truth to how to do that is relative to the clock (or things that would use that clock). If you are interested, and I would guess others might be interested too at the progress, I have a start to the implementation here.
Obviously this isn't the whole story to get to those higher level parts but basically it would involve two tasks executing with one sleeping given a clock and another doing work. That can build up primitives to implement lots of really useful interfaces.
Would you care quoting the analogous Wikipedia article for Date?
With all respect, that is not the best argument.
(The reason why many of us react so strongly is really that Date is truly misleading - if we could agree on that there are (much) better alternatives maybe we could discuss other possible ways forward)
With respect to the wikipedia source; my comment was to say that the common form of Timestamp is perhaps as ambiguous - Date has at least the refinement in the entries to have it listed as Calendar Date which there used to be a type NSCalendarDate that was deprecated which did represent the concept of a NSCalendar + a NSDate. The definitions with regards to Date as it has been used in swift for the past few years has been by the definition posed by Foundation which dates (pun definitely intended) back to early NeXTStep. I have tried to dig up the original impetus for the naming however I have yet to find anything worth sharing on that.
Additionally, if we need a CGFloat -like mechanism to smooth the way, it is clearly doable. Moreover, such a design has been envisioned in this very pitch for Duration and TimeInterval .
To me, this analogy hits the nail on the head:
The proposal recognizes that TimeInterval inadequately represents the semantics of a measurement in seconds.
Any APIs which today utilize TimeInterval would require duplication to support Duration, so the proposal reasonably suggests a bidirectional conversion to preserve ergonomics as TimeInterval phases out of usage.
Swapping the types in question:
Unlike TimeInterval with e.g. multiplication, the semantics of Dateâinsofar as the concrete set of operations it providesâdon't support intrinsically incorrect usage. But discussion here has demonstrated that the name itself suggests responsibilities outside of the type's designated purpose, and an incorrect understanding of the model can just as well result in invalid usage.
The second bullet above holds for a renaming of Date.
Finally, I'd argue the proposed story for changing the underlying representation of Date is made cleaner with the introduction of a new type: roundtrip serialization of both Date and a new type can remain lossless, with lossiness pushed into the implicit conversionâa pattern precedented by CGFloat-to-Double conversions on 32-bit platforms.
I wanna point out thatâunless the proposal seeks to change this, which is a unclear to meâthis is not the case.
To verify, use calendar APIs to get the beginning of each year in utc since 1970, then print the dates timeIntervalSince1970. All cleanly divisible by 24x60x60.
Furthermore, the only affordance for measuring time between two Date instances, timeIntervalSince(_:), just subtracts the timestamps. No leap second handling to be found here.
No leap second handling to be found in Calendar APIs either. Creating a Date just before a past leap second, then using calendar API to step that date forward second by second will skip right over the leap second.
So in conclusion, the current model of Date is neither a true physical timestamp nor a human date, but a weird hybrid of the two that was maybe useful enough to justify when developers had to work with raw timestamps more routinely, but feels rather archaic today.
Now, if the proposal was to change this, I would welcome this very much. The Date types lying about the time interval between some dates that meet specific criteria (with no indication of this I could find in any documentation, I might add; indeed searching for "leap" in the Date docs yields no results at all) to me feels kind of akin to int overflow, and very non-Swifty.
Indeed. I think we should think of Date as "calendar seconds" since reference date, whereas "real seconds" since reference date should include leap seconds.