Сравнить NSDate для Сегодня или Вчера

Ну, я думаю, это было задано тысячу раз, но почему-то ответы не работают или не имеют других проблем,...

В любом случае, вот что я "работаю":

    NSCalendar *calendar = [NSCalendar currentCalendar];    
    NSDate *currentDate = [NSDate date];
    NSDateComponents *comps = [[NSDateComponents alloc] init];
    // set tomorrow (0: today, -1: yesterday)
    [comps setDay:0];
    NSDate *dateToday = [calendar dateByAddingComponents:comps toDate:currentDate options:0];
    [comps setDay:-1];
    NSDate *dateYesterday = [calendar dateByAddingComponents:comps toDate:currentDate options:0];
    [comps release];


NSString *todayString = [self.dateFormatter stringFromDate:dateToday] ;
NSString *yesterdayString = [self.dateFormatter stringFromDate:dateYesterday] ;
NSString *refDateString = [self.dateFormatter stringFromDate:info.date];

if ([refDateString isEqualToString:todayString]) 
{
    cell.title.text =  @"Today";
} else if ([refDateString isEqualToString:yesterdayString]) 
{
    cell.title.text =  @"Yesterday";
} else 
{
    cell.title.text =  [self.dateFormatter stringFromDate:info.date];
}

Теперь к проблеме (задачам):

Это, кажется, очень много кода для сравнения только даты, есть ли более простой способ?

И самый важный вопрос - это выпуск всех объектов. Как я мог предположить, я использую это в UITableViewController. У меня также есть эти строки в моем коде:

//[calendar release];
//[currentDate release];
//[dateToday release];
//[dateYesterday release];
//[todayString release];
//[yesterdayString release];
//[refDateString release];

Проблема в том, что как только я раскомментирую одну из этих строк, мое приложение падает, и я понятия не имею, почему?! Надеюсь, кто-то может просветить меня здесь.

Спасибо большое.

Ответ 1

Самый простой способ сделать это - просто сравнить description дат:

// Your dates:
NSDate * today = [NSDate date];
NSDate * yesterday = [NSDate dateWithTimeIntervalSinceNow:-86400]; //86400 is the seconds in a day
NSDate * refDate; // your reference date

// 10 first characters of description is the calendar date:
NSString * todayString = [[today description] substringToIndex:10];
NSString * yesterdayString = [[yesterday description] substringToIndex:10];
NSString * refDateString = [[refDate description] substringToIndex:10];

if ([refDateString isEqualToString:todayString]) 
{
    cell.title.text =  @"Today";
} else if ([refDateString isEqualToString:yesterdayString]) 
{
    cell.title.text =  @"Yesterday";
} else 
{
    cell.title.text =  refDateString;
}

Если вы хотите изменить формат строки даты, вы можете использовать descriptionWithLocale: вместо этого.

Ответ 2

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

Прежде всего, поскольку iOS 4.0 (и Mac OS 10.6), NSDateFormatter может выполнять относительные даты, что дает вам "Сегодня" и "Вчера" автоматически.

NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setTimeStyle:NSDateFormatterNoStyle];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setDoesRelativeDateFormatting:YES];

NSString* dateString = [formatter stringFromDate:[NSDate date]];    
NSLog( @"date = %@", dateString );

Какие выходы:

2014-03-15 15:26:37.683 TestApp[1293:303] date = Today

Тем не менее, OP спрашивал, как сравнить NSDate сегодня или вчера, то, что я также хотел сделать, относительное форматирование даты в сторону. Вот что я придумал, реализованный как категория на NSDate:

@implementation NSDate (IsToday)

- (BOOL) isToday
{
    NSCalendar* calendar = [NSCalendar currentCalendar];

    // Components representing the day of our date.
    NSDateComponents* dateComp = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
                                             fromDate:self];
    NSDate* date = [calendar dateFromComponents:dateComp];

    // Components representing today.
    NSDateComponents* todayComp = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
                                              fromDate:[NSDate date]];
    NSDate* todayDate = [calendar dateFromComponents:todayComp];

    // If the dates are equal, then our date is today.
    return [date isEqualToDate:todayDate];
}

@end

Причина, по которой я хотел сделать это, - это показать время, созданное сегодня, и дату вещей, которые не созданы сегодня - подобно тому, как Mail.app показывает даты в сообщениях. Это выглядит так:

- (NSString*) postDateToString:(NSDate*)aDate
{
    static NSDateFormatter* todayFormatter = nil;
    if( todayFormatter == nil ) {
        todayFormatter = [[NSDateFormatter alloc] init];
        [todayFormatter setTimeStyle:NSDateFormatterShortStyle];
        [todayFormatter setDateStyle:NSDateFormatterNoStyle];
    }

    static NSDateFormatter* notTodayFormatter = nil;
    if( notTodayFormatter == nil ) {
        notTodayFormatter = [[NSDateFormatter alloc] init];
        [notTodayFormatter setTimeStyle:NSDateFormatterNoStyle];
        [notTodayFormatter setDateStyle:NSDateFormatterShortStyle];
        [notTodayFormatter setDoesRelativeDateFormatting:YES];
    }

    NSDateFormatter* formatter = notTodayFormatter;

    if( [aDate isToday] ) {
        formatter = todayFormatter;
    }

    return [formatter stringFromDate:aDate];
}

Ответ 3

Я могу предложить использовать этот проект с открытым исходным кодом: https://github.com/erica/NSDate-Extensions

Вы можете проверить текущие методы:

+ (NSDate *) dateTomorrow
+ (NSDate *) dateYesterday

Ответ 4

Вы можете сравнить два объекта NSDate с помощью метода isEqualToDate, вернет bool (да или нет), сообщив вам, совпадают ли даты. См. Документация Apple.

Что касается освобождения объектов - правило в objective-c заключается в том, что вы только освобождаете объекты, которые вы выделяете для памяти во время вашего метода. Единственный объект, который вы специально выделяете для памяти в своем коде, - это comps, поэтому он единственный, который вы должны выпустить - и вы это сделали. Освобождение памяти для объектов, которые вы никогда не выделяли, вероятно, приводит к сбою вашего приложения. Когда методы, которые фактически выделяют эти объекты, пытаются их освободить или другая ссылка на них пытается получить к ним доступ, они вызовут ошибку EXC_BAD_ACCESS, как вы уже их выпустили!

Поэтому не просто комментируйте эти строки выпуска, удаляйте их из своего script - им не нужно!