Skip to content

Commit 2a604a4

Browse files
authored
Merge pull request #2162 from spevans/pr_sr_10515
SR-10515: Calendar.date(from:) unexpectedly mutates Calendar instance
2 parents 5dfe636 + 24f377e commit 2a604a4

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

Foundation/NSCalendar.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,8 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding {
515515

516516
open func date(from comps: DateComponents) -> Date? {
517517
var (vector, compDesc) = _convert(comps)
518-
518+
519+
let oldTz = self.timeZone
519520
self.timeZone = comps.timeZone ?? timeZone
520521

521522
var at: CFAbsoluteTime = 0.0
@@ -524,7 +525,8 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding {
524525
return _CFCalendarComposeAbsoluteTimeV(_cfObject, t, compDesc, vectorBuffer.baseAddress!, Int32(vectorBuffer.count))
525526
}
526527
}
527-
528+
529+
self.timeZone = oldTz
528530
if res {
529531
return Date(timeIntervalSinceReferenceDate: at)
530532
} else {

TestFoundation/TestCalendar.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class TestCalendar: XCTestCase {
2525
("test_ampmSymbols", test_ampmSymbols),
2626
("test_currentCalendarRRstability", test_currentCalendarRRstability),
2727
("test_hashing", test_hashing),
28+
("test_dateFromDoesntMutate", test_dateFromDoesntMutate),
2829
]
2930
}
3031

@@ -227,6 +228,32 @@ class TestCalendar: XCTestCase {
227228
]
228229
checkHashable(calendars2, equalityOracle: { $0 == $1 })
229230
}
231+
232+
func test_dateFromDoesntMutate() throws {
233+
// Check that date(from:) does not change the timeZone of the calendar
234+
let df = DateFormatter()
235+
df.dateFormat = "yyyy-MM-dd"
236+
df.timeZone = try TimeZone(identifier: "UTC").unwrapped()
237+
238+
var calendar = Calendar(identifier: .gregorian)
239+
calendar.locale = Locale(identifier: "en_US_POSIX")
240+
calendar.timeZone = try TimeZone(secondsFromGMT: 0).unwrapped()
241+
242+
let calendarCopy = calendar
243+
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
244+
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
245+
246+
let dc = try calendarCopy.dateComponents(in: TimeZone(identifier: "America/New_York").unwrapped(), from: df.date(from: "2019-01-01").unwrapped())
247+
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
248+
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
249+
250+
let dt = try calendarCopy.date(from: dc).unwrapped()
251+
XCTAssertEqual(dt.description, "2019-01-01 00:00:00 +0000")
252+
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
253+
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
254+
XCTAssertEqual(calendarCopy.timeZone, calendar.timeZone)
255+
XCTAssertEqual(calendarCopy, calendar)
256+
}
230257
}
231258

232259
class TestNSDateComponents: XCTestCase {

0 commit comments

Comments
 (0)