Reputation: 16430
I want to obtain the first and the last day of a given week (number) for a given year. The function that I wrote works except for the last and the first week of the year.
For example, if I ask for the weekday
1 and 7 of the week
1 for the year
2014 I get the first week of the 2015!!!
2014-12-28 // weekday 1
2015-01-03 // weekday 7
But the right result should be!
2013-12-29 // weekday 1
2014-01-04 // weekday 7
If I ask for week 51 of 2013 I correctly receive:
2013-12-15 // weekday 1
2013-12-21 // weekday 7
Here my function, how can I fix this strange behaviour?!
// Return the date which is the weekday for a given week number and year
+ (NSDate*)weekDay:(NSInteger)weekday forWeekOfYear:(NSInteger)week year:(NSInteger)year{
// Date component
NSDateComponents *comp = [[NSDateComponents alloc]init];
[comp setWeekOfYear:week];
[comp setWeekday:weekday];
[comp setYear:year];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [calendar dateFromComponents:comp];
NSLog(@"week %d year %d weekday %d\n%@", week, year, weekday, date);
return date;
}
EDIT -------------
Following @Guillaume answer I've modified my code using setWeekOfYear
instead of setYear
. It partially worked, I correctly get the last day of the week, but as first weekday I get the first day of the next week. Now I get this error with any weeks number, not only the first or the last of the year.
Here the new result for week 1 of 2014:
2014-01-05 // weekday1... it should be 2013-12-29. damn!
2014-01-04 // weekday7... it should be 2014-01-04. great!
Just as information I call my Category function with this code:
self.fromDate = [NSDate weekDay:1 forWeekOfYear:self.selectedWeek year:self.selectedYear];
self.toDate = [NSDate weekDay:7 forWeekOfYear:self.selectedWeek year:self.selectedYear];
Upvotes: 0
Views: 291
Reputation: 52227
I get this result
2013-12-18 14:57:48.090 datecal[20740:303] week 1 year 2014 weekday 1 29/12/2013 00:00:00
2013-12-18 14:57:48.091 datecal[20740:303] week 1 year 2014 weekday 7 04/01/2014 00:00:00
for this code (Sunday first day of the week):
#import <Foundation/Foundation.h>
@interface NSDate (WeekBoundries)
+ (NSDate*)weekDay:(NSInteger)weekday forWeekOfYear:(NSInteger)week year:(NSInteger)year;
@end
@implementation NSDate (WeekBoundries)
static NSUInteger SUNDAY = 1;
static NSUInteger MONDAY = 2;
static NSUInteger SATURDAY = 7;
+ (NSDate*)weekDay:(NSInteger)weekday forWeekOfYear:(NSInteger)week year:(NSInteger)year{
// Date component
NSDateComponents *comp = [[NSDateComponents alloc]init];
[comp setWeekOfYear:week];
[comp setWeekday:weekday];
[comp setYearForWeekOfYear:year];
NSCalendar *calendar = [NSCalendar currentCalendar];
calendar.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
calendar.firstWeekday = SUNDAY;
NSDate *date = [calendar dateFromComponents:comp];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:[NSDateFormatter dateFormatFromTemplate:@"yyyy-MM-dd HH:mm:ss"
options:0
locale:[NSLocale currentLocale]]];
NSLog(@"week %ld year %ld weekday %ld %@", (long)week, (long)year, (long)weekday, [formatter stringFromDate:date]);
return date;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSDate *fromDate = [NSDate weekDay:SUNDAY forWeekOfYear:1 year:2014];
NSDate *toDate = [NSDate weekDay:SATURDAY forWeekOfYear:1 year:2014];
}
return 0;
}
if you want Monday be first day of the week, change:
calendar.firstWeekday = SUNDAY;
to
calendar.firstWeekday = MONDAY;
and
NSDate *fromDate = [NSDate weekDay:SUNDAY forWeekOfYear:1 year:2014];
NSDate *toDate = [NSDate weekDay:SATURDAY forWeekOfYear:1 year:2014];
to
NSDate *fromDate = [NSDate weekDay:MONDAY forWeekOfYear:1 year:2014];
NSDate *toDate = [NSDate weekDay:SUNDAY forWeekOfYear:1 year:2014];
if you mix it up like
calendar.firstWeekday = MONDAY;
NSDate *fromDate = [NSDate weekDay:SUNDAY forWeekOfYear:1 year:2014];
NSDate *toDate = [NSDate weekDay:SATURDAY forWeekOfYear:1 year:2014];
you'll get the behaviour you describe in your edit, there-for it is apparent, that your calendar has Monday as start of the week, will you fill in a sunday and a saturday.
If you want to respect the users locale, you can do this:
@interface NSDate (WeekBoundries)
+ (NSDate*)weekDay:(NSInteger)weekday forWeekOfYear:(NSInteger)week year:(NSInteger)year;
@end
@implementation NSDate (WeekBoundries)
+ (NSDate*)weekDay:(NSInteger)weekday forWeekOfYear:(NSInteger)week year:(NSInteger)year{
NSDateComponents *comp = [[NSDateComponents alloc]init];
[comp setWeekOfYear:week];
[comp setWeekday:weekday];
[comp setYearForWeekOfYear:year];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [calendar dateFromComponents:comp];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:[NSDateFormatter dateFormatFromTemplate:@"yyyy-MM-dd HH:mm:ss"
options:0
locale:[NSLocale currentLocale]]];
NSLog(@"week %ld year %ld weekday %ld %@", (long)week, (long)year, (long)weekday, [formatter stringFromDate:date]);
return date;
}
@end
-(void)method
{
static NSUInteger SUNDAY = 1;
static NSUInteger MONDAY = 2;
static NSUInteger SATURDAY = 7;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *fromDate = [NSDate weekDay:(calendar.firstWeekday == MONDAY)? MONDAY : SUNDAY forWeekOfYear:1 year:2014];
NSDate *toDate = [NSDate weekDay:(calendar.firstWeekday == MONDAY)? SUNDAY : SATURDAY forWeekOfYear:1 year:2014];
}
Upvotes: 1
Reputation: 142
Have you worked it out yet?
Try:
int week = 0;
int weekday = 0;
int year = 2014;
[comp setWeekOfYear:week];
[comp setWeekday:weekday];
[comp setYear:year];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [calendar dateFromComponents:comp];
NSLog(@"week %d year %d weekday %d\n%@", week, year, weekday, date);
Upvotes: -1
Reputation: 4361
Did you try setYearForWeekOfYear:
instead of setYear:
?
In NSCalendar
there is also a property minimumDaysInFirstWeek
that might be worth looking at...
Upvotes: 2
Reputation: 17186
You are creating the wrong object of calendar.
Create it by below way:
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
Upvotes: 0