15
15
#endif
16
16
#endif
17
17
18
+ extension String {
19
+ func containsInOrder( requiresLastToBeAtEnd: Bool = false , _ substrings: String ... ) -> Bool {
20
+ var foundRange : Range < String . Index > = startIndex ..< startIndex
21
+ for substring in substrings {
22
+ if let newRange = range ( of: substring, options: [ ] , range: foundRange. upperBound..< endIndex, locale: nil ) {
23
+ foundRange = newRange
24
+ } else {
25
+ return false
26
+ }
27
+ }
28
+
29
+ if requiresLastToBeAtEnd {
30
+ return foundRange. upperBound == endIndex
31
+ } else {
32
+ return true
33
+ }
34
+ }
35
+ }
36
+
18
37
class TestDateIntervalFormatter : XCTestCase {
19
38
private var formatter : DateIntervalFormatter !
20
39
@@ -38,47 +57,52 @@ class TestDateIntervalFormatter: XCTestCase {
38
57
let older = Date ( timeIntervalSinceReferenceDate: 0 )
39
58
let newer = Date ( timeIntervalSinceReferenceDate: 3e9 )
40
59
41
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
42
- " January 1, 2001, 12:00:00 AM Greenwich Mean Time – January 25, 2096, 5:20:00 AM Greenwich Mean Time " )
60
+ let result = formatter. string ( from: older, to: newer)
61
+ XCTAssert ( result. containsInOrder ( " January 1 " , " 2001 " , " 12:00:00 AM " , " Greenwich Mean Time " ,
62
+ " January 25 " , " 2096 " , " 5:20:00 AM " , " Greenwich Mean Time " ) )
43
63
}
44
64
45
65
func testStringFromDateToDateAcrossThreeMillionSeconds( ) {
46
66
let older = Date ( timeIntervalSinceReferenceDate: 0 )
47
67
let newer = Date ( timeIntervalSinceReferenceDate: 3e6 )
48
68
49
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
50
- " January 1, 2001, 12:00:00 AM Greenwich Mean Time – February 4, 2001, 5:20:00 PM Greenwich Mean Time " )
69
+ let result = formatter. string ( from: older, to: newer)
70
+ XCTAssert ( result. containsInOrder ( " January 1 " , " 2001 " , " 12:00:00 AM " , " Greenwich Mean Time " ,
71
+ " February 4 " , " 2001 " , " 5:20:00 AM " , " Greenwich Mean Time " ) )
51
72
}
52
73
53
74
func testStringFromDateToDateAcrossThreeBillionSecondsReversed( ) {
54
75
let older = Date ( timeIntervalSinceReferenceDate: 0 )
55
76
let newer = Date ( timeIntervalSinceReferenceDate: 3e9 )
56
77
57
- XCTAssertEqual ( formatter. string ( from: newer, to: older) ,
58
- " January 25, 2096, 5:20:00 AM Greenwich Mean Time – January 1, 2001, 12:00:00 AM Greenwich Mean Time " )
78
+ let result = formatter. string ( from: older, to: newer)
79
+ XCTAssert ( result. containsInOrder ( " January 25 " , " 2096 " , " 5:20:00 AM " , " Greenwich Mean Time " ,
80
+ " January 1 " , " 2001 " , " 12:00:00 AM " , " Greenwich Mean Time " ) )
59
81
}
60
82
61
83
func testStringFromDateToDateAcrossThreeMillionSecondsReversed( ) {
62
84
let older = Date ( timeIntervalSinceReferenceDate: 0 )
63
85
let newer = Date ( timeIntervalSinceReferenceDate: 3e6 )
64
86
65
- XCTAssertEqual ( formatter. string ( from: newer, to: older) ,
66
- " February 4, 2001, 5:20:00 PM Greenwich Mean Time – January 1, 2001, 12:00:00 AM Greenwich Mean Time " )
87
+ let result = formatter. string ( from: older, to: newer)
88
+ XCTAssert ( result. containsInOrder ( " February 4 " , " 2001 " , " 5:20:00 AM " , " Greenwich Mean Time " ,
89
+ " January 1 " , " 2001 " , " 12:00:00 AM " , " Greenwich Mean Time " ) )
67
90
}
68
91
69
92
func testStringFromDateToSameDate( ) {
70
93
let date = Date ( timeIntervalSinceReferenceDate: 3e6 )
71
94
72
95
// For a range from a date to itself, we represent the date only once, with no interdate separator.
73
- XCTAssertEqual ( formatter. string ( from: date, to: date) ,
74
- " February 4, 2001, 5:20:00 PM Greenwich Mean Time " )
96
+ let result = formatter. string ( from: date, to: date)
97
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " February 4 " , " 2001 " , " 5:20:00 AM " , " Greenwich Mean Time " ) )
75
98
}
76
99
77
- func testStringFromDateIntervalAcrossThreeMillionSeconds( ) {
100
+ func testStringFromDateIntervalAcrossThreeMillionSeconds( ) throws {
78
101
let interval = DateInterval ( start: Date ( timeIntervalSinceReferenceDate: 0 ) , duration: 3e6 )
79
102
80
- XCTAssertEqual ( formatter. string ( from: interval) ,
81
- " January 1, 2001, 12:00:00 AM Greenwich Mean Time – February 4, 2001, 5:20:00 PM Greenwich Mean Time " )
103
+ let result = try formatter. string ( from: interval) . unwrapped ( )
104
+ XCTAssert ( result. containsInOrder ( " January 1 " , " 2001 " , " 12:00:00 AM " , " Greenwich Mean Time " ,
105
+ " February 4 " , " 2001 " , " 5:20:00 AM " , " Greenwich Mean Time " ) )
82
106
}
83
107
84
108
func testStringFromDateToDateAcrossOneWeek( ) {
@@ -88,16 +112,16 @@ class TestDateIntervalFormatter: XCTestCase {
88
112
let older = Date ( timeIntervalSinceReferenceDate: 0 )
89
113
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 7 )
90
114
91
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
92
- " Jan 1 – 8 " )
115
+ let result = formatter. string ( from: older, to: newer)
116
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " Jan " , " 1 " , " 8 " ) )
93
117
}
94
118
95
119
do {
96
120
let older = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 28 )
97
121
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 34 )
98
122
99
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
100
- " Jan 29 – Feb 4 " )
123
+ let result = formatter. string ( from: older, to: newer)
124
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " Jan " , " 29 " , " Feb " , " 4 " ) )
101
125
}
102
126
}
103
127
@@ -110,16 +134,17 @@ class TestDateIntervalFormatter: XCTestCase {
110
134
let older = Date ( timeIntervalSinceReferenceDate: 0 )
111
135
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 7 )
112
136
113
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
114
- " Jan 1 – 8 " )
137
+ let result = formatter. string ( from: older, to: newer)
138
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " Jan " , " 1 " , " 8 " ) )
115
139
}
116
140
117
141
do {
118
142
let older = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 28 )
119
143
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 34 )
120
144
121
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
122
- " Jan 29 – 4 " )
145
+ let result = formatter. string ( from: older, to: newer)
146
+ XCTAssert ( result. containsInOrder ( requiresLastToBeAtEnd: true , " Jan " , " 29 " , " 4 " ) )
147
+ XCTAssertNil ( result. range ( of: " Feb " ) )
123
148
}
124
149
}
125
150
#endif
@@ -130,8 +155,8 @@ class TestDateIntervalFormatter: XCTestCase {
130
155
let older = Date ( timeIntervalSinceReferenceDate: 0 )
131
156
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 60 )
132
157
133
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
134
- " Jan 1 – Mar 2 " )
158
+ let result = formatter. string ( from: older, to: newer)
159
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " Jan " , " 1 " , " Mar " , " 2 " ) )
135
160
}
136
161
137
162
#if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS))
@@ -143,18 +168,21 @@ class TestDateIntervalFormatter: XCTestCase {
143
168
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 24 * 60 )
144
169
145
170
// Minimization shouldn't do anything since this spans more than a month
146
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
147
- " Jan 1 – Mar 2 " )
171
+ let result = formatter. string ( from: older, to: newer)
172
+ XCTAssert ( result . containsInOrder ( requiresLastToBeAtEnd : true , " Jan " , " 1 " , " Mar " , " 2 " ) )
148
173
}
149
174
#endif
150
175
151
- func testStringFromDateToDateAcrossFiveHours( ) {
176
+ func testStringFromDateToDateAcrossFiveHours( ) throws {
152
177
do {
153
178
let older = Date ( timeIntervalSinceReferenceDate: 0 )
154
179
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 5 )
155
180
156
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
157
- " January 1, 2001, 12:00:00 AM GMT – 5:00:00 AM GMT " )
181
+ let result = formatter. string ( from: older, to: newer)
182
+ XCTAssert ( result. containsInOrder ( requiresLastToBeAtEnd: true , " January " , " 1 " , " 2001 " , " 12:00:00 AM " , " 5:00:00 AM " ) )
183
+
184
+ let firstJanuary = try result. range ( of: " January " ) . unwrapped ( )
185
+ XCTAssertNil ( result [ firstJanuary. upperBound... ] . range ( of: " January " ) ) // January appears only once.
158
186
}
159
187
160
188
do {
@@ -163,16 +191,20 @@ class TestDateIntervalFormatter: XCTestCase {
163
191
164
192
XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
165
193
" January 1, 2001, 10:00:00 PM Greenwich Mean Time – January 2, 2001, 3:00:00 AM Greenwich Mean Time " )
194
+ let result = formatter. string ( from: older, to: newer)
195
+ XCTAssert ( result. containsInOrder ( requiresLastToBeAtEnd: true , " January " , " 1 " , " 2001 " , " 10:00:00 AM " , " 5:00:00 AM " ) )
166
196
}
167
197
}
168
198
169
- func testStringFromDateToDateAcrossEighteenHours( ) {
199
+ func testStringFromDateToDateAcrossEighteenHours( ) throws {
170
200
let older = Date ( timeIntervalSinceReferenceDate: 0 )
171
201
let newer = Date ( timeIntervalSinceReferenceDate: 3600 * 18 )
172
202
173
- // Minimization shouldn't do anything since this spans more than a month
174
- XCTAssertEqual ( formatter. string ( from: older, to: newer) ,
175
- " January 1, 2001, 12:00:00 AM GMT – 6:00:00 PM GMT " )
203
+ let result = formatter. string ( from: older, to: newer)
204
+ XCTAssert ( result. containsInOrder ( requiresLastToBeAtEnd: true , " January " , " 1 " , " 2001 " , " 12:00:00 AM " , " 6:00:00 PM " ) )
205
+
206
+ let firstJanuary = try result. range ( of: " January " ) . unwrapped ( )
207
+ XCTAssertNil ( result [ firstJanuary. upperBound... ] . range ( of: " January " ) ) // January appears only once.
176
208
}
177
209
178
210
static var allTests : [ ( String , ( TestDateIntervalFormatter ) -> ( ) throws -> Void ) ] {
0 commit comments