I am making a TimeTable app, and i have a method that adds 1 week to the current date, this works as it is supposed to, however if the week transitions from December to January,
That dateAtWeekStart()
method simply does not work.
[.YearForWeekOfYear, .WeekOfYear]
are sufficient as calendar units to
determine the (start of a) week uniquely. The additional units can make
the calculation undetermined. Also you can not just set
components.weekday = 1
because in some regions Monday (2) is the first
day of the week.
So it is actually a bit easier:
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)!
}
}
This should work in all cases and give the start of the week (at midnight) for the given date. There are also other methods
one could use, such as rangeOfUnit()
.
If you want Sunday to be considered as the first day of the week
instead of using the user's regional settings
then you have to set the firstWeekday
property of the calendar.
The code to add days or weeks to a date also looks highly suspicious.
The extensions method for Int
in the SwiftDate project treats
a day as 24*60*60 seconds. This is not correct, because in regions with
daylight saving times, a day can have 23 or 25 hours when the clocks
are adjusted. The correct way to add one week to a date is to
use calendar components again:
date = cal.dateByAddingUnit(.WeekOfYear, value: 1, toDate: date, options: [])!
Update for 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)!
}
}