Swift - NSDate 和一年中的最后一周

Swift - NSDate and last week of year

我正在制作一个 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
}

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)!
}

dateAtWeekStart() 是 NSDate 扩展中的函数)

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

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

顺便说一句,设备上的区域设置为丹麦。

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

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

那个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)!
    }
}

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

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

向日期添加天数或周数的代码看起来也非常可疑。 SwiftDate 项目中 Int 的扩展方法处理 一天为 24*60*60 秒。这是不正确的,因为在具有 夏令时,一天可以有 23 或 25 小时,当时钟 被调整。将日期加一周的正确方法是 再次使用日历组件:

date = cal.dateByAddingUnit(.WeekOfYear, value: 1, toDate: date, options: [])!

Swift3 的更新:

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)!
    }
}