Skip to content

Commit 36f6bdb

Browse files
authored
Add JSDate implementation with tests (#45)
This doesn't 100% match the JS API, for example `getMonth`/`setMonth` etc accessor methods are converted to properties, but the rest of it matches in the naming. I didn't expose API parts [that MDN marks as non-standard](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) or not consistent across browsers and JS implementations.
1 parent cbbe6f9 commit 36f6bdb

File tree

2 files changed

+260
-0
lines changed

2 files changed

+260
-0
lines changed

IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift

+40
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,46 @@ try test("TypedArray_Mutation") {
395395
try expectEqual(toString(array.jsValue().object!), jsStringify(Array(0..<100)))
396396
}
397397

398+
try test("Date") {
399+
let date1Milliseconds = JSDate.now()
400+
let date1 = JSDate(millisecondsSinceEpoch: date1Milliseconds)
401+
let date2 = JSDate(millisecondsSinceEpoch: date1.valueOf())
402+
403+
try expectEqual(date1.valueOf(), date2.valueOf())
404+
try expectEqual(date1.fullYear, date2.fullYear)
405+
try expectEqual(date1.month, date2.month)
406+
try expectEqual(date1.date, date2.date)
407+
try expectEqual(date1.day, date2.day)
408+
try expectEqual(date1.hours, date2.hours)
409+
try expectEqual(date1.minutes, date2.minutes)
410+
try expectEqual(date1.seconds, date2.seconds)
411+
try expectEqual(date1.milliseconds, date2.milliseconds)
412+
try expectEqual(date1.utcFullYear, date2.utcFullYear)
413+
try expectEqual(date1.utcMonth, date2.utcMonth)
414+
try expectEqual(date1.utcDate, date2.utcDate)
415+
try expectEqual(date1.utcDay, date2.utcDay)
416+
try expectEqual(date1.utcHours, date2.utcHours)
417+
try expectEqual(date1.utcMinutes, date2.utcMinutes)
418+
try expectEqual(date1.utcSeconds, date2.utcSeconds)
419+
try expectEqual(date1.utcMilliseconds, date2.utcMilliseconds)
420+
try expectEqual(date1, date2)
421+
422+
let date3 = JSDate(millisecondsSinceEpoch: 0)
423+
try expectEqual(date3.valueOf(), 0)
424+
try expectEqual(date3.utcFullYear, 1970)
425+
try expectEqual(date3.utcMonth, 0)
426+
try expectEqual(date3.utcDate, 1)
427+
// the epoch date was on Friday
428+
try expectEqual(date3.utcDay, 4)
429+
try expectEqual(date3.utcHours, 0)
430+
try expectEqual(date3.utcMinutes, 0)
431+
try expectEqual(date3.utcSeconds, 0)
432+
try expectEqual(date3.utcMilliseconds, 0)
433+
try expectEqual(date3.toISOString(), "1970-01-01T00:00:00.000Z")
434+
435+
try expectEqual(date3 < date1, true)
436+
}
437+
398438
try test("Error") {
399439
let message = "test error"
400440
let error = JSError(message: message)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
public final class JSDate {
2+
private static let constructor = JSObject.global.Date.function!
3+
public let ref: JSObject
4+
5+
public init(millisecondsSinceEpoch: Double? = nil) {
6+
if let milliseconds = millisecondsSinceEpoch {
7+
ref = Self.constructor.new(milliseconds)
8+
} else {
9+
ref = Self.constructor.new()
10+
}
11+
}
12+
13+
/** According to the standard, `monthIndex` is zero-indexed, where `11` is December. `day`
14+
represents a day of the month starting at `1`.
15+
*/
16+
public init(
17+
year: Int,
18+
monthIndex: Int,
19+
day: Int = 1,
20+
hours: Int = 0,
21+
minutes: Int = 0,
22+
seconds: Int = 0,
23+
milliseconds: Int = 0
24+
) {
25+
ref = Self.constructor.new(year, monthIndex, day, hours, minutes, seconds, milliseconds)
26+
}
27+
28+
/// Year of this date in local time zone.
29+
public var fullYear: Int {
30+
get {
31+
Int(ref.getFullYear!().number!)
32+
}
33+
set {
34+
_ = ref.setFullYear!(newValue)
35+
}
36+
}
37+
38+
/// Month of this date in `0–11` range in local time zone
39+
public var month: Int {
40+
get {
41+
Int(ref.getMonth!().number!)
42+
}
43+
set {
44+
_ = ref.setMonth!(newValue)
45+
}
46+
}
47+
48+
/// The day of the month in `1..31` range in local time zone.
49+
public var date: Int {
50+
get {
51+
Int(ref.getDate!().number!)
52+
}
53+
set {
54+
_ = ref.setDate!(newValue)
55+
}
56+
}
57+
58+
/// The day of the week in `0..6` range in local time zone.
59+
public var day: Int {
60+
Int(ref.getDay!().number!)
61+
}
62+
63+
/// The amount of hours in this day from `0..23` range in local time zone.
64+
public var hours: Int {
65+
get {
66+
Int(ref.getHours!().number!)
67+
}
68+
set {
69+
_ = ref.setHours!(newValue)
70+
}
71+
}
72+
73+
/// The amount of minutes in this hours from `0..59` range in local time zone.
74+
public var minutes: Int {
75+
get {
76+
Int(ref.getMinutes!().number!)
77+
}
78+
set {
79+
_ = ref.setMinutes!(newValue)
80+
}
81+
}
82+
83+
/// The amount of seconds in this minute from `0..59` range in local time zone.
84+
public var seconds: Int {
85+
get {
86+
Int(ref.getSeconds!().number!)
87+
}
88+
set {
89+
_ = ref.setSeconds!(newValue)
90+
}
91+
}
92+
93+
/// The amount of milliseconds in this second `0..999` range in local time zone.
94+
public var milliseconds: Int {
95+
get {
96+
Int(ref.getMilliseconds!().number!)
97+
}
98+
set {
99+
_ = ref.setMilliseconds!(newValue)
100+
}
101+
}
102+
103+
/// Year of this date in the UTC time zone
104+
public var utcFullYear: Int {
105+
get {
106+
Int(ref.getUTCFullYear!().number!)
107+
}
108+
set {
109+
_ = ref.setUTCFullYear!(newValue)
110+
}
111+
}
112+
113+
/// Month of this date in `0–11` range in the UTC time zone
114+
public var utcMonth: Int {
115+
get {
116+
Int(ref.getUTCMonth!().number!)
117+
}
118+
set {
119+
_ = ref.setUTCMonth!(newValue)
120+
}
121+
}
122+
123+
/// The day of the month in `1..31` range in the UTC time zone
124+
public var utcDate: Int {
125+
get {
126+
Int(ref.getUTCDate!().number!)
127+
}
128+
set {
129+
_ = ref.setUTCDate!(newValue)
130+
}
131+
}
132+
133+
/// The day of the week in `0..6` range in the UTC time zone
134+
public var utcDay: Int {
135+
Int(ref.getUTCDay!().number!)
136+
}
137+
138+
/// The amount of hours in this day from `0..23` range in the UTC time zone
139+
public var utcHours: Int {
140+
get {
141+
Int(ref.getUTCHours!().number!)
142+
}
143+
set {
144+
_ = ref.setUTCHours!(newValue)
145+
}
146+
}
147+
148+
/// The amount of minutes in this hours from `0..59` range in the UTC time zone
149+
public var utcMinutes: Int {
150+
get {
151+
Int(ref.getUTCMinutes!().number!)
152+
}
153+
set {
154+
_ = ref.setUTCMinutes!(newValue)
155+
}
156+
}
157+
158+
/// The amount of seconds in this minute from `0..59` range in the UTC time zone
159+
public var utcSeconds: Int {
160+
get {
161+
Int(ref.getUTCSeconds!().number!)
162+
}
163+
set {
164+
_ = ref.setUTCSeconds!(newValue)
165+
}
166+
}
167+
168+
/// The amount of milliseconds in this second `0..999` range in the UTC time zone
169+
public var utcMilliseconds: Int {
170+
get {
171+
Int(ref.getUTCMilliseconds!().number!)
172+
}
173+
set {
174+
_ = ref.setUTCMilliseconds!(newValue)
175+
}
176+
}
177+
178+
/// Offset in minutes between the local time zone and UTC
179+
public var timezoneOffset: Int {
180+
Int(ref.getTimezoneOffset!().number!)
181+
}
182+
183+
public func toISOString() -> String {
184+
ref.toISOString!().string!
185+
}
186+
187+
public func toLocaleDateString() -> String {
188+
ref.toLocaleDateString!().string!
189+
}
190+
191+
public func toLocaleTimeString() -> String {
192+
ref.toLocaleTimeString!().string!
193+
}
194+
195+
public func toUTCString() -> String {
196+
ref.toUTCString!().string!
197+
}
198+
199+
/// Number of milliseconds since midnight 01 January 1970 UTC to the present moment ignoring leap
200+
/// seconds
201+
public static func now() -> Double {
202+
constructor.now!().number!
203+
}
204+
205+
/// Number of milliseconds since midnight 01 January 1970 UTC to the given date ignoring leap
206+
/// seconds
207+
public func valueOf() -> Double {
208+
ref.valueOf!().number!
209+
}
210+
}
211+
212+
extension JSDate: Comparable {
213+
public static func ==(lhs: JSDate, rhs: JSDate) -> Bool {
214+
return lhs.valueOf() == rhs.valueOf()
215+
}
216+
217+
public static func <(lhs: JSDate, rhs: JSDate) -> Bool {
218+
return lhs.valueOf() < rhs.valueOf()
219+
}
220+
}

0 commit comments

Comments
 (0)