From ca6a08b121404b4233240d47f99705bceb052ae2 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 19:22:37 +0100 Subject: [PATCH 1/7] Basic JSDate implementation with a simple test --- .../Sources/PrimaryTests/main.swift | 24 +++ .../JavaScriptKit/BasicObjects/JSDate.swift | 203 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 Sources/JavaScriptKit/BasicObjects/JSDate.swift diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 292e6f3a5..1af0f1161 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -394,3 +394,27 @@ try test("TypedArray_Mutation") { } try expectEqual(toString(array.jsValue().object!), jsStringify(Array(0..<100))) } + +try test("Date") { + let date1 = JSDate() + print(date1.toISOString()) + let date2 = JSDate(millisecondsSinceEpoch: date1.now()) + + try expectEqual(date1.now(), date2.now()) + try expectEqual(date1.fullYear, date2.fullYear) + try expectEqual(date1.month, date2.month) + try expectEqual(date1.date, date2.date) + try expectEqual(date1.day, date2.day) + try expectEqual(date1.hours, date2.hours) + try expectEqual(date1.minutes, date2.minutes) + try expectEqual(date1.seconds, date2.seconds) + try expectEqual(date1.milliseconds, date2.milliseconds) + try expectEqual(date1.utcFullYear, date2.utcFullYear) + try expectEqual(date1.utcMonth, date2.utcMonth) + try expectEqual(date1.utcDate, date2.utcDate) + try expectEqual(date1.utcDay, date2.utcDay) + try expectEqual(date1.utcHours, date2.utcHours) + try expectEqual(date1.utcMinutes, date2.utcMinutes) + try expectEqual(date1.utcSeconds, date2.utcSeconds) + try expectEqual(date1.utcMilliseconds, date2.utcMilliseconds) +} diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift new file mode 100644 index 000000000..3c97456d9 --- /dev/null +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -0,0 +1,203 @@ +public final class JSDate { + private static let constructor = JSObject.global.Date.function! + private let ref: JSObject + + public init(millisecondsSinceEpoch: Int? = nil) { + if let milliseconds = millisecondsSinceEpoch { + ref = Self.constructor.new(milliseconds) + } else { + ref = Self.constructor.new() + } + } + + /** According to the standard, `monthIndex` is zero-indexed, where `11` is December. `day` + represents a day of the month starting at `1`. + */ + public init( + year: Int, + monthIndex: Int, + day: Int = 1, + hours: Int = 0, + minutes: Int = 0, + seconds: Int = 0, + milliseconds: Int = 0 + ) { + ref = Self.constructor.new(year, monthIndex, day, hours, minutes, seconds, milliseconds) + } + + /// Year of this date in local time zone. + public var fullYear: Int { + get { + Int(ref.getFullYear.function!().number!) + } + set { + ref.setFullYear.function!(newValue) + } + } + + /// Month of this date in `0–11` range in local time zone + public var month: Int { + get { + Int(ref.getMonth.function!().number!) + } + set { + ref.setMonth.function!(newValue) + } + } + + /// The day of the month in `1..31` range in local time zone. + public var date: Int { + get { + Int(ref.getDate.function!().number!) + } + set { + ref.setDate.function!(newValue) + } + } + + /// The day of the week in `0..6` range in local time zone. + public var day: Int { + Int(ref.getDay.function!().number!) + } + + /// The amount of hours in this day from `0..23` range in local time zone. + public var hours: Int { + get { + Int(ref.getHours.function!().number!) + } + set { + ref.setHours.function!(newValue) + } + } + + /// The amount of minutes in this hours from `0..59` range in local time zone. + public var minutes: Int { + get { + Int(ref.getMinutes.function!().number!) + } + set { + ref.setMinutes.function!(newValue) + } + } + + /// The amount of seconds in this minute from `0..59` range in local time zone. + public var seconds: Int { + get { + Int(ref.getSeconds.function!().number!) + } + set { + ref.setSeconds.function!(newValue) + } + } + + /// The amount of milliseconds in this second `0..999` range in local time zone. + public var milliseconds: Int { + get { + Int(ref.getMilliseconds.function!().number!) + } + set { + ref.setMilliseconds.function!(newValue) + } + } + + /// Year of this date in the UTC time zone + public var utcFullYear: Int { + get { + Int(ref.getFullYear.function!().number!) + } + set { + ref.setFullYear.function!(newValue) + } + } + + /// Month of this date in `0–11` range in the UTC time zone + public var utcMonth: Int { + get { + Int(ref.getMonth.function!().number!) + } + set { + ref.setMonth.function!(newValue) + } + } + + /// The day of the month in `1..31` range in the UTC time zone + public var utcDate: Int { + get { + Int(ref.getDate.function!().number!) + } + set { + ref.setDate.function!(newValue) + } + } + + /// The day of the week in `0..6` range in the UTC time zone + public var utcDay: Int { + Int(ref.getDay.function!().number!) + } + + /// The amount of hours in this day from `0..23` range in the UTC time zone + public var utcHours: Int { + get { + Int(ref.getHours.function!().number!) + } + set { + ref.setHours.function!(newValue) + } + } + + /// The amount of minutes in this hours from `0..59` range in the UTC time zone + public var utcMinutes: Int { + get { + Int(ref.getMinutes.function!().number!) + } + set { + ref.setMinutes.function!(newValue) + } + } + + /// The amount of seconds in this minute from `0..59` range in the UTC time zone + public var utcSeconds: Int { + get { + Int(ref.getSeconds.function!().number!) + } + set { + ref.setSeconds.function!(newValue) + } + } + + /// The amount of milliseconds in this second `0..999` range in the UTC time zone + public var utcMilliseconds: Int { + get { + Int(ref.getMilliseconds.function!().number!) + } + set { + ref.setMilliseconds.function!(newValue) + } + } + + /// Offset in minutes between the local time zone and UTC + public var timezoneOffset: Int { + Int(ref.getTimezoneOffset.function!().number!) + } + + public func toISOString() -> String { + ref.toISOString.function!().string! + } + + public func toLocaleDateString() -> String { + ref.toLocaleDateString.function!().string! + } + + public func toLocaleTimeString() -> String { + ref.toLocaleTimeString.function!().string! + } + + public func toUTCString() -> String { + ref.toUTCString.function!().string! + } + + /// Number of seconds since epoch ignoring leap seconds + public func now() -> Int { + Int(ref.now.function!().number!) + } +} From 6546f3ab884e5d35e43c967ae4029de40fb46846 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 21:11:40 +0100 Subject: [PATCH 2/7] Fix tests, address PR feedback --- .../Sources/PrimaryTests/main.swift | 8 +- .../JavaScriptKit/BasicObjects/JSDate.swift | 87 ++++++++++--------- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 1af0f1161..323c90f0c 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -396,11 +396,11 @@ try test("TypedArray_Mutation") { } try test("Date") { - let date1 = JSDate() - print(date1.toISOString()) - let date2 = JSDate(millisecondsSinceEpoch: date1.now()) + let date1Milliseconds = JSDate.now() + let date1 = JSDate(millisecondsSinceEpoch: date1Milliseconds) + let date2 = JSDate(millisecondsSinceEpoch: date1.valueOf()) - try expectEqual(date1.now(), date2.now()) + try expectEqual(date1.valueOf(), date2.valueOf()) try expectEqual(date1.fullYear, date2.fullYear) try expectEqual(date1.month, date2.month) try expectEqual(date1.date, date2.date) diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index 3c97456d9..3a4242766 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -1,8 +1,8 @@ public final class JSDate { private static let constructor = JSObject.global.Date.function! - private let ref: JSObject + public let ref: JSObject - public init(millisecondsSinceEpoch: Int? = nil) { + public init(millisecondsSinceEpoch: Double? = nil) { if let milliseconds = millisecondsSinceEpoch { ref = Self.constructor.new(milliseconds) } else { @@ -28,176 +28,183 @@ public final class JSDate { /// Year of this date in local time zone. public var fullYear: Int { get { - Int(ref.getFullYear.function!().number!) + Int(ref.getFullYear!().number!) } set { - ref.setFullYear.function!(newValue) + _ = ref.setFullYear!(newValue) } } /// Month of this date in `0–11` range in local time zone public var month: Int { get { - Int(ref.getMonth.function!().number!) + Int(ref.getMonth!().number!) } set { - ref.setMonth.function!(newValue) + _ = ref.setMonth!(newValue) } } /// The day of the month in `1..31` range in local time zone. public var date: Int { get { - Int(ref.getDate.function!().number!) + Int(ref.getDate!().number!) } set { - ref.setDate.function!(newValue) + _ = ref.setDate!(newValue) } } /// The day of the week in `0..6` range in local time zone. public var day: Int { - Int(ref.getDay.function!().number!) + Int(ref.getDay!().number!) } /// The amount of hours in this day from `0..23` range in local time zone. public var hours: Int { get { - Int(ref.getHours.function!().number!) + Int(ref.getHours!().number!) } set { - ref.setHours.function!(newValue) + _ = ref.setHours!(newValue) } } /// The amount of minutes in this hours from `0..59` range in local time zone. public var minutes: Int { get { - Int(ref.getMinutes.function!().number!) + Int(ref.getMinutes!().number!) } set { - ref.setMinutes.function!(newValue) + _ = ref.setMinutes!(newValue) } } /// The amount of seconds in this minute from `0..59` range in local time zone. public var seconds: Int { get { - Int(ref.getSeconds.function!().number!) + Int(ref.getSeconds!().number!) } set { - ref.setSeconds.function!(newValue) + _ = ref.setSeconds!(newValue) } } /// The amount of milliseconds in this second `0..999` range in local time zone. public var milliseconds: Int { get { - Int(ref.getMilliseconds.function!().number!) + Int(ref.getMilliseconds!().number!) } set { - ref.setMilliseconds.function!(newValue) + _ = ref.setMilliseconds!(newValue) } } /// Year of this date in the UTC time zone public var utcFullYear: Int { get { - Int(ref.getFullYear.function!().number!) + Int(ref.getFullYear!().number!) } set { - ref.setFullYear.function!(newValue) + _ = ref.setFullYear!(newValue) } } /// Month of this date in `0–11` range in the UTC time zone public var utcMonth: Int { get { - Int(ref.getMonth.function!().number!) + Int(ref.getMonth!().number!) } set { - ref.setMonth.function!(newValue) + _ = ref.setMonth!(newValue) } } /// The day of the month in `1..31` range in the UTC time zone public var utcDate: Int { get { - Int(ref.getDate.function!().number!) + Int(ref.getDate!().number!) } set { - ref.setDate.function!(newValue) + _ = ref.setDate!(newValue) } } /// The day of the week in `0..6` range in the UTC time zone public var utcDay: Int { - Int(ref.getDay.function!().number!) + Int(ref.getDay!().number!) } /// The amount of hours in this day from `0..23` range in the UTC time zone public var utcHours: Int { get { - Int(ref.getHours.function!().number!) + Int(ref.getHours!().number!) } set { - ref.setHours.function!(newValue) + _ = ref.setHours!(newValue) } } /// The amount of minutes in this hours from `0..59` range in the UTC time zone public var utcMinutes: Int { get { - Int(ref.getMinutes.function!().number!) + Int(ref.getMinutes!().number!) } set { - ref.setMinutes.function!(newValue) + _ = ref.setMinutes!(newValue) } } /// The amount of seconds in this minute from `0..59` range in the UTC time zone public var utcSeconds: Int { get { - Int(ref.getSeconds.function!().number!) + Int(ref.getSeconds!().number!) } set { - ref.setSeconds.function!(newValue) + _ = ref.setSeconds!(newValue) } } /// The amount of milliseconds in this second `0..999` range in the UTC time zone public var utcMilliseconds: Int { get { - Int(ref.getMilliseconds.function!().number!) + Int(ref.getMilliseconds!().number!) } set { - ref.setMilliseconds.function!(newValue) + _ = ref.setMilliseconds!(newValue) } } /// Offset in minutes between the local time zone and UTC public var timezoneOffset: Int { - Int(ref.getTimezoneOffset.function!().number!) + Int(ref.getTimezoneOffset!().number!) } public func toISOString() -> String { - ref.toISOString.function!().string! + ref.toISOString!().string! } public func toLocaleDateString() -> String { - ref.toLocaleDateString.function!().string! + ref.toLocaleDateString!().string! } public func toLocaleTimeString() -> String { - ref.toLocaleTimeString.function!().string! + ref.toLocaleTimeString!().string! } public func toUTCString() -> String { - ref.toUTCString.function!().string! + ref.toUTCString!().string! } - /// Number of seconds since epoch ignoring leap seconds - public func now() -> Int { - Int(ref.now.function!().number!) + /// Number of seconds since midnight 01 January 1970 UTC to the present moment ignoring leap + /// seconds + public static func now() -> Double { + constructor.now!().number! + } + + /// Number of seconds since midnight 01 January 1970 UTC to the present moment ignoring leap + /// seconds + public func valueOf() -> Double { + ref.valueOf!().number! } } From e134515d49f1a0fdab068d62db6f52362c29e45c Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 21:24:41 +0100 Subject: [PATCH 3/7] Fix UTC properties, refine test expectations --- .../Sources/PrimaryTests/main.swift | 13 ++++++++ .../JavaScriptKit/BasicObjects/JSDate.swift | 30 +++++++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 323c90f0c..a948e33b5 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -417,4 +417,17 @@ try test("Date") { try expectEqual(date1.utcMinutes, date2.utcMinutes) try expectEqual(date1.utcSeconds, date2.utcSeconds) try expectEqual(date1.utcMilliseconds, date2.utcMilliseconds) + + let date3 = JSDate(millisecondsSinceEpoch: 0) + try expectEqual(date3.valueOf(), 0) + try expectEqual(date3.utcFullYear, 1970) + try expectEqual(date3.utcMonth, 0) + try expectEqual(date3.utcDate, 1) + // the epoch date was on Friday + try expectEqual(date3.utcDay, 4) + try expectEqual(date3.utcHours, 0) + try expectEqual(date3.utcMinutes, 0) + try expectEqual(date3.utcSeconds, 0) + try expectEqual(date3.utcMilliseconds, 0) + try expectEqual(date3.toISOString(), "1970-01-01T00:00:00.000Z") } diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index 3a4242766..cfe398f96 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -103,75 +103,75 @@ public final class JSDate { /// Year of this date in the UTC time zone public var utcFullYear: Int { get { - Int(ref.getFullYear!().number!) + Int(ref.getUTCFullYear!().number!) } set { - _ = ref.setFullYear!(newValue) + _ = ref.setUTCFullYear!(newValue) } } /// Month of this date in `0–11` range in the UTC time zone public var utcMonth: Int { get { - Int(ref.getMonth!().number!) + Int(ref.getUTCMonth!().number!) } set { - _ = ref.setMonth!(newValue) + _ = ref.setUTCMonth!(newValue) } } /// The day of the month in `1..31` range in the UTC time zone public var utcDate: Int { get { - Int(ref.getDate!().number!) + Int(ref.getUTCDate!().number!) } set { - _ = ref.setDate!(newValue) + _ = ref.setUTCDate!(newValue) } } /// The day of the week in `0..6` range in the UTC time zone public var utcDay: Int { - Int(ref.getDay!().number!) + Int(ref.getUTCDay!().number!) } /// The amount of hours in this day from `0..23` range in the UTC time zone public var utcHours: Int { get { - Int(ref.getHours!().number!) + Int(ref.getUTCHours!().number!) } set { - _ = ref.setHours!(newValue) + _ = ref.setUTCHours!(newValue) } } /// The amount of minutes in this hours from `0..59` range in the UTC time zone public var utcMinutes: Int { get { - Int(ref.getMinutes!().number!) + Int(ref.getUTCMinutes!().number!) } set { - _ = ref.setMinutes!(newValue) + _ = ref.setUTCMinutes!(newValue) } } /// The amount of seconds in this minute from `0..59` range in the UTC time zone public var utcSeconds: Int { get { - Int(ref.getSeconds!().number!) + Int(ref.getUTCSeconds!().number!) } set { - _ = ref.setSeconds!(newValue) + _ = ref.setUTCSeconds!(newValue) } } /// The amount of milliseconds in this second `0..999` range in the UTC time zone public var utcMilliseconds: Int { get { - Int(ref.getMilliseconds!().number!) + Int(ref.getUTCMilliseconds!().number!) } set { - _ = ref.setMilliseconds!(newValue) + _ = ref.setUTCMilliseconds!(newValue) } } From cbea311bec3a2a95a7fb98b5430f0b9399ead729 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 21:37:07 +0100 Subject: [PATCH 4/7] Implement Equatable and Comparable on JSDate --- .../TestSuites/Sources/PrimaryTests/main.swift | 3 +++ Sources/JavaScriptKit/BasicObjects/JSDate.swift | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index a948e33b5..0eda3b3bf 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -417,6 +417,7 @@ try test("Date") { try expectEqual(date1.utcMinutes, date2.utcMinutes) try expectEqual(date1.utcSeconds, date2.utcSeconds) try expectEqual(date1.utcMilliseconds, date2.utcMilliseconds) + try expectEqual(date1, date2) let date3 = JSDate(millisecondsSinceEpoch: 0) try expectEqual(date3.valueOf(), 0) @@ -430,4 +431,6 @@ try test("Date") { try expectEqual(date3.utcSeconds, 0) try expectEqual(date3.utcMilliseconds, 0) try expectEqual(date3.toISOString(), "1970-01-01T00:00:00.000Z") + + try expectEqual(date3 < date1, true) } diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index cfe398f96..2b21c0bc7 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -208,3 +208,13 @@ public final class JSDate { ref.valueOf!().number! } } + +extension JSDate: Comparable { + public static func ==(lhs: JSDate, rhs: JSDate) -> Bool { + return lhs.valueOf() == rhs.valueOf() + } + + public static func <(lhs: JSDate, rhs: JSDate) -> Bool { + return lhs.valueOf() < rhs.valueOf() + } +} \ No newline at end of file From 3bc029456fa5b344828514105bfa38d39a8b909f Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 23:07:52 +0100 Subject: [PATCH 5/7] Update Sources/JavaScriptKit/BasicObjects/JSDate.swift Co-authored-by: Jed Fox --- Sources/JavaScriptKit/BasicObjects/JSDate.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index 2b21c0bc7..8efbffd46 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -202,7 +202,7 @@ public final class JSDate { constructor.now!().number! } - /// Number of seconds since midnight 01 January 1970 UTC to the present moment ignoring leap + /// Number of milliseconds since midnight 01 January 1970 UTC to the present moment ignoring leap /// seconds public func valueOf() -> Double { ref.valueOf!().number! @@ -217,4 +217,4 @@ extension JSDate: Comparable { public static func <(lhs: JSDate, rhs: JSDate) -> Bool { return lhs.valueOf() < rhs.valueOf() } -} \ No newline at end of file +} From 08a0b78f91217e8d21c2dc11d7b3173d2910d3e9 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 23:08:00 +0100 Subject: [PATCH 6/7] Update Sources/JavaScriptKit/BasicObjects/JSDate.swift Co-authored-by: Jed Fox --- Sources/JavaScriptKit/BasicObjects/JSDate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index 8efbffd46..e33ad7c8e 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -196,7 +196,7 @@ public final class JSDate { ref.toUTCString!().string! } - /// Number of seconds since midnight 01 January 1970 UTC to the present moment ignoring leap + /// Number of milliseconds since midnight 01 January 1970 UTC to the present moment ignoring leap /// seconds public static func now() -> Double { constructor.now!().number! From 6c142eb69834fef40ba428235c88071df44d12a6 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 13 Sep 2020 23:08:55 +0100 Subject: [PATCH 7/7] Update Sources/JavaScriptKit/BasicObjects/JSDate.swift --- Sources/JavaScriptKit/BasicObjects/JSDate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JavaScriptKit/BasicObjects/JSDate.swift b/Sources/JavaScriptKit/BasicObjects/JSDate.swift index e33ad7c8e..dc5653212 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSDate.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSDate.swift @@ -202,7 +202,7 @@ public final class JSDate { constructor.now!().number! } - /// Number of milliseconds since midnight 01 January 1970 UTC to the present moment ignoring leap + /// Number of milliseconds since midnight 01 January 1970 UTC to the given date ignoring leap /// seconds public func valueOf() -> Double { ref.valueOf!().number!