Daniel Daniel - 5 months ago 18
iOS Question

Ordinal weekday index from NSDateComponents

I have created a category for

NSDate
which can create a string representation of a date with the weekday name, such as Thursday 5 January.

I want to get the weekday index and use a custom made array of weekdays which are stored in a plist and localised to english and spanish.

However using
NSDateComponents
is giving me some unexpected results. I'm requesting both
NSWeekdayOrdinalCalendarUnit
and
NSWeekdayCalendarUnit
and I am outputting the results to the log and I am getting the following example:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSWeekdayOrdinalCalendarUnit | NSWeekdayCalendarUnit fromDate:self];
NSInteger weekdayOrdinal = [components weekdayOrdinal];
NSInteger weekdayNonOrdinal = [components weekday];
NSLog(@"Date: %@", [self description]);
NSLog(@"Device oridinal weekday: %d", weekdayOrdinal);
NSLog(@"Device non-oridinal weekday: %d", weekdayNonOrdinal);



2012-01-06 15:05:56.492 MyApp[964:11903] Date: 2012-01-05 16:13:46 +0000

2012-01-06 15:05:56.492 MyApp[964:11903] Device oridinal weekday: 1

2012-01-06 15:05:56.493 MyApp[964:11903] Device non-oridinal weekday: 5


This day should be Thursday, ordinal should be 4 and non ordinal 5

I don't understand where the 1 comes from.

I found a way to adjust this to make sure we are using the gregorian calendar with
NSDateFormatter
and specifying an
NSCalendar
(with the first date of the week to be Monday) like the following:

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[gregorian setFirstWeekday:2];
NSUInteger adjustedWeekdayOrdinal = [gregorian ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:self];

NSDateFormatter *weekdayF = [[[NSDateFormatter alloc] init] autorelease];
[weekdayF setDateFormat: @"EEEE"];
[weekdayF setCalendar:gregorian];
[weekdayF setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_UK"]];
NSLog(@"The day of the week is: %@", [weekdayF stringFromDate:self]);


This will give me what I want but now I have to store the locale identifier in the plist to use in spanish, what I would prefer to keep is the first instance with
NSDateComponents
but I don't understand why I am getting a funny value sometimes.

I did find a solution to adjust the index with this solution: http://stackoverflow.com/a/3524462/662605

However, to be honest, I wouldn't like to use that along with
NSDateComponents
, I would rather use the
NSDateFormatter
, but overall it would be cool to fix the first example which gives me a false
weekdayOrdinal
value.

Any ideas on this ?

Answer

I think you're misinterpreting what weekdayOrdinal means. According to the doc for NSDateComponents, getting the weekdayOrdinal returns the ordinal number of weekday units for the receiver, where weekday ordinal units are the "position of the weekday within the next larger calendar unit, such as the month. For example, 2 is the weekday ordinal unit for the second Friday of the month".

By this reasoning, 2012-01-05 correctly has a weekdayOrdinal of 1 b/c it's the first Thursday of the month.