From cd026aaed30320b16f0c5a409a8af6f1e338d0ec Mon Sep 17 00:00:00 2001 From: Jason Ji Date: Tue, 4 Oct 2016 16:40:00 -0400 Subject: [PATCH 1/4] Fix NSCalendar date(byAdding:to:options:) improperly returning nil date(byAdding:to:options:) was always trying to add the components to CFAbsoluteTime 0.0, rather than the passed-in date. --- Foundation/NSCalendar.swift | 2 +- TestFoundation/TestNSCalendar.swift | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Foundation/NSCalendar.swift b/Foundation/NSCalendar.swift index d6d0d4feb5..520cdd4b3e 100644 --- a/Foundation/NSCalendar.swift +++ b/Foundation/NSCalendar.swift @@ -579,7 +579,7 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding { open func date(byAdding comps: DateComponents, to date: Date, options opts: Options = []) -> Date? { var (vector, compDesc) = _convert(comps) - var at: CFAbsoluteTime = 0.0 + var at: CFAbsoluteTime = date.timeIntervalSinceReferenceDate let res: Bool = withUnsafeMutablePointer(to: &at) { t in return vector.withUnsafeMutableBufferPointer { (vectorBuffer: inout UnsafeMutableBufferPointer) in diff --git a/TestFoundation/TestNSCalendar.swift b/TestFoundation/TestNSCalendar.swift index 71e2ec4ad0..8b48d2611c 100644 --- a/TestFoundation/TestNSCalendar.swift +++ b/TestFoundation/TestNSCalendar.swift @@ -24,6 +24,7 @@ class TestNSCalendar: XCTestCase { ("test_gettingDatesOnHebrewCalendar", test_gettingDatesOnHebrewCalendar ), ("test_gettingDatesOnChineseCalendar", test_gettingDatesOnChineseCalendar), ("test_copy",test_copy), + ("test_addingDates", test_addingDates) // Disabled because this fails on linux https://bugs.swift.org/browse/SR-320 // ("test_currentCalendarRRstability", test_currentCalendarRRstability), ] @@ -89,6 +90,17 @@ class TestNSCalendar: XCTestCase { XCTAssertEqual(copy.firstWeekday, 2) XCTAssertEqual(copy.minimumDaysInFirstWeek, 2) } + + func test_addingDates() { + var calendar = Calendar.current + let today = calendar.current.date(from: DateComponents(year: 2016, month: 10, day: 4)) + let diffComponents = DateComponents(day: 1) + let tomorrow = calendar.date(byAdding: diffComponents, to: today) + + XCTAssertEqual(tomorrow.year, 2016) + XCTAssertEqual(tomorrow.month, 10) + XCTAssertEqual(tomorrow.day, 5) + } } class TestNSDateComponents: XCTestCase { From 2569d56996426647ecd501a12d84810fe398e698 Mon Sep 17 00:00:00 2001 From: Jason Ji Date: Tue, 4 Oct 2016 18:32:56 -0400 Subject: [PATCH 2/4] More fixes: - DateComponent should only return isLeapMonth if the underlying leapMonthSet variable is true. Previously, DateComponent was setting isLeapMonth to false in situations where there is no concept of isLeapMonth. - _convert was using 'L' for isLeapMonth, when the corresponding UCalendarDateFields enum value for isLeapMonth is 'l'. This was causing _CFCalendarAddComponentsV to return error status. --- Foundation/DateComponents.swift | 2 +- Foundation/NSCalendar.swift | 2 +- TestFoundation/TestNSCalendar.swift | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Foundation/DateComponents.swift b/Foundation/DateComponents.swift index aa167234cd..9cde6aba10 100644 --- a/Foundation/DateComponents.swift +++ b/Foundation/DateComponents.swift @@ -189,7 +189,7 @@ public struct DateComponents : ReferenceConvertible, Hashable, Equatable, _Mutab /// Set to true if these components represent a leap month. public var isLeapMonth: Bool? { - get { return _handle.map { $0.isLeapMonth } } + get { return _handle.map { $0.leapMonthSet ? $0.isLeapMonth : nil } } set { _applyMutation { // Technically, the underlying class does not support setting isLeapMonth to nil, but it could - so we leave the API consistent. diff --git a/Foundation/NSCalendar.swift b/Foundation/NSCalendar.swift index 520cdd4b3e..624b103408 100644 --- a/Foundation/NSCalendar.swift +++ b/Foundation/NSCalendar.swift @@ -461,7 +461,7 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding { _convert(comps.weekday, type: "E", vector: &vector, compDesc: &compDesc) _convert(comps.weekdayOrdinal, type: "F", vector: &vector, compDesc: &compDesc) _convert(comps.month, type: "M", vector: &vector, compDesc: &compDesc) - _convert(comps.isLeapMonth, type: "L", vector: &vector, compDesc: &compDesc) + _convert(comps.isLeapMonth, type: "l", vector: &vector, compDesc: &compDesc) _convert(comps.day, type: "d", vector: &vector, compDesc: &compDesc) _convert(comps.hour, type: "H", vector: &vector, compDesc: &compDesc) _convert(comps.minute, type: "m", vector: &vector, compDesc: &compDesc) diff --git a/TestFoundation/TestNSCalendar.swift b/TestFoundation/TestNSCalendar.swift index 8b48d2611c..79ae5b47a2 100644 --- a/TestFoundation/TestNSCalendar.swift +++ b/TestFoundation/TestNSCalendar.swift @@ -92,14 +92,15 @@ class TestNSCalendar: XCTestCase { } func test_addingDates() { - var calendar = Calendar.current - let today = calendar.current.date(from: DateComponents(year: 2016, month: 10, day: 4)) + let calendar = Calendar.current + let today = Date() let diffComponents = DateComponents(day: 1) let tomorrow = calendar.date(byAdding: diffComponents, to: today) - XCTAssertEqual(tomorrow.year, 2016) - XCTAssertEqual(tomorrow.month, 10) - XCTAssertEqual(tomorrow.day, 5) + let tomorrowComponents = calendar.dateComponents([.year, .month, .day], from: tomorrow!) + XCTAssertEqual(tomorrowComponents.year, 2016) + XCTAssertEqual(tomorrowComponents.month, 10) + XCTAssertEqual(tomorrowComponents.day, 5) } } From 3275b30ef01333409cf3c04e9a4110b3d6f394d0 Mon Sep 17 00:00:00 2001 From: Jason Ji Date: Tue, 4 Oct 2016 18:40:58 -0400 Subject: [PATCH 3/4] Update tests to work beyond today --- TestFoundation/TestNSCalendar.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TestFoundation/TestNSCalendar.swift b/TestFoundation/TestNSCalendar.swift index 79ae5b47a2..15168dda61 100644 --- a/TestFoundation/TestNSCalendar.swift +++ b/TestFoundation/TestNSCalendar.swift @@ -93,14 +93,14 @@ class TestNSCalendar: XCTestCase { func test_addingDates() { let calendar = Calendar.current - let today = Date() + let thisDay = calendar.date(from: DateComponents(year: 2016, month: 10, day: 4))! let diffComponents = DateComponents(day: 1) - let tomorrow = calendar.date(byAdding: diffComponents, to: today) + let dayAfter = calendar.date(byAdding: diffComponents, to: thisDay) - let tomorrowComponents = calendar.dateComponents([.year, .month, .day], from: tomorrow!) - XCTAssertEqual(tomorrowComponents.year, 2016) - XCTAssertEqual(tomorrowComponents.month, 10) - XCTAssertEqual(tomorrowComponents.day, 5) + let dayAfterComponents = calendar.dateComponents([.year, .month, .day], from: dayAfter!) + XCTAssertEqual(dayAfterComponents.year, 2016) + XCTAssertEqual(dayAfterComponents.month, 10) + XCTAssertEqual(dayAfterComponents.day, 5) } } From 87063ed5c8d627070892bde9188b5de63f3a9e43 Mon Sep 17 00:00:00 2001 From: Jason Ji Date: Tue, 4 Oct 2016 19:55:42 -0400 Subject: [PATCH 4/4] Update test to explicitly use Gregorian calendar --- TestFoundation/TestNSCalendar.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestFoundation/TestNSCalendar.swift b/TestFoundation/TestNSCalendar.swift index 15168dda61..3b11faa6f9 100644 --- a/TestFoundation/TestNSCalendar.swift +++ b/TestFoundation/TestNSCalendar.swift @@ -92,7 +92,7 @@ class TestNSCalendar: XCTestCase { } func test_addingDates() { - let calendar = Calendar.current + let calendar = Calendar(identifier: .gregorian) let thisDay = calendar.date(from: DateComponents(year: 2016, month: 10, day: 4))! let diffComponents = DateComponents(day: 1) let dayAfter = calendar.date(byAdding: diffComponents, to: thisDay)