NSCalendar return wrong date for previous Monday i

2020-05-06 08:53发布

问题:

I am using below code to calculate previous Monday using random date. Which work file but my code break on next year date.below is the code for same :

NSDate *date = [NSDate dateWithTimeIntervalSince1970:1483620311.228];
NSLog(@"current date ===> : %@", date);

NSCalendar *calendar;
calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en-US"]];
NSTimeZone *zone = [NSTimeZone timeZoneWithName:@"Australia/Sydney"];
[calendar setTimeZone:zone];

NSDateComponents *nowComponents = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitWeekday | NSCalendarUnitWeekOfYear | NSCalendarUnitWeekOfMonth | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitTimeZone fromDate:date];
if (nowComponents.weekday == 1) {    //If my date fall in sunday then I am moving to previous week.
    [nowComponents setWeekOfYear:[nowComponents weekOfYear]-1];
}

[nowComponents setWeekday:2]; //Monday

NSDate *previousMonday = [calendar dateFromComponents:nowComponents];
NSLog(@"previousMonday date ===> : %@", previousMonday);

In Log I am getting as :

current date ===> : 2017-01-05 12:45:11 +0000
previousMonday date ===> : 2018-01-01 12:45:11 +0000

I have seen other stack overflow resource but not getting expected solution.

回答1:

There is a much smarter way to do that using nextDateAfterDate of NSCalendar. It can search backwards for the match of a single component in this case NSCalendarUnitWeekday == 2

NSDate *date = [NSDate dateWithTimeIntervalSince1970:1483620311.228]; 
NSLog(@"current date ===> : %@", date);
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *previousMonday = [calendar nextDateAfterDate:date 
                                        matchingUnit:NSCalendarUnitWeekday  
                                               value:2 
                                             options:NSCalendarMatchNextTime | NSCalendarSearchBackwards];
NSLog(@"previousMonday date ===> : %@", previousMonday);

The time zone and locale don't really matter.