Intereting Posts
Хорошо ли утверждать, что объект содержит определенные методы, когда известно, что этот объект соответствует протоколу? Как оживить ползунок к маркеру в двухстороннем слайдере Панель навигации в ошибке UIPageViewController Отключение пользовательского модального контроллера Добавить основной заголовок HTTP-аутентификации в файл AFHttpRequestOperation & download Ошибка: UIAlertController при переходе на другое представление UIPanGestureRecognizer не работает с UIImageView Как использовать подписанную сборку (PCL) в проекте Xamarin iOS? Семантический выпуск: использование необъявленного идентификатора Вспышка MpMovieplayer во время напоминания о напоминании Один запрос для двух основных отношений данных? Ячейки не отображаются в виде таблицы Попытка вытащить метаданные GPS из UIImagePickerController, но NSLog показывает Null Как вы управляете тегами просмотра в своем проекте iOS? Сохраняйте текст согласованным, если внутри контроллера просмотра страницы

NSDateComponents / NSDate: получите последнее воскресенье

Я знаю, что есть некоторые вопросы, подобные этому, но я просто не могу найти, что не так с моим кодом.

В принципе, я хочу, если сегодня не в воскресенье, currentDate устанавливается на последнее воскресенье. Если сегодня воскресенье, то currentDate устанавливается на воскресенье раньше.

Вот как я пытаюсь это сделать.

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]; } 

В первый раз, когда эта часть кода выполнена, я получаю правильный ответ. После первого раза я получаю странные даты, например, 02 декабря 4026 года, и год продолжает расти.

Вот код, который заставил его работать:

  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]; 

Используйте nextDateAfterDate с опцией .SearchBackwards если вы используете iOS 8.0+

 let calendar = NSCalendar.currentCalendar() let options: NSCalendarOptions = [.MatchPreviousTimePreservingSmallerUnits, .SearchBackwards] calendar.nextDateAfterDate(NSDate(), matchingUnit: .Weekday, value: 1, options: options) 

Попробуйте эту категорию в 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 

используйте его как:

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

PS:

версия для «one-method-one-return-statement» – фетишисты:

 @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 

Причина, по которой вы получили 4026, связана с этой строкой:

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

Он устанавливает компонент года в текущем году, 2013 год. Он также инициализирует компоненты недели и недели. Затем компоненты добавляются к текущей дате, которая удваивает год до 4026, здесь:

 [components setWeek: -1]; currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0]; 

Если вы хотите вычесть только одну неделю, сделайте это так:

 NSDateComponents *components = [[NSDateComponents alloc] init]; [components setWeek: -1]; currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0]; [components release];