6

i need to calculate the weekday for a given date, however, depending on the calendar a week can star on Monday and somwhere on Sunday

so i wanted to set it, to start on Monday, using

[[NSCalendar currentCalendar] setFirstWeekday:2];

however, the calculation outcome is the same

{
    [[NSCalendar currentCalendar] setFirstWeekday:1];
    NSDateComponents *weekdayComponents = [[NSCalendar currentCalendar] components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
    NSInteger weekday = [weekdayComponents weekday] - 1;
    NSLog(@"%d", weekday);
}
{
    [[NSCalendar currentCalendar] setFirstWeekday:2];
    NSDateComponents *weekdayComponents = [[NSCalendar currentCalendar] components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
    NSInteger weekday = [weekdayComponents weekday] - 1;
    NSLog(@"%d", weekday);
}

returns same numbers, but why?

Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179

3 Answers3

11

The behavior you see is correct. The weekday component is not affected by the firstWeekday property. If you have a date representing a sunday it will always be a sunday wether you start your week on that sunday or on monday. What this should affect is the week number in the week property of your date components.

Sven
  • 22,475
  • 4
  • 52
  • 71
5

I believe you need to use the ordinalityOfUnit:inUnit:forDate: method rather than attempting to extract the date components. So something like this:

NSUInteger weekday = [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:date];

Basically that call is asking for the day (NSWeekdayCalendarUnit) in the week (NSWeekCalendarUnit) for the given date.

If that doesn't work as is, you may need to create your own calendar, rather than trying to modifying the first week day on the currentCalendar.

For example:

NSCalendarIdentifier calendarIdentifier = [[NSCalendar currentCalendar] calendarIdentifier];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier] autorelease];
[calendar setFirstWeekday:2];

Then use that new calendar object rather than [NSCalendar currentCalendar] in the ordinalityOfUnit:inUnit:forDate: call.

Dmitry
  • 14,306
  • 23
  • 105
  • 189
James Holderness
  • 22,721
  • 2
  • 40
  • 52
  • NSWeekCalendarUnit is deprecated :/ – Peter Lapisu Jun 01 '13 at 19:46
  • Perhaps try one of the other week units: `NSWeekOfMonthCalendarUnit` or `NSWeekOfYearCalendarUnit`. They don't really make sense in this context, but it's worth trying. – James Holderness Jun 01 '13 at 20:04
  • If you're finding you're getting strange values when simply plugging in `NSWeekOfMonthCalendarUnit` or `NSWeekOfYearCalendarUnit`, try... `NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitWeekday fromDate:[NSDate date]];` – roycable Apr 04 '18 at 04:01
0

A useful function to get corrected weekday number for different firstWeekday cases

Swift 3.0

func dayOfWeek(day: Int, month: Int, year: Int) -> Int {
    let calendar = Calendar.current
    let dateComponents = DateComponents(year: year, month: month, day: day)

    guard let date = calendar.date(from: dateComponents) else {
        fatalError("Can't create date form specified date components")
    }

    var weekday = calendar.component(.weekday, from: date)

    //handling the case when calendar starts from Monday: firstWeekday == 2
    if calendar.firstWeekday == 2 {
        weekday = (weekday == 1) ? 7 : (weekday - 1)
    }

    return weekday
}
ViktoR
  • 691
  • 9
  • 11