@@ -34,64 +34,12 @@ public typealias TimeInterval = Double
3434 A `Date` is independent of a particular calendar or time zone. To represent a `Date` to a user, you must interpret it in the context of a `Calendar`.
3535*/
3636@available ( macOS 10 . 10 , iOS 8 . 0 , watchOS 2 . 0 , tvOS 9 . 0 , * )
37- public struct Date : Comparable , Hashable , Equatable , Sendable {
38- /* Date is internally represented as a sum of two Doubles.
39-
40- Previously Date was backed by a single Double measuring time since
41- Jan 1 2001 in seconds. Because Double's precision is non-uniform, this
42- means that times within a hundred days of the epoch are represented
43- with approximately nanosecond precision, but as you get farther away
44- from that date the precision decreases. For times close to the time
45- at which this comment was written, accuracy has been reduced to about
46- 100ns.
47-
48- The obvious thing would be to adopt an integer-based representation
49- similar to C's timespec (32b nanoseconds, 64b seconds) or Swift's
50- Duration (128b attoseconds). These representations suffer from a few
51- difficulties:
52-
53- - Existing API on Date takes and produces `TimeInterval` (aka Double).
54- Making Date use an integer representation internally would mean that
55- existing users of the public API would suddently start getting
56- different results for computations that were previously exact; even
57- though we could add new API, and the overall system would be more
58- precise, this would be a surprisingly subtle change for users to
59- navigate.
60-
61- - We have been told that some software interprets the raw bytes of Date
62- as a Double for the purposes of fast serialization. These packages
63- formally violate Foundation's API boundaries, but that doesn't help
64- users of those packages who would abruptly be broken by switching to
65- an integer representation.
66-
67- Using DoubleDouble instead navigates these problems fairly elegantly.
68-
69- - Because DoubleDouble is still a floating-point type, it still suffers
70- from non-uniform precision. However, because DoubleDouble is so
71- fantastically precise, it can represent dates out to ±2.5 quadrillion
72- years at ~nanosecond or better precision, so in practice this won't
73- be much of an issue.
74-
75- - Existing API on Date will produce exactly the same result as it did
76- previously in cases where those results were exact, minimizing
77- surprises. In cases where the existing API was not exact, it will
78- produce much more accurate results, even if users do not adopt new
79- API, because its internal calculations are now more precise.
80-
81- - Software that (incorrectly) interprets the raw bytes of Date as a
82- Double will get at least as accurate of a value as it did previously
83- (and often a more accurate value). */
84- internal var _time : DoubleDouble
85-
86- internal init ( _ time: DoubleDouble ) {
87- self . _time = time
88- }
89- }
37+ public struct Date : Comparable , Hashable , Equatable , Sendable {
38+
39+ internal var _time : TimeInterval
9040
91- @available ( macOS 10 . 10 , iOS 8 . 0 , watchOS 2 . 0 , tvOS 9 . 0 , * )
92- extension Date {
9341 /// The number of seconds from 1 January 1970 to the reference date, 1 January 2001.
94- public static let timeIntervalBetween1970AndReferenceDate : TimeInterval = 978307200.0
42+ public static let timeIntervalBetween1970AndReferenceDate : TimeInterval = 978307200.0
9543
9644 /// The number of seconds from 1 January 1601 to the reference date, 1 January 2001.
9745 internal static let timeIntervalBetween1601AndReferenceDate : TimeInterval = 12622780800.0
@@ -103,23 +51,17 @@ extension Date {
10351
10452 /// Returns a `Date` initialized to the current date and time.
10553 public init ( ) {
106- _time = . init ( uncheckedHead : Self . getCurrentAbsoluteTime ( ) , tail : 0 )
54+ _time = Self . getCurrentAbsoluteTime ( )
10755 }
10856
10957 /// Returns a `Date` initialized relative to the current date and time by a given number of seconds.
11058 public init ( timeIntervalSinceNow: TimeInterval ) {
111- self . init ( . sum(
112- Self . getCurrentAbsoluteTime ( ) ,
113- timeIntervalSinceNow
114- ) )
59+ self . init ( timeIntervalSinceReferenceDate: timeIntervalSinceNow + Self. getCurrentAbsoluteTime ( ) )
11560 }
11661
11762 /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
11863 public init ( timeIntervalSince1970: TimeInterval ) {
119- self . init ( . sum(
120- timeIntervalSince1970,
121- - Date. timeIntervalBetween1970AndReferenceDate
122- ) )
64+ self . init ( timeIntervalSinceReferenceDate: timeIntervalSince1970 - Date. timeIntervalBetween1970AndReferenceDate)
12365 }
12466
12567 /**
@@ -129,12 +71,12 @@ extension Date {
12971 - Parameter date: The reference date.
13072 */
13173 public init ( timeInterval: TimeInterval , since date: Date ) {
132- self . init ( date. _time + timeInterval)
74+ self . init ( timeIntervalSinceReferenceDate : date. timeIntervalSinceReferenceDate + timeInterval)
13375 }
13476
13577 /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 2001 by a given number of seconds.
13678 public init ( timeIntervalSinceReferenceDate ti: TimeInterval ) {
137- _time = . init ( uncheckedHead : ti , tail : 0 )
79+ _time = ti
13880 }
13981
14082 /**
@@ -143,7 +85,7 @@ extension Date {
14385 This property's value is negative if the date object is earlier than the system's absolute reference date (00:00:00 UTC on 1 January 2001).
14486 */
14587 public var timeIntervalSinceReferenceDate : TimeInterval {
146- return _time. head
88+ return _time
14789 }
14890
14991 /**
@@ -158,7 +100,7 @@ extension Date {
158100 - SeeAlso: `timeIntervalSinceReferenceDate`
159101 */
160102 public func timeIntervalSince( _ date: Date ) -> TimeInterval {
161- return ( self . _time - date. _time ) . head
103+ return self . timeIntervalSinceReferenceDate - date. timeIntervalSinceReferenceDate
162104 }
163105
164106 /**
@@ -231,9 +173,9 @@ extension Date {
231173
232174 /// Compare two `Date` values.
233175 public func compare( _ other: Date ) -> ComparisonResult {
234- if _time < other. _time {
176+ if _time < other. timeIntervalSinceReferenceDate {
235177 return . orderedAscending
236- } else if _time > other. _time {
178+ } else if _time > other. timeIntervalSinceReferenceDate {
237179 return . orderedDescending
238180 } else {
239181 return . orderedSame
@@ -242,27 +184,27 @@ extension Date {
242184
243185 /// Returns true if the two `Date` values represent the same point in time.
244186 public static func == ( lhs: Date , rhs: Date ) -> Bool {
245- return lhs. _time == rhs. _time
187+ return lhs. timeIntervalSinceReferenceDate == rhs. timeIntervalSinceReferenceDate
246188 }
247189
248190 /// Returns true if the left hand `Date` is earlier in time than the right hand `Date`.
249191 public static func < ( lhs: Date , rhs: Date ) -> Bool {
250- return lhs. _time < rhs. _time
192+ return lhs. timeIntervalSinceReferenceDate < rhs. timeIntervalSinceReferenceDate
251193 }
252194
253195 /// Returns true if the left hand `Date` is later in time than the right hand `Date`.
254196 public static func > ( lhs: Date , rhs: Date ) -> Bool {
255- return lhs. _time > rhs. _time
197+ return lhs. timeIntervalSinceReferenceDate > rhs. timeIntervalSinceReferenceDate
256198 }
257199
258200 /// Returns a `Date` with a specified amount of time added to it.
259201 public static func + ( lhs: Date , rhs: TimeInterval ) -> Date {
260- return Date ( lhs. _time + rhs)
202+ return Date ( timeIntervalSinceReferenceDate : lhs. timeIntervalSinceReferenceDate + rhs)
261203 }
262204
263205 /// Returns a `Date` with a specified amount of time subtracted from it.
264206 public static func - ( lhs: Date , rhs: TimeInterval ) -> Date {
265- return Date ( lhs. _time - rhs)
207+ return Date ( timeIntervalSinceReferenceDate : lhs. timeIntervalSinceReferenceDate - rhs)
266208 }
267209
268210 /// Add a `TimeInterval` to a `Date`.
@@ -278,6 +220,7 @@ extension Date {
278220 public static func -= ( lhs: inout Date , rhs: TimeInterval ) {
279221 lhs = lhs - rhs
280222 }
223+
281224}
282225
283226@available ( macOS 10 . 10 , iOS 8 . 0 , watchOS 2 . 0 , tvOS 9 . 0 , * )
@@ -395,7 +338,7 @@ extension Date : ReferenceConvertible, _ObjectiveCBridgeable {
395338
396339 @_semantics ( " convertToObjectiveC " )
397340 public func _bridgeToObjectiveC( ) -> NSDate {
398- return NSDate ( timeIntervalSinceReferenceDate: _time. head )
341+ return NSDate ( timeIntervalSinceReferenceDate: _time)
399342 }
400343
401344 public static func _forceBridgeFromObjectiveC( _ x: NSDate , result: inout Date ? ) {
0 commit comments