Skip to content

Commit e268301

Browse files
authored
Handle 1-day weekend properly (#1450)
India only has Sunday as their weekend; the other places (GB, US, etc) have two days. Update `Calendar.nextWeekend(startingAfter:direction:)` to handle this case. 153114732
1 parent f1d5488 commit e268301

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

Sources/FoundationEssentials/Calendar/Calendar.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,9 +1153,17 @@ public struct Calendar : Hashable, Equatable, Sendable {
11531153
}
11541154

11551155
let weekendEndComponents = DateComponents(weekday: weekend.end)
1156-
// We only care about the end date to get the interval of the weekend, so we don't care if it falls ahead of the passed in date. Always search forward from here, since we just found the *beginning* of the weekend.
1157-
guard var end = nextDate(after: start, matching: weekendEndComponents, matchingPolicy: .nextTime, repeatedTimePolicy: .first, direction: .forward) else {
1158-
return nil
1156+
1157+
var end: Date
1158+
if weekend.start == weekend.end {
1159+
// This locale has a 1-day weekend
1160+
end = start
1161+
} else {
1162+
// We only care about the end date to get the interval of the weekend, so we don't care if it falls ahead of the passed in date. Always search forward from here, since we just found the *beginning* of the weekend.
1163+
guard let possibleEnd = nextDate(after: start, matching: weekendEndComponents, matchingPolicy: .nextTime, repeatedTimePolicy: .first, direction: .forward) else {
1164+
return nil
1165+
}
1166+
end = possibleEnd
11591167
}
11601168

11611169
if let ceaseTime = weekend.ceaseTime, ceaseTime > 0 {
@@ -1667,7 +1675,8 @@ package struct WeekendRange: Equatable, Hashable {
16671675
package var ceaseTime: TimeInterval?
16681676
package var start: Int
16691677
package var end: Int
1670-
1678+
1679+
// start == end means a one-day weekend. There isn't a known use case for 7-day weekend.
16711680
package init(onsetTime: TimeInterval? = nil, ceaseTime: TimeInterval? = nil, start: Int, end: Int) {
16721681
self.onsetTime = onsetTime
16731682
self.ceaseTime = ceaseTime

Tests/FoundationInternationalizationTests/CalendarTests.swift

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,49 @@ private struct CalendarTests {
907907
#expect(weekend != nil)
908908
#expect(weekend == weekendForNilLocale)
909909
}
910-
910+
911+
@Test func weekendRange_1dayWeekend() throws {
912+
var calendar = Calendar(identifier: .gregorian)
913+
calendar.locale = Locale(identifier: "en_IN")
914+
calendar.timeZone = .gmt
915+
916+
do {
917+
// Date(timeIntervalSinceReferenceDate: 0) is a Monday
918+
// India's weekend is on Sunday
919+
let weekend = try #require(calendar.nextWeekend(startingAfter: Date(timeIntervalSinceReferenceDate: 0)))
920+
let expectStart = try Date("2001-01-07T00:00:00Z", strategy: .iso8601)
921+
#expect(weekend.start == expectStart)
922+
923+
let expectEnd = try Date("2001-01-08T00:00:00Z", strategy: .iso8601)
924+
#expect(weekend.end == expectEnd)
925+
926+
let previousWeekend = try #require(calendar.nextWeekend(startingAfter: Date(timeIntervalSinceReferenceDate: 0), direction: .backward))
927+
let expectedPreviousStart = try Date("2000-12-31T00:00:00Z", strategy: .iso8601)
928+
#expect(previousWeekend.start == expectedPreviousStart)
929+
930+
let expectedPreviousEnd = try Date("2001-01-01T00:00:00Z", strategy: .iso8601)
931+
#expect(previousWeekend.end == expectedPreviousEnd)
932+
}
933+
934+
// Starting on a weekend
935+
do {
936+
let sundayMidnight = Date(timeIntervalSinceReferenceDate: -86400)
937+
let weekend = try #require(calendar.nextWeekend(startingAfter: sundayMidnight))
938+
let expectStart = try Date("2001-01-07T00:00:00Z", strategy: .iso8601)
939+
#expect(weekend.start == expectStart)
940+
941+
let expectEnd = try Date("2001-01-08T00:00:00Z", strategy: .iso8601)
942+
#expect(weekend.end == expectEnd)
943+
944+
let previousWeekend = try #require(calendar.nextWeekend(startingAfter: sundayMidnight, direction: .backward))
945+
let expectedPreviousStart = try Date("2000-12-24T00:00:00Z", strategy: .iso8601)
946+
#expect(previousWeekend.start == expectedPreviousStart)
947+
948+
let expectedPreviousEnd = try Date("2000-12-25T00:00:00Z", strategy: .iso8601)
949+
#expect(previousWeekend.end == expectedPreviousEnd)
950+
}
951+
}
952+
911953
@Test func datesAdding_range() {
912954
let startDate = Date(timeIntervalSinceReferenceDate: 689292158.712307) // 2022-11-04 22:02:38 UTC
913955
let endDate = startDate + (86400 * 3) + (3600 * 2) // 3 days + 2 hours later - cross a DST boundary which adds a day with an additional hour in it

0 commit comments

Comments
 (0)