我不知道是否有更简单的方法来完成您想要的,但这就是我想出的。首先,我在同一年得到所有的日子。然后我创建一个包含 26 个子数组的数组,每 2 周分组一次。然后我使用每个子数组的第一个和最后一个日期创建一个日期间隔数组。
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
func dayAfter(using calendar: Calendar = .current) -> Date {
calendar.date(byAdding: .day, value: 1, to: noon(using: calendar))!
}
func noon(using calendar: Calendar = .current) -> Date {
calendar.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
func startOfNextDay(using calendar: Calendar = .current) -> Date {
calendar.startOfDay(for: dayAfter(using: calendar))
}
func lastSecondOfDay(using calendar: Calendar = .current) -> Date {
calendar.date(byAdding: DateComponents(second: -1), to: calendar.startOfDay(for: dayAfter(using: calendar)))!
}
func weekOfYear(using calendar: Calendar = .current) -> Int { calendar.component(.weekOfYear, from: self) }
func year(using calendar: Calendar = .current) -> Int { calendar.component(.year, from: self) }
func month(using calendar: Calendar = .current) -> Int { calendar.component(.month, from: self) }
func allDaysInSameYear(using calendar: Calendar = .current) -> [Date] {
calendar.range(of: .day, in: .year, for: self)!.map {
DateComponents(calendar: calendar,year: year(using: calendar), day: $0).date!
}
}
func biweeksInSameYear(using calendar: Calendar = .current) -> [[Date]] {
allDaysInSameYear(using: calendar).reduce(into: .init(repeating: [], count: 26)) {
let weekOfYear = $1.weekOfYear(using: calendar)-1
let index = weekOfYear > 51 ? 25 : weekOfYear / 2
$0[index].append($1)
}
}
func biweekIntervalsInSameYear(using calendar: Calendar = .current) -> [DateInterval] {
biweeksInSameYear(using: calendar).map {
DateInterval(start: $0.first!, end: $0.last!.lastSecondOfDay(using: calendar))
}
}
}
let biweekIntervals = Date().biweekIntervalsInSameYear(using: .iso8601)
for interval in biweekIntervals {
print(interval.start.description(with: .current), interval.end.description(with: .current), terminator: "\n")
}
这将打印:
2020 年 1 月 1 日星期三 00:00:00 2020 年 1 月 12 日星期日 23:59:59
2020 年 1 月 13 日星期一 00:00:00 2020 年 1 月 26 日星期日 23:59:59
2020 年 1 月 27 日星期一 00:00:00 2020 年 2 月 9 日星期日 23:59:59
2020 年 2 月 10 日星期一 00:00:00 2020 年 2 月 23 日星期日 23:59:59
2020 年 2 月 24 日星期一 00:00:00 2020 年 3 月 8 日星期日 23:59:59
2020 年 3 月 9 日星期一 00:00:00 2020 年 3 月 22 日星期日 23:59:59
2020 年 3 月 23 日星期一 00:00:00 2020 年 4 月 5 日星期日 23:59:59
2020 年 4 月 6 日星期一 00:00:00 2020 年 4 月 19 日星期日 23:59:59
2020 年 4 月 20 日星期一 00:00:00 2020 年 5 月 3 日星期日 23:59:59
2020 年 5 月 4 日星期一 00:00:00 2020 年 5 月 17 日星期日 23:59:59
2020 年 5 月 18 日星期一 00:00:00 2020 年 5 月 31 日星期日 23:59:59
2020 年 6 月 1 日星期一 00:00:00 2020 年 6 月 14 日星期日 23:59:59
2020 年 6 月 15 日星期一 00:00:00 2020 年 6 月 28 日星期日 23:59:59
2020 年 6 月 29 日星期一 00:00:00 2020 年 7 月 12 日星期日 23:59:59
2020 年 7 月 13 日星期一 00:00:00 2020 年 7 月 26 日星期日 23:59:59
2020 年 7 月 27 日星期一 00:00:00 2020 年 8 月 9 日星期日 23:59:59
2020 年 8 月 10 日星期一 00:00:00 2020 年 8 月 23 日星期日 23:59:59
2020 年 8 月 24 日星期一 00:00:00 2020 年 9 月 6 日星期日 23:59:59
2020 年 9 月 7 日星期一 00:00:00 2020 年 9 月 20 日星期日 23:59:59
2020 年 9 月 21 日星期一 00:00:00 2020 年 10 月 4 日星期日 23:59:59
2020 年 10 月 5 日星期一 00:00:00 2020 年 10 月 18 日星期日 23:59:59
2020 年 10 月 19 日星期一 00:00:00 2020 年 11 月 1 日星期日 23:59:59
2020 年 11 月 2 日星期一 00:00:00 2020 年 11 月 15 日星期日 23:59:59
2020 年 11 月 16 日星期一 00:00:00 2020 年 11 月 29 日星期日 23:59:59
2020 年 11 月 30 日星期一 00:00:00 2020 年 12 月 13 日星期日 23:59:59
2020 年 12 月 14 日星期一 00:00:00 2020 年 12 月 31 日星期四 23:59:59
另一种方法,这个方法似乎更短,但我建议进一步测试:
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
func startOfYear(using calendar: Calendar = .current) -> Date {
calendar.dateComponents([.calendar,.year], from: self).date!
}
func endOfYear(using calendar: Calendar = .current) -> Date {
startOfYear(using: calendar).adding(.init(year: 1, second: -1))!
}
func adding(_ components: DateComponents, wrappingComponents: Bool = false, using calendar: Calendar = .current) -> Date? {
calendar.date(byAdding: components, to: self)
}
func yearForWeekOfYear(using calendar: Calendar = .current) -> Int {
calendar.component(.yearForWeekOfYear, from: self)
}
func biweekIntervalsInSameYear(using calendar: Calendar = .current) -> [DateInterval] {
let date = DateComponents(calendar: .iso8601, weekOfYear: 1, yearForWeekOfYear: yearForWeekOfYear(using: .iso8601)).date!
var intervals: [DateInterval] = [.init(start: startOfYear(using: .iso8601), end: date.adding( .init(second: -1, weekOfYear: 2), using: calendar)!)]
var weekOfYear = 3
while let start = Calendar.iso8601.nextDate(after: date, matching: DateComponents(weekOfYear: weekOfYear), matchingPolicy: .strict) {
if intervals.count < 25 {
intervals.append(.init(start: start, end: start.adding( .init(second: -1, weekOfYear: 2), using: calendar)!)) } else if intervals.count == 25 {
intervals.append(.init(start: start, end: start.endOfYear(using: .iso8601)))
}
weekOfYear += 2
}
return intervals
}
}