158

如何检查一个是否NSDate属于今天?

我曾经使用[aDate description]. [[aDate description] substringToIndex:10]"YYYY-MM-DD"这样返回字符串,我将字符串与返回的字符串进行了比较[[[NSDate date] description] substringToIndex:10]

是否有更快速和/或更简洁的检查方式?

谢谢。

4

20 回答 20

315

在 macOS 10.9+ 和 iOS 8+ 中,NSCalendar/Calendar 上有一个方法可以做到这一点!

- (BOOL)isDateInToday:(NSDate *)date 

所以你只需做

目标-C:

BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];

斯威夫特 3:

let today = Calendar.current.isDateInToday(date)
于 2014-03-24T03:34:21.083 回答
192

您可以比较日期组件:

NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
   [today month] == [otherDay month] &&
   [today year] == [otherDay year] &&
   [today era] == [otherDay era]) {
    //do stuff
}

编辑:

我更喜欢 stefan 的方法,我认为它使 if 语句更清晰、更容易理解:

NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];

if([today isEqualToDate:otherDate]) {
    //do stuff
}

克里斯,我已经采纳了你的建议。我必须查一下是什么时代,所以对于其他不知道的人来说,它区分了公元前和公元。这对大多数人来说可能是不必要的,但它很容易检查并增加了一些确定性,所以我把它包括在内。如果你追求速度,这可能不是一个好方法。


请注意,与 SO 上的许多答案一样,7 年后这完全过时了。在 Swift 现在只需使用.isDateInToday

于 2010-02-25T02:23:39.120 回答
27

这是您问题的一个分支,但如果您想打印带有“今天”或“昨天”的 NSDate,请使用该功能

- (void)setDoesRelativeDateFormatting:(BOOL)b

对于 NSDateFormatter

于 2011-01-29T05:09:44.593 回答
16

我会尝试将今天的日期标准化为午夜和第二个日期,标准化为午夜,然后比较它是否是相同的 NSDate。

Apple 示例中,您可以将今天的日期标准化为午夜,对第二个日期执行相同操作并进行比较:

NSCalendar * gregorian = [[NSCalendar alloc]
                               initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
    [gregorian components:
                 (NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
                 fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
于 2010-02-25T02:40:07.723 回答
14

使用Catfish_Man建议的Swift 3 和 4 扩展

extension Date {

    func isToday() -> Bool {
        return Calendar.current.isDateInToday(self)
    }

}
于 2016-09-06T11:46:26.183 回答
12

无需处理组件、时代和其他东西。

NSCalendar 提供了一种方法来获取现有日期的某个时间单位的开始。

此代码将获取今天的开始日期和另一个日期并进行比较。如果计算结果为NSOrderedSame,则两个日期都在同一天 - 所以今天。

NSDate *today = nil;
NSDate *beginningOfOtherDate = nil;

NSDate *now = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&today interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfOtherDate interval:NULL forDate:beginningOfOtherDate];

if([today compare:beginningOfOtherDate] == NSOrderedSame) {
    //otherDate is a date in the current day
}
于 2013-07-14T17:53:31.003 回答
9
extension NSDate {
  func isToday() -> Bool {
    let cal = NSCalendar.currentCalendar()
    var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
    let today = cal.dateFromComponents(components)!

    components = cal.components([.Era, .Year, .Month, .Day], fromDate:self)
    let otherDate = cal.dateFromComponents(components)!

    return today.isEqualToDate(otherDate)
}

在 Swift 2.0 上为我工作

于 2015-11-03T11:50:56.670 回答
6

Swift 版本的最佳答案:

let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!

components = cal.components([.Era, .Year, .Month, .Day], fromDate:aDate);
let otherDate = cal.dateFromComponents(components)!

if(today.isEqualToDate(otherDate)) {
    //do stuff
}
于 2015-04-09T13:27:12.803 回答
5

您还可以检查您拥有的日期和当前日期之间的时间间隔:

[myDate timeIntervalSinceNow]

这将为您提供 myDate 和当前日期/时间之间的时间间隔(以秒为单位)。

链接

编辑:大家注意:我很清楚 [myDate timeIntervalSinceNow] 并没有明确地确定 myDate 是否是今天。

我将保留此答案,以便如果有人正在寻找类似的东西并且 [myDate timeIntervalSinceNow] 很有用,他们可能会在这里找到它。

于 2010-02-25T02:30:43.010 回答
5

请参阅 Apple 的文档条目,标题为“执行日历计算” [链接]

该页面上的清单 13 建议要确定几天之间的午夜数,您可以使用:

- (NSInteger)midnightsFromDate:(NSDate *)startDate toDate:(NSDate *)endDate
{
    NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
    NSInteger startDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
                                             inUnit:NSEraCalendarUnit
                                            forDate:startDate];
    NSInteger endDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
                                           inUnit:NSEraCalendarUnit
                                          forDate:endDate];
    return endDay - startDay;
}

然后,您可以通过使用该方法并查看它是否返回 0 来确定两天是否相同。

于 2013-07-14T17:41:39.883 回答
4

基于最佳答案的 Swift 扩展:

extension NSDate {
    func isToday() -> Bool {
        let cal = NSCalendar.currentCalendar()
        if cal.respondsToSelector("isDateInToday:") {
            return cal.isDateInToday(self)
        }
        var components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:NSDate())
        let today = cal.dateFromComponents(components)!

        components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:self);
        let otherDate = cal.dateFromComponents(components)!
        return today.isEqualToDate(otherDate)
    }
}
于 2015-08-05T10:58:48.983 回答
2

