2013-12-13 2 views
3

Я знаю, что есть некоторые вопросы, подобные этому, но я просто не могу найти, что не так с моим кодом.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]; 
+3

Почему вы установили неделю как '-1'? Если вы хотите получить на прошлой неделе, просто 'components.week - = 1;' –

+0

Я использую dateByAddingComponents и устанавливаю день -1, чтобы получить последний день, я думал, что установить неделю -1, когда добавлено получить las неделю. –

ответ

3

Использование nextDateAfterDate с .SearchBackwards вариант, если вы используете IOS 8.0+

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

Комментирование кода с быстрыми решениями бесполезно. –

+0

@MatthewBahr Я не уверен в этом. Swift - предпочтительный язык для разработки iOS. Этот вопрос задавали в декабре 2013 года, прежде чем Свифт был освобожден. Если бы вопрос был задан сейчас, была бы высокая вероятность того, что он будет помечен как Свифт. Разработчики iOS должны иметь возможность быстрого преобразования между синтаксисом Obj-C & Swift. – Jon

+1

Просто потому, что это «предпочтительный» язык не означает, что он полезен. У меня есть 2 библиотеки, которые являются obj-c только по причинам обслуживания, и получение быстрых ответов по объектам не помогает. –

1

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

версия для «один-метод-один-возвратное заявление» - фетишисты:

@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 
+0

Хорошо работает, но как получилось, когда я использую этот код, возвращаемая дата установлена ​​в 5 утра? – kraftydevil

+0

Это обсуждалось тысячи раз. Но в основном экземпляры nsdates отображают время печати gmt при печати. – vikingosegundo

0

Причина вы получили 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];