Z S
Z S

Reputation: 7479

NSDateComponents: difference between weekOfYear and weekOfMonth

In my app, I have to set up a weekly reminder so that an alert goes off at the same day/time, a week from now. I have been using NSDateComponenents.week = 1 and adding that to an NSDate, using NSCalendar's dateByAddingComponents:toDate:options: API. It seems that week is now being deprecated in iOS7, and the warning tells me to "Use weekOfMonth or weekOfYear, depending on which you mean". But I can't find much documentation about what either of them means.

Can anyone explain the difference between the two? In a basic test, the two return the same value when added to an NSDate, but I'm sure there is some meaningful difference between the two.

Upvotes: 9

Views: 7379

Answers (4)

Kacper Cz
Kacper Cz

Reputation: 586

I'm using DateComponents to display a recurring event (eg. every 30 days, every 3 weeks, every 2 months). I wrote an extension:

extension DateComponents {
var frequencyString: String? {
    let formatter = DateComponentsFormatter()
    if let value = self.day, value != 0 {
        formatter.allowedUnits = [.day]
    } else if let value = self.weekOfYear, value != 0 {
        formatter.allowedUnits = [.weekOfYear]
    } else if let value = self.month, value != 0 {
        formatter.allowedUnits = [.month]
    } else {
        formatter.allowedUnits = [.day, .weekOfMonth, .month]
    }
    formatter.unitsStyle = .full
    formatter.maximumUnitCount = 1
    return formatter.string(from: self)
}
}

Then in Playground I did this:

var dateComponents = DateComponents()
dateComponents.weekOfYear = 100
dateComponents.calendar = .current

Surprisingly, for .weekOfYear the frequencyString returned nil. When I changed all .weekOfYear to .weekOfMonth in the extension, it returned correct value of weeks (when getting weekOfMonth).

Upvotes: 0

Peter Johnson
Peter Johnson

Reputation: 3786

The difference is useful if you want to set an event to always happen on "the second Tuesday of the month", for example.

In that case you would want weekOfMonth to be 2.

Upvotes: 2

Collin
Collin

Reputation: 6760

The difference between the two show show the week relative to the month or year.

The second week (weekOfMonth) of February would be the seventh week (weekOfYear) of the year, for example, depending on the year.

As to using date components for adding weeks to a date, it doesn't appear to matter which is used but weekOfYear seems to be preferred on the Internet.

I did some testing in a Swift playground and they always calculated the same value when adding weeks to a date.

weekOfMonth vs weekOfYear

Upvotes: 10

Fogmeister
Fogmeister

Reputation: 77631

I've always found that weeks seem to be handled strangely in iOS.

weekOfMonth will be 1, 2, 3, 4 etc...

weekOfYear will be 1 to 52 (I think)

They don't seem to be measurements of duration. Just like 'The 3rd of April' is not a measurement of duration whereas "1 day" is a measurement of duration.

The best way to add one weeks would be...

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *currentDate = [NSDate date];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:7];
NSDate *date = [calendar dateByAddingComponents:comps toDate:currentDate  options:0];

EDIT

After a little test I was right.

NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:NSCalendarUnitWeekOfMonth | NSCalendarUnitWeekOfYear fromDate:date];

Printing description of date:
2014-08-20 08:15:13 +0000

Printing description of comps:
<NSDateComponents: 0xb7753c0>
    Week of Year: 34
    Week of Month: 4

Upvotes: 5

Related Questions