Сравните NSDate на сегодня или вчера - PullRequest
9 голосов
/ 24 мая 2010

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

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

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

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

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

Ответы [ 4 ]

12 голосов
/ 24 мая 2010

Самый простой способ сделать это - просто сравнить 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:.

6 голосов
/ 16 марта 2014

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

Прежде всего, поскольку 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

Однако ОП спрашивал, как сравнить 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];
}
2 голосов
/ 16 марта 2014

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

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

+ (NSDate *) dateTomorrow
+ (NSDate *) dateYesterday
0 голосов
/ 24 мая 2010

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

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

Так что не просто закомментируйте эти строки релиза, удалите их из скрипта - в них нет необходимости!

...