如果你有很多这些日期比较,那么calendar:components:fromDate开始调用会占用大量时间。根据我所做的一些分析,它们似乎相当昂贵。

假设您正在尝试从某个日期数组中确定哪些日期NSArray *datesToCompare与某个给定日期相同,例如NSDate *baseDate,那么您可以使用类似以下的内容(部分改编自上面的答案):

NSDate *baseDate = [NSDate date];

NSArray *datesToCompare = [NSArray arrayWithObjects:[NSDate date], 
                           [NSDate dateWithTimeIntervalSinceNow:100],
                           [NSDate dateWithTimeIntervalSinceNow:1000],
                           [NSDate dateWithTimeIntervalSinceNow:-10000],
                           [NSDate dateWithTimeIntervalSinceNow:100000],
                           [NSDate dateWithTimeIntervalSinceNow:1000000],
                           [NSDate dateWithTimeIntervalSinceNow:50],
                           nil];

// determine the NSDate for midnight of the base date:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) 
                                       fromDate:baseDate];
NSDate* theMidnightHour = [calendar dateFromComponents:comps];

// set up a localized date formatter so we can see the answers are right!
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];

// determine which dates in an array are on the same day as the base date:
for (NSDate *date in datesToCompare) {
    NSTimeInterval interval = [date timeIntervalSinceDate:theMidnightHour];
    if (interval >= 0 && interval < 60*60*24) {
        NSLog(@"%@ is on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
    }
    else {
        NSLog(@"%@ is NOT on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
    }
}

输出:

Nov 23, 2011 1:32:00 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:33:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:48:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 10:45:20 AM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 24, 2011 5:18:40 PM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Dec 5, 2011 3:18:40 AM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:32:50 PM is on the same day as Nov 23, 2011 1:32:00 PM
于 2011-11-23T21:37:36.497 回答
2

有比上述许多答案更简单的方法!

NSDate *date = ... // The date you wish to test
NSCalendar *calendar = [NSCalendar currentCalendar];

if([calendar isDateInToday:date]) {
    //do stuff
}
于 2016-08-14T23:50:12.407 回答
0

这可能会被重新设计为 NSDate 类别,但我使用了:

// Seconds per day (24h * 60m * 60s)
#define kSecondsPerDay 86400.0f

+ (BOOL) dateIsToday:(NSDate*)dateToCheck
{
    // Split today into components
    NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents* comps = [gregorian components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit) 
                                        fromDate:[NSDate date]];

    // Set to this morning 00:00:00
    [comps setHour:0];
    [comps setMinute:0];
    [comps setSecond:0];
    NSDate* theMidnightHour = [gregorian dateFromComponents:comps];
    [gregorian release];

    // Get time difference (in seconds) between date and then
    NSTimeInterval diff = [dateToCheck timeIntervalSinceDate:theMidnightHour];
    return ( diff>=0.0f && diff<kSecondsPerDay );
}

(但是,在原始问题中比较两个日期字符串几乎感觉“更干净”..)

于 2010-02-26T15:07:47.523 回答
0

对于 iOS7 及更早版本:

//this is now => need that for the current date
NSDate * now = [NSDate date];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];

