如何从NSDate中找到本周的开头?

Ane*_*eel 13 calendar date swift

我正在实现日历视图,我希望它在包含特定日期的一周开始时开始.例如.如果目标日期是2016年2月29日星期一,并且当前日历设置为星期日开始,我希望我的观点从2月28日星期日开始.

这似乎应该是直截了当的:

let calendar = NSCalendar.currentCalendar()
let firstDate = calendar.nextDateAfterDate(targetDate, 
                    matchingUnit: .Weekday,
                           value: calendar.firstWeekday,
                         options: .SearchBackwards)
Run Code Online (Sandbox Code Playgroud)

但这失败了:

由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因是:'必须指定集合中的一个选项{NSCalendarMatchPreviousTimePreservingSmallerUnits,NSCalendarMatchNextTimePreservingSmallerUnits,NSCalendarMatchNextTime}.

我基本上可以得到我想要的东西:

let firstDate = calendar.nextDateAfterDate(firstDate, 
                    matchingUnit: .Weekday,
                           value: calendar.firstWeekday,
                        options: .MatchPreviousTimePreservingSmallerUnits)?
                    .dateByAddingTimeInterval(-7 * 84600)
Run Code Online (Sandbox Code Playgroud)

但这似乎是一种不好的做法,因为有时候一天中的秒数不是86400.

有没有更好的办法?

Leo*_*bus 43

您可以使用NSCalendar方法dateFromComponents传递.YearForWeekOfYear,.WeekOfYear组件,从任何日期开始,它将从使用的日历返回一周的第一天.因此,如果您想在周日使用格里高利历.如果你想把星期一作为一周的第一天,你可以使用NSCalendar iso8601,你可以在这个答案中看到

Xcode 8.3.2•Swift 3.1或更高版本

extension Calendar {
    static let gregorian = Calendar(identifier: .gregorian)
}
extension Date {
    var startOfWeek: Date? {
        return Calendar.gregorian.date(from: Calendar.gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

Date().startOfWeek   // "Oct 15, 2017 at 1:00 AM" (note that daylight savings took effect last Sunday, thats why it shows 1am)
Run Code Online (Sandbox Code Playgroud)

  • 而不是公历,最好使用 NSCalendar.autoupdatingCurrent (4认同)
  • 谢谢!这是一种优雅的方式. (3认同)

Ras*_*iya 6

斯威夫特 4 解决方案

我已经根据我的要求找出了以下日期。

1. Today

2. Tomorrow 

3. This Week 

4. This Weekend 

5. Next Week 

6. Next Weekend
Run Code Online (Sandbox Code Playgroud)

因此,我创建了Date Extension获取当前周下周的日期。

代码

extension Date {

    func getWeekDates() -> (thisWeek:[Date],nextWeek:[Date]) {
        var tuple: (thisWeek:[Date],nextWeek:[Date])
        var arrThisWeek: [Date] = []
        for i in 0..<7 {
            arrThisWeek.append(Calendar.current.date(byAdding: .day, value: i, to: startOfWeek)!)
        }
        var arrNextWeek: [Date] = []
        for i in 1...7 {
            arrNextWeek.append(Calendar.current.date(byAdding: .day, value: i, to: arrThisWeek.last!)!)
        }
        tuple = (thisWeek: arrThisWeek,nextWeek: arrNextWeek)
        return tuple
    }

    var tomorrow: Date {
        return Calendar.current.date(byAdding: .day, value: 1, to: noon)!
    }
    var noon: Date {
        return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
    }

    var startOfWeek: Date {
        let gregorian = Calendar(identifier: .gregorian)
        let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
        return gregorian.date(byAdding: .day, value: 1, to: sunday!)!
    }

    func toDate(format: String) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = format
        return formatter.string(from: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let arrWeekDates = Date().getWeekDates() // Get dates of Current and Next week.
let dateFormat = "MMM dd" // Date format
let thisMon = arrWeekDates.thisWeek.first!.toDate(format: dateFormat)
let thisSat = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 2].toDate(format: dateFormat)
let thisSun = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 1].toDate(format: dateFormat)

let nextMon = arrWeekDates.nextWeek.first!.toDate(format: dateFormat)
let nextSat = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 2].toDate(format: dateFormat)
let nextSun = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 1].toDate(format: dateFormat)

print("Today: \(Date().toDate(format: dateFormat))") // Sep 26
print("Tomorrow: \(Date().tomorrow.toDate(format: dateFormat))") // Sep 27
print("This Week: \(thisMon) - \(thisSun)") // Sep 24 - Sep 30
print("This Weekend: \(thisSat) - \(thisSun)") // Sep 29 - Sep 30
print("Next Week: \(nextMon) - \(nextSun)") // Oct 01 - Oct 07
print("Next Weekend: \(nextSat) - \(nextSun)") // Oct 06 - Oct 07
Run Code Online (Sandbox Code Playgroud)

您可以Extension根据您的需要进行修改。

谢谢!

  • 不要忘记您可以使用以下命令设置要考虑的第一天: var gregorian = Calendar(identifier: .gregorian) gregorian.firstWeekday = 2 // Monday (2认同)

kpo*_*ekk 5

您可以将其实现为 Date 类扩展或其他东西。它应该返回类似2020-01-06 00:00:00 +0000

Xcode 11.3 斯威夫特 5

func firstDayOfWeek() -> Date {
    var c = Calendar(identifier: .iso8601)
    c.timeZone = TimeZone(secondsFromGMT: 0)!
    print(
        c.date(from: c.dateComponents([.weekOfYear, .yearForWeekOfYear], from: Date()))!
    )
} 
Run Code Online (Sandbox Code Playgroud)