Skip to content

Commit bd9397b

Browse files
authored
Update Time implementation (#288)
1 parent 6561d64 commit bd9397b

File tree

2 files changed

+220
-11
lines changed

2 files changed

+220
-11
lines changed

Sources/OpenSwiftUICore/Data/Time.swift

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,92 +7,178 @@
77

88
#if canImport(QuartzCore)
99
public import QuartzCore
10+
#else
11+
public import Foundation
1012
#endif
1113

14+
/// A type that represents a time value in seconds.
15+
///
16+
/// Use `Time` to represent durations or time intervals within the OpenSwiftUI framework.
17+
/// The structure provides various operators and methods for time-related calculations.
18+
///
19+
/// Example:
20+
///
21+
/// let duration = Time(seconds: 2.5)
22+
/// let delay = Time.systemUptime + 1.0
23+
///
1224
@_spi(ForOpenSwiftUIOnly)
1325
public struct Time: Equatable, Hashable, Comparable {
26+
/// The time value in seconds.
1427
public var seconds: Double
28+
29+
/// Creates a time value from the specified number of seconds.
30+
/// - Parameter seconds: The number of seconds.
1531
public init(seconds: Double) {
1632
self.seconds = seconds
1733
}
34+
35+
/// Creates a time value initialized to zero seconds.
1836
public init() {
1937
self.seconds = .zero
2038
}
39+
40+
/// A time value of zero seconds.
2141
public static let zero: Time = Time(seconds: .zero)
22-
public static let infinity: Time = Time(seconds: .infinity)
2342

24-
#if canImport(QuartzCore)
43+
/// A time value representing infinity.
44+
public static let infinity: Time = Time(seconds: .infinity)
45+
46+
/// The current system uptime as a `Time` value.
47+
///
48+
/// This property provides the time since system boot using platform-specific
49+
/// implementation.
2550
@inlinable
2651
public static var systemUptime: Time {
52+
// NOTE: ProcessInfo.systemUptime is a general API available on all platforms via Foundation.
53+
// The implementation result of ProcessInfo().systemUptime and CACurrentMediaTime() is the same on Darwin platforms.
54+
// Both of them is using `mach_absolute_time` under the hood for Darwin platforms.
55+
// On non-Darwin platforms, `CACurrentMediaTime` is not available. But `ProcessInfo.systemUptime` is available.
56+
#if canImport(QuartzCore)
2757
Time(seconds: CACurrentMediaTime())
58+
#else
59+
Time(seconds: ProcessInfo.processInfo.systemUptime)
60+
#endif
2861
}
29-
#endif
3062

63+
/// Returns the negation of the specified time value.
64+
/// - Parameter lhs: A time value.
65+
/// - Returns: A time value that is the negation of the input.
3166
@inlinable
32-
prefix public static func - (lhs: Time) -> Time {
67+
public static prefix func - (lhs: Time) -> Time {
3368
Time(seconds: -lhs.seconds)
3469
}
35-
70+
71+
/// Adds a time value and a number of seconds.
72+
/// - Parameters:
73+
/// - lhs: A time value.
74+
/// - rhs: The number of seconds to add.
75+
/// - Returns: A new time value representing the sum.
3676
@inlinable
3777
public static func + (lhs: Time, rhs: Double) -> Time {
3878
Time(seconds: lhs.seconds + rhs)
3979
}
4080

81+
/// Adds a number of seconds to a time value.
82+
/// - Parameters:
83+
/// - lhs: The number of seconds to add.
84+
/// - rhs: A time value.
85+
/// - Returns: A new time value representing the sum.
4186
@inlinable
4287
public static func + (lhs: Double, rhs: Time) -> Time {
4388
rhs + lhs
4489
}
4590

91+
/// Subtracts a number of seconds from a time value.
92+
/// - Parameters:
93+
/// - lhs: A time value.
94+
/// - rhs: The number of seconds to subtract.
95+
/// - Returns: A new time value representing the difference.
4696
@inlinable
4797
public static func - (lhs: Time, rhs: Double) -> Time {
4898
Time(seconds: lhs.seconds - rhs)
4999
}
50100

101+
/// Calculates the time difference between two time values.
102+
/// - Parameters:
103+
/// - lhs: The first time value.
104+
/// - rhs: The second time value.
105+
/// - Returns: The difference in seconds between the two time values.
51106
@inlinable
52107
public static func - (lhs: Time, rhs: Time) -> Double {
53108
lhs.seconds - rhs.seconds
54109
}
55-
110+
111+
/// Multiplies a time value by a scalar.
112+
/// - Parameters:
113+
/// - lhs: A time value.
114+
/// - rhs: The scalar to multiply by.
115+
/// - Returns: A new time value representing the product.
56116
@inlinable
57117
public static func * (lhs: Time, rhs: Double) -> Time {
58118
Time(seconds: lhs.seconds * rhs)
59119
}
60-
120+
121+
/// Divides a time value by a scalar.
122+
/// - Parameters:
123+
/// - lhs: A time value.
124+
/// - rhs: The scalar to divide by.
125+
/// - Returns: A new time value representing the quotient.
61126
@inlinable
62127
public static func / (lhs: Time, rhs: Double) -> Time {
63128
return Time(seconds: lhs.seconds / rhs)
64129
}
65-
130+
131+
/// Adds a number of seconds to a time value, storing the result in the left-hand operand.
132+
/// - Parameters:
133+
/// - lhs: The time value to modify.
134+
/// - rhs: The number of seconds to add.
66135
@inlinable
67136
public static func += (lhs: inout Time, rhs: Double) {
68137
lhs = lhs + rhs
69138
}
70139

140+
/// Subtracts a number of seconds from a time value, storing the result in the left-hand operand.
141+
/// - Parameters:
142+
/// - lhs: The time value to modify.
143+
/// - rhs: The number of seconds to subtract.
71144
@inlinable
72145
public static func -= (lhs: inout Time, rhs: Double) {
73146
lhs = lhs - rhs
74147
}
75148

149+
/// Multiplies a time value by a scalar, storing the result in the left-hand operand.
150+
/// - Parameters:
151+
/// - lhs: The time value to modify.
152+
/// - rhs: The scalar to multiply by.
76153
@inlinable
77154
public static func *= (lhs: inout Time, rhs: Double) {
78155
lhs = lhs * rhs
79156
}
80-
157+
158+
/// Divides a time value by a scalar, storing the result in the left-hand operand.
159+
/// - Parameters:
160+
/// - lhs: The time value to modify.
161+
/// - rhs: The scalar to divide by.
81162
@inlinable
82163
public static func /= (lhs: inout Time, rhs: Double) {
83164
lhs = lhs / rhs
84165
}
85166

167+
/// Returns a Boolean value indicating whether the first time value is less than the second.
168+
/// - Parameters:
169+
/// - lhs: A time value to compare.
170+
/// - rhs: Another time value to compare.
171+
/// - Returns: `true` if the first value is less than the second value; otherwise, `false`.
86172
@inlinable
87173
public static func < (lhs: Time, rhs: Time) -> Bool {
88174
lhs.seconds < rhs.seconds
89175
}
90-
176+
91177
@inlinable
92178
public static func == (a: Time, b: Time) -> Bool {
93179
a.seconds == b.seconds
94180
}
95-
181+
96182
@inlinable
97183
public func hash(into hasher: inout Hasher) {
98184
hasher.combine(seconds)
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//
2+
// TimeTests.swift
3+
// OpenSwiftUICoreTests
4+
5+
@_spi(ForOpenSwiftUIOnly)
6+
import OpenSwiftUICore
7+
import Testing
8+
import Numerics
9+
10+
struct TimeTests {
11+
@Test
12+
func initialization() {
13+
let time1 = Time(seconds: 10)
14+
#expect(time1.seconds.isApproximatelyEqual(to: 10))
15+
16+
let time2 = Time()
17+
#expect(time2.seconds.isApproximatelyEqual(to: 0))
18+
19+
#expect(Time.zero.seconds.isApproximatelyEqual(to: 0))
20+
#expect(Time.infinity.seconds == Double.infinity)
21+
}
22+
23+
@Test
24+
func systemUptime() {
25+
let uptime = Time.systemUptime
26+
#expect(uptime.seconds > 0)
27+
}
28+
29+
@Test
30+
func negation() {
31+
let time = Time(seconds: 5)
32+
let negated = -time
33+
#expect(negated.seconds.isApproximatelyEqual(to: -5))
34+
}
35+
36+
@Test
37+
func addition() {
38+
let time = Time(seconds: 5)
39+
let result1 = time + 3
40+
#expect(result1.seconds.isApproximatelyEqual(to: 8))
41+
42+
let result2 = 3 + time
43+
#expect(result2.seconds.isApproximatelyEqual(to: 8))
44+
45+
var time2 = Time(seconds: 5)
46+
time2 += 3
47+
#expect(time2.seconds.isApproximatelyEqual(to: 8))
48+
}
49+
50+
@Test
51+
func subtraction() {
52+
let time = Time(seconds: 5)
53+
let result1 = time - 3
54+
#expect(result1.seconds.isApproximatelyEqual(to: 2))
55+
56+
let time2 = Time(seconds: 8)
57+
let diff = time2 - time
58+
#expect(diff.isApproximatelyEqual(to: 3))
59+
60+
var time3 = Time(seconds: 5)
61+
time3 -= 3
62+
#expect(time3.seconds.isApproximatelyEqual(to: 2))
63+
}
64+
65+
@Test
66+
func multiplication() {
67+
let time = Time(seconds: 5)
68+
let result = time * 3
69+
#expect(result.seconds.isApproximatelyEqual(to: 15))
70+
71+
var time2 = Time(seconds: 5)
72+
time2 *= 3
73+
#expect(time2.seconds.isApproximatelyEqual(to: 15))
74+
}
75+
76+
@Test
77+
func division() {
78+
let time = Time(seconds: 15)
79+
let result = time / 3
80+
#expect(result.seconds.isApproximatelyEqual(to: 5))
81+
82+
var time2 = Time(seconds: 15)
83+
time2 /= 3
84+
#expect(time2.seconds.isApproximatelyEqual(to: 5))
85+
}
86+
87+
@Test
88+
func comparison() {
89+
let time1 = Time(seconds: 5)
90+
let time2 = Time(seconds: 10)
91+
let time3 = Time(seconds: 5)
92+
93+
#expect(time1 < time2)
94+
#expect(time1 <= time2)
95+
#expect(time2 > time1)
96+
#expect(time2 >= time1)
97+
#expect(time1 == time3)
98+
#expect(time1 != time2)
99+
}
100+
101+
@Test
102+
func hashable() {
103+
let time1 = Time(seconds: 5)
104+
let time2 = Time(seconds: 5)
105+
let time3 = Time(seconds: 10)
106+
107+
var set = Set<Time>()
108+
set.insert(time1)
109+
set.insert(time2)
110+
set.insert(time3)
111+
112+
#expect(set.count == 2)
113+
}
114+
115+
@Test
116+
func sendable() {
117+
let time = Time(seconds: 5)
118+
Task {
119+
let copiedTime = time
120+
#expect(copiedTime.seconds.isApproximatelyEqual(to: 5))
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)