NSDateComponents * components = [calendar components:( NSYearCalendarUnit|    NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: now];

[components setMinute:0];
[components setHour:0];
[components setSecond:0];

//this is Today's Midnight
NSDate *todaysMidnight = [calendar dateFromComponents: components];



//now timeIntervals since Midnight => in seconds
NSTimeInterval todayTimeInterval = [now timeIntervalSinceDate: todaysMidnight];

//now timeIntervals since OtherDate => in seconds
NSTimeInterval otherDateTimeInterval = [now timeIntervalSinceDate: otherDate];

if(otherDateTimeInterval > todayTimeInterval) //otherDate is not in today
{
    if((otherDateTimeInterval - todayTimeInterval) <= 86400) //86400 == a day total seconds
    {
        @"yesterday";
    }
    else
    {
        @"earlier";
    }
}
else
{
    @"today";
}


now = nil;
calendar = nil;
components = nil;
todaysMidnight = nil;

NSLog("Thank you :-)");
于 2014-09-18T10:57:13.153 回答
0

检查我们的 Erica Sadun 的伟大NSDate extension。使用非常简单。在这里罚款:

http://github.com/erica/NSDate-Extensions

它已经在这篇文章中了:https ://stackoverflow.com/a/4052798/362310

于 2015-04-09T11:50:03.230 回答
0

无需强制解包的正确且安全的解决方案,适用于 Swift 2.2 和 iOS 8 之前的版本:

func isToday() -> Bool {
    let calendar = NSCalendar.currentCalendar()
    if #available(iOS 8.0, *) {
        return calendar.isDateInToday(self)
    }

    let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
    let dayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:self)

    guard let today = calendar.dateFromComponents(todayComponents),
        day = calendar.dateFromComponents(dayComponents) else {
        return false
    }

    return today.compare(day) == .OrderedSame
}
于 2016-05-05T19:45:20.503 回答
-1

这是我基于已接受答案的 2 美分答案,但也支持较新的 API。注意:我使用公历,因为大多数时间戳都是 GMT,但您可以根据需要更改您的时间戳

func isDateToday(date: NSDate) -> Bool {
    let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    if calendar.respondsToSelector("isDateInToday:") {
        return calendar.isDateInToday(date)
    }
    let dateComponents = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay
    let today = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: NSDate()))!
    let dateToCompare = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: date))!

    return dateToCompare == today
}
于 2015-04-24T11:01:43.703 回答
-3

我的解决方案是通过除法计算自 1970 年以来经过了多少天并比较整数部分

#define kOneDay (60*60*24)
- (BOOL)isToday {
  NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT];

  NSInteger days =[self timeIntervalSince1970] + offset;
  NSInteger currentDays = [[NSDate date] timeIntervalSince1970] + offset;
  return (days / kOneDay == currentDays / kOneDay);
}
于 2013-01-28T06:40:59.143 回答
-4
NSDate *dateOne = yourDate;
NSDate *dateTwo = [NSDate date];  

switch ([dateOne compare:dateTwo])
{  
    case NSOrderedAscending:  
        NSLog(@”NSOrderedAscending”);  
        break;  

    case NSOrderedSame: 
        NSLog(@”NSOrderedSame”);  
        break;

    case NSOrderedDescending:  
        NSLog(@”NSOrderedDescending”);  
        break;  
}  
于 2010-12-07T08:03:53.877 回答