【问题标题】:Compare NSDate for Today or Yesterday比较今天或昨天的 NSDate
【发布时间】:2026-01-05 16:55:01
【问题描述】:

好吧,我想这已经被问了一千次了,但由于某种原因,答案并没有真正起作用或有其他问题,....

无论如何,这就是我的“工作”:

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

问题是,一旦我取消注释其中一行,我的应用程序就会崩溃,我不知道为什么?!我希望有人能在这里启发我。

非常感谢。

【问题讨论】:

  • 好吧,最后一点很简单:您不拥有这些对象中的任何一个,因此它们不属于您的释放。 comps 是您分配的唯一对象。其他的要么全部返回自动释放,要么根本不打算释放。

标签: iphone uitableview nsdate


【解决方案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:

【讨论】:

  • 不要依赖描述方法的结果。它的存在主要是为了调试目的,不能保证是持久的或可逆的。如果您想使用这种字符串比较方法,请使用显式 NSDateFormatter 来生成您想要的确切字符串。但是,当您可以比较 NSCalendar 生成的组件时,这有点矫枉过正。
  • 我得到的描述方法结果(在 iOS 7.1 中)提供了 GMT 日期,这意味着它将被当前用户的时区与 GMT 的偏移量关闭。对我来说,这意味着今天提前 6 小时开始。
【解决方案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
    

    【讨论】:

    • 这是一个很棒的扩展 - 感谢 Kriv。 CocoaPod 也支持:pod 'NSDate-Extensions', '~> 0.0.1'
    【解决方案4】:

    您可以使用 isEqualToDate 方法比较两个 NSDate 对象,将返回一个布尔值(是或否)告诉您日期是否相等。见Apple Documentation

    至于释放对象——objective-c 中的规则是你只释放你在方法过程中分配内存的对象。您在代码中专门为其分配内存的唯一对象是 comps,因此它是您应该释放的唯一对象——而且您已经这样做了。为您从未分配的对象释放内存可能是导致您的应用程序崩溃的原因。当实际分配这些对象的方法试图释放它们或其他对它们的引用试图访问它们时,它们将触发 EXC_BAD_ACCESS 错误,因为您已经释放了它们!

    所以不要只是注释掉那些发布行,从你的脚本中删除它们 - 不需要它们!

    【讨论】:

    • isEqualToDate: 在这里不起作用。如果日期“完全”相同,它只返回YES:“此方法检测日期之间的亚秒级差异。” (来自类参考。)