在 iOS swift 中获取当月所有周的第一天

Get the first day of all weeks of current month in iOS swift

我需要在图表的 x 轴上显示 当前 month/first 工作日 。谁能帮我解决这个问题? 如何获取当月所有周的第一天。

您可以使用以下组件创建 DateComponents

year: someYear,
month: someMonth,
weekday: someCalendar.firstWeekday,
weekOfMonth: n

使用Calendar.date(from:)得到那些组件对应的Date。现在您只需要将 n 从 1 变为 5,并将每个结果放入一个数组中。

var firstsOfWeek = [Date]()
let year = 2020
let month = 10
let calendar = Calendar.current

for n in 1...5 {
    let dc = DateComponents(
        year: year,
        month: month,
        weekday: calendar.firstWeekday,
        weekOfMonth: n
    )
    firstsOfWeek.append(calendar.date(from: dc)!)
}

但是,如果 someMonth 的第一周仅部分在 someMonth 内,date(from:) 将 return 不在 someMonth 内的日期。例如,(假设一周从星期日开始)2020 年 10 月的第一周从 9 月 27 日开始,如果你问 weekOfMonth: 1 对应的日期是什么,date(from:) 会给你那个日期。

如果你不想要那个日期。只需添加一个检查以仅包括月初(如果它也是一周的开始),并将 for 循环范围更改为 2...5:

let firstDayOfMonth = calendar.date(from: DateComponents(year: year, month: month))!
if calendar.component(.weekday, from: firstDayOfMonth) == calendar.firstWeekday {
    firstsOfWeek.append(firstDayOfMonth)
}
for n in 2...5 {
...

但请注意,如果这样做,生成的数组有时会有 4 个元素,有时会有 5 个元素。

您可以获得当前日期的 .yearForWeekOfYear,获取该日期月份的 weekOfYear 范围和 return 范围内同一个月的所有日期:

extension Date {
    func month(using calendar: Calendar = .current) -> Int {
        calendar.component(.month, from: self)
    }
    func firstWeekdaysInMonth(using calendar: Calendar = .current) -> [Date] {
        var components = calendar.dateComponents([.calendar, .yearForWeekOfYear], from: self)
        return calendar.range(of: .weekOfYear, in: .month, for: self)?.compactMap {
            components.weekOfYear = [=10=]
            return components.date?.month(using: calendar) == month(using: calendar) ? components.date : nil
        } ?? []
    }
}

另一种选择是获取该特定日期的月初,枚举该日期之后与日历的第一个工作日匹配的日期,如果结果日期与该日期不在同一个月份,则停止:

extension Date {
    func firstWeekdaysInMonth(using calendar: Calendar = .current) -> [Date] {
        let year = calendar.component(.year, from: self)
        let month = calendar.component(.month, from: self)
        let start = DateComponents(calendar: calendar, year: year, month: month).date!
        let matching = DateComponents(weekday: calendar.firstWeekday)
        var dates: [Date] = []
        calendar.enumerateDates(startingAfter: start, matching: matching, matchingPolicy: .strict) { date, _, stop in
            guard let date = date, calendar.component(.month, from: date) == month else {
                stop = true
                return
            }
            dates.append(date)
        }
        return dates
    }
}

let dates = Date().firstWeekdaysInMonth()  // "Oct 4, 2020 at 12:00 AM", "Oct 11, 2020 at 12:00 AM", "Oct 18, 2020 at 12:00 AM", "Oct 25, 2020 at 12:00 AM"]

let august = DateComponents(calendar: .current, year: 2020, month: 8, day: 10).date!
august.firstWeekdaysInMonth()  // ["Aug 2, 2020 at 12:00 AM", "Aug 9, 2020 at 12:00 AM", "Aug 16, 2020 at 12:00 AM", "Aug 23, 2020 at 12:00 AM", "Aug 30, 2020 at 12:00 AM"]