Swift - NSDate 和一年的最后一周

Jon*_*han 1 nsdate ios swift

我正在制作一个 TimeTable 应用程序,我有一种方法可以将当前日期增加 1 周,这可以正常工作,但是如果一周从 12 月过渡到 1 月,则会额外增加 1 天。

这是我的代码:

func getWeekDates(var date: NSDate) -> [NSDate] {
    var dates: [NSDate] = [NSDate]()
    for var i = 0; i < 5; i++ {
        date = date.dateAtWeekStart() + 1.day - 1.week
        date += i.day
        dates.append(date)
    }
    return dates
}
Run Code Online (Sandbox Code Playgroud)

并且dateAtWeekStart()

func dateAtWeekStart() -> NSDate {
    let flags : NSCalendarUnit = [NSCalendarUnit.Year,NSCalendarUnit.Month ,
        NSCalendarUnit.WeekOfYear,
        NSCalendarUnit.Weekday]
    let components = NSCalendar.currentCalendar().components(flags, fromDate: self)
    components.weekday = 1 // Sunday
    components.hour = self.hour
    components.minute = self.minute
    components.second = self.second
    return NSCalendar.currentCalendar().dateFromComponents(components)!
}
Run Code Online (Sandbox Code Playgroud)

(dateAtWeekStart()是在 NSDate 的扩展中制作的函数)

我添加 1 天并删除 1 周的原因是因为 dateAtWeekStart 下周日返回,例如 08-10-2015。dateAtWeekStart()返回 11-10-2015。

所以这正常工作正常,但是如果我们以今年为例,29-12-2015。dateAtWeekStart()返回 04-01-2015 而不是 03-01-2016。

顺便说一下,设备上的地区设置为丹麦。

dateAtWeekStart,来自malcommac制作的一个名为SwiftDate的辅助类:https : //github.com/malcommac/SwiftDate

更新编辑: 我仍然无法弄清楚如何解决这个问题,我尝试将年份添加到这样的组件中:components.year = self.year但由于某种原因,它在返回组件时将年份设置为 2014 年。

Mar*_*n R 5

这种dateAtWeekStart()方法根本行不通。 [.YearForWeekOfYear, .WeekOfYear]足以作为日历单位来唯一地确定(开始)周。附加单位可能会使计算不确定。您也不能仅仅设置, components.weekday = 1因为在某些地区,星期一 (2) 是一周的第一天。

所以它实际上更容易一些:

extension NSDate {
    func dateAtWeekStart() -> NSDate {
        let cal = NSCalendar.currentCalendar()
        // cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
        let flags : NSCalendarUnit = [.YearForWeekOfYear, .WeekOfYear]
        let components = cal.components(flags, fromDate: self)
        return cal.dateFromComponents(components)!
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该适用于所有情况,并为给定日期提供一周的开始(午夜)。还有其他方法可以使用,例如rangeOfUnit().

如果您希望将星期日视为一周的第一天而不是使用用户的区域设置,那么您必须设置firstWeekday日历的属性。

向日期添加天数或周数的代码看起来也非常可疑。IntSwiftDate 项目中的 extensions 方法将一天视为 24*60*60 秒。这是不正确的,因为在实行夏令时的地区,调整时钟后一天可能有 23 或 25 小时。将一周添加到日期的正确方法是再次使用日历组件:

date = cal.dateByAddingUnit(.WeekOfYear, value: 1, toDate: date, options: [])!
Run Code Online (Sandbox Code Playgroud)

Swift 3 更新:

extension Date {
    func dateAtWeekStart() -> Date {
        var cal = Calendar.current
        // cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
        let components = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
        return cal.date(from: components)!
    }
}
Run Code Online (Sandbox Code Playgroud)