72

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

我要修复的代码是:

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

其中 key 和 todaysDate 是 NSDate 对象,而 todaysDate 正在使用:

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

问候

戴夫

4

16 回答 16

83

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

[[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可以比较的任意值。如果它们相等,则它们在同一天。

于 2009-12-07T02:07:11.673 回答
73

在进行比较之前,您将日期中的时间设置为 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

然后您可以比较日期值。请参阅参考文档中的概述

于 2009-12-06T09:52:29.110 回答
20

在 iOS 8 中,NSCalendar 引入了一种新方法,使这变得更容易。

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

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

于 2015-02-14T18:32:38.730 回答
16

对于 iOS8 及更高版本,检查两个日期是否在同一天很简单:

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

查看文档

于 2015-11-30T01:17:04.997 回答
10

这是所有答案的简写:

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
    }
于 2012-10-12T20:21:53.307 回答
6

我使用这个小工具方法:

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

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

使用它,很容易检查日期是否像这样:

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

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

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

于 2009-12-06T17:25:59.317 回答
6

我使用了 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;
}
于 2012-04-23T13:47:57.357 回答
3

答案比大家想象的要简单。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;
}

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

于 2011-11-26T20:43:14.393 回答
3

从 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 到 iOS 8.0 API 差异中

于 2015-03-31T15:32:22.330 回答
3

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


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

Calendar有一个方法叫做compare(_:​to:​to​Granularity:​). compare(_:​to:​to​Granularity:​)有以下声明:

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

将给定日期与给定组件进行比较,ordered​Same如果它们在给定组件和所有较大组件中相同,则报告它们,否则为ordered​Ascendingordered​Descending

下面的 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
}
于 2017-03-31T12:23:08.417 回答
2

对于使用 Swift 3 编码的开发人员

if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
     // Do something
}
于 2017-03-31T03:26:04.957 回答
1
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}
于 2014-09-18T09:46:04.877 回答
1

我的解决方案是使用 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  
    }
于 2016-02-10T16:18:28.863 回答
0

有关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;
    }
}
于 2009-12-06T09:58:16.587 回答
0

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

bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
于 2013-06-30T01:09:41.933 回答
0
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 天的差异

于 2015-02-27T06:06:31.627 回答