首页 文章

比较两个NSDates并忽略时间组件

提问于
浏览
71

比较两个NSDates的最有效/推荐的方法是什么?我希望能够看到两个日期是否在同一天,无论时间如何,并且已经开始编写一些在NSDate类中使用timeIntervalSinceDate:方法的代码,并获取此值的整数除以秒数一天内 . 这似乎很长,我觉得我错过了一些明显的东西 .

我试图解决的代码是:

if (!([key compare:todaysDate] == NSOrderedDescending))
{
    todaysDateSection = [eventSectionsArray count] - 1;
}

其中key和todaysDate是NSDate对象,todaysDate使用以下方法创建:

NSDate *todaysDate = [[NSDate alloc] init];

问候

戴夫

16 回答

  • 6

    在进行比较之前,您将日期中的时间设置为00:00:00:

    unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
    NSCalendar* calendar = [NSCalendar currentCalendar];
    
    NSDateComponents* components = [calendar components:flags fromDate:date];
    
    NSDate* dateOnly = [calendar dateFromComponents:components];
    
    // ... necessary cleanup
    

    然后,您可以比较日期值 . 见overview in reference documentation .

  • 0

    我很惊讶没有其他答案有这个选项来获取对象的“开始日期”日期:

    [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1];
    [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];
    

    date1date2 设置为各自日期的开头 . 如果他们是平等的,他们就在同一天 .

    或者这个选项:

    NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
    NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];
    

    day1day2 设置为可以比较的某些任意值 . 如果他们是平等的,他们就在同一天 .

  • 14

    有一个新的方法被引入到NSCalendar与iOS 8,使这更容易 .

    - (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);
    

    您将粒度设置为重要的单位 . 这忽略了所有其他单位并限制与所选单位的比较 .

  • 10

    对于iOS8及更高版本,检查同一天是否出现两个日期非常简单:

    [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2]
    

    documentation

  • 3

    这是所有答案的简写:

    NSInteger interval = [[[NSCalendar currentCalendar] components: NSDayCalendarUnit
                                                                      fromDate: date1
                                                                        toDate: date2
                                                                       options: 0] day];
        if(interval<0){
           //date1<date2
        }else if (interval>0){
           //date2<date1
        }else{
           //date1=date2
        }
    
  • 0

    我使用了Duncan C方法,我修正了他犯的一些错误

    -(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate { 
    
        NSCalendar *currentCalendar = [NSCalendar currentCalendar];
        NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0];
    
        NSInteger days = [components day];
    
        return days;
    }
    
  • 1

    我用这个小的util方法:

    -(NSDate*)normalizedDateWithDate:(NSDate*)date
    {
       NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
                                                  fromDate: date];
       return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized
    }
    

    (你显然需要一个名为 calendar_ 的ivar,其中包含 NSCalendar . )

    使用这个,很容易检查今天的日期是这样的:

    [[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]];
    

    [NSDate date] 返回当前日期和时间 . )

    这当然与格雷戈里的建议非常相似 . 这种方法的缺点是它往往会创建大量临时的 NSDate 对象 . 如果你要处理很多日期,我建议使用其他方法,例如直接比较组件,或使用 NSDateComponents 对象而不是 NSDates .

  • 0

    答案比每个人都做到的更简单 . NSCalendar有一个方法

    components:fromDate:toDate:options
    

    该方法允许您使用您想要的任何单位计算两个日期之间的差异 .

    所以写一个像这样的方法:

    -(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate)
    {
      NSCalendar *currentCalendar = [NSCalendar currentCalendar];
      NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit
        fromDate: firstDate 
        toDate: secondDate
        options: 0];
    
      NSInteger days = [components days];
      return days;
    }
    

    如果上述方法返回零,则两个日期在同一天 .

  • 1

    从iOS 8.0开始,您可以使用:

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSComparisonResult dateComparison = [calendar compareDate:[NSDate date] toDate:otherNSDate toUnitGranularity:NSCalendarUnitDay];
    

    如果结果是例如NSOrderedDescending,otherDate在[NSDate date]之前以天为单位 .

    我在NSCalendar文档中没有看到这个方法,但它在iOS 7.1 to iOS 8.0 API Differences

  • 1

    对于在Swift 3中编码的开发人员

    if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
         // Do something
    }
    
  • 83
    int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
    if (interval!=0){
       //not the same day;
    }
    
  • 2

    我的解决方案是使用NSDateFormatter进行两次转换:

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
        [dateFormat setDateFormat:@"yyyyMMdd"];
        [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    
        NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0];
        NSString *todayString=[dateFormat stringFromDate:today];
        NSDate *todayWithoutHour=[dateFormat dateFromString:todayString];
    
        if ([today compare:exprDate] == NSOrderedDescending)
        {
           //do  
        }
    
  • 3

    使用Swift 3,根据您的需要,您可以选择以下两种模式之一来解决您的问题 .


    #1 . 使用compare(_:to:toGranularity :)方法

    Calendar 有一个名为compare(_:to:toGranularity:)的方法 . compare(_:to:toGranularity:) 有以下声明:

    func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
    

    将给定日期与给定组件进行比较,如果它们在给定组件和所有较大组件中相同,则报告orderedSame,否则为orderedAscending或orderedDescending .

    下面的Playground代码显示热使用它:

    import Foundation
    
    let calendar = Calendar.current
    let date1 = Date() // "Mar 31, 2017, 2:01 PM"
    let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
    let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"
    
    /* Compare date1 and date2 */
    do {
        let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day)
        switch comparisonResult {
        case ComparisonResult.orderedSame:
            print("Same day")
        default:
            print("Not the same day")
        }
        // Prints: "Not the same day"
    }
    
    /* Compare date1 and date3 */
    do {
        let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day)
        if case ComparisonResult.orderedSame = comparisonResult {
            print("Same day")
        } else {
            print("Not the same day")
        }
        // Prints: "Same day"
    }
    

    #2 . 使用dateComponents(_:from:to :)

    Calendar 有一个名为dateComponents(_:from:to:)的方法 . dateComponents(_:from:to:) 有以下声明:

    func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents
    

    返回两个日期之间的差异 .

    下面的Playground代码显示热使用它:

    import Foundation
    
    let calendar = Calendar.current
    let date1 = Date() // "Mar 31, 2017, 2:01 PM"
    let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM"
    let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM"
    
    /* Compare date1 and date2 */
    do {
        let dateComponents = calendar.dateComponents([.day], from: date1, to: date2)
        switch dateComponents.day {
        case let value? where value < 0:
            print("date2 is before date1")
        case let value? where value > 0:
            print("date2 is after date1")
        case let value? where value == 0:
            print("date2 equals date1")
        default:
            print("Could not compare dates")
        }
        // Prints: date2 is before date1
    }
    
    /* Compare date1 and date3 */
    do {
        let dateComponents = calendar.dateComponents([.day], from: date1, to: date3)
        switch dateComponents.day {
        case let value? where value < 0:
            print("date2 is before date1")
        case let value? where value > 0:
            print("date2 is after date1")
        case let value? where value == 0:
            print("date2 equals date1")
        default:
            print("Could not compare dates")
        }
        // Prints: date2 equals date1
    }
    
  • 72

    有关NSDate的文档表明 compare:isEqual: 方法都将执行基本比较并对结果进行排序,尽管它们仍然是时间因素 .

    管理任务的最简单方法可能是创建一个新的 isToday 方法,以实现以下效果:

    - (bool)isToday:(NSDate *)otherDate
    {
        currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code
    
        if (currentTime < [otherDate timeIntervalSinceNow])
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    
  • 19

    这对皮肤来说是一种特别难看的猫,但这是另一种方法 . 我不是说它很优雅,但它可能与iOS中的日期/时间支持一样接近 .

    bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
    
  • 6
    NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit;
    NSDateComponents *comp = [cal components:unit
                                    fromDate:nowDate
                                      toDate:setDate
                                     options:0];
    
    NSString *dMonth;
    dMonth = [NSString stringWithFormat:@"%02ld",comp.month];
    NSString *dDay;
    dDay = [NSString stringWithFormat:@"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)];
    

    比较小时以及修复1天的差异

相关问题