Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSDateComponents / NSDate : get the last sunday

I know there are some questions similar to this one, but I just can't find what's wrong with my code.

Basically what I want is if today is not sunday, currentDate is set to the last sunday. If today is sunday I currentDate is set to the sunday before.

Here's how I'm trying to do it.

  NSDateComponents *components = [[NSCalendar currentCalendar] components:  NSWeekCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit fromDate:currentDate];

    if (components.weekday == 1) { //Its sunday. We just need to subtract a week
        [components setWeek: -1];
        currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0];

    }else{ //If its not sunday we just go to sunday
        [components setWeekday: 1];
        currentDate = [[NSCalendar currentCalendar] dateFromComponents:components];

    }

The first time this part of the code is executed I get the right answer. After the first time I get weird dates, like 02 Dec. 4026, and the year keeps going up.

Here's the code that made it work:

   NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components: ( NSWeekCalendarUnit | NSWeekdayCalendarUnit | NSYearCalendarUnit) fromDate:currentDate];
    int weekday = components.weekday;

    if (weekday == 1) {
        [components setWeek:components.week -1];
    }else{
        [components setWeekday:1];
    }
    currentDate = [calendar dateFromComponents:components];
like image 330
Lorenzo Piccoli Módolo Avatar asked Oct 28 '25 14:10

Lorenzo Piccoli Módolo


2 Answers

Use nextDateAfterDate with the .SearchBackwards option if you are using iOS 8.0+

let calendar = NSCalendar.currentCalendar()
let options: NSCalendarOptions = [.MatchPreviousTimePreservingSmallerUnits, .SearchBackwards]
calendar.nextDateAfterDate(NSDate(), matchingUnit: .Weekday, value: 1, options: options)
like image 108
Jon Avatar answered Oct 30 '25 07:10

Jon


Try this category on NSCalendar

@interface NSCalendar (LastSunday)
-(NSDate *)previousSundayForDate:(NSDate *)date;
@end

@implementation NSCalendar (LastSunday)

-(NSDate *)previousSundayForDate:(NSDate *)date
{
    static NSUInteger SUNDAY = 1;
    static NSUInteger MONDAY = 2;

    NSDate *startOfWeek;
    [self rangeOfUnit:NSWeekCalendarUnit
            startDate:&startOfWeek
             interval:NULL
              forDate:date];

    if(self.firstWeekday == SUNDAY){

        NSDate *beginningOfDate;
        [self rangeOfUnit:NSDayCalendarUnit
                startDate:&beginningOfDate
                 interval:NULL forDate:date];
        if ([startOfWeek isEqualToDate:beginningOfDate]) {
            startOfWeek = [self dateByAddingComponents:(
                                                        {
                                                            NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                            comps.day = -7;
                                                            comps;
                                                        })
                                                toDate:startOfWeek
                                               options:0];
        }
        return startOfWeek;
    }
    if(self.firstWeekday == MONDAY)
        return [self dateByAddingComponents:(
                                             {
                                                 NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                 comps.day = -1;
                                                 comps;
                                             })
                                     toDate:startOfWeek
                                    options:0];

    return nil;

}

@end

use it as:

NSDate *lastSunday = [calendar previousSundayForDate:[NSDate date]];

PS:

a version for "one-method-one-return-statement"- fetishists:

@implementation NSCalendar (LastSunday)

-(NSDate *)previousSundayForDate:(NSDate *)date
{
    NSDate *resultDate = nil;
    static NSUInteger SUNDAY = 1;
    static NSUInteger MONDAY = 2;

    NSDate *startOfWeek;
    [self rangeOfUnit:NSWeekCalendarUnit
            startDate:&startOfWeek
             interval:NULL
              forDate:date];

    if(self.firstWeekday == SUNDAY){

        NSDate *beginningOfDate;
        [self rangeOfUnit:NSDayCalendarUnit
                startDate:&beginningOfDate
                 interval:NULL forDate:date];

        if ([startOfWeek isEqualToDate:beginningOfDate]) {
            startOfWeek = [self dateByAddingComponents:(
                                                        {
                                                            NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                            comps.day = -7;
                                                            comps;
                                                        })
                                                toDate:startOfWeek
                                               options:0];
        }
        resultDate = startOfWeek;
    }
    if(self.firstWeekday == MONDAY)
        resultDate = [self dateByAddingComponents:(
                                                   {
                                                       NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                       comps.day = -1;
                                                       comps;
                                                   })
                                           toDate:startOfWeek
                                          options:0];

    return resultDate;

}

@end
like image 42
vikingosegundo Avatar answered Oct 30 '25 06:10

vikingosegundo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!