比较两个 NSDate 并忽略时间部分

发布于 2024-08-13 14:21:32 字数 470 浏览 2 评论 0原文

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

我试图修复的代码是:

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

其中 key 和 TodaysDate 是 NSDate 对象,并且 TodaysDate 正在使用以下命令创建:

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

问候

戴夫

What is the most efficient/recommended way of comparing two NSDates? I would like to be able to see if both dates are on the same day, irrespective of the time and have started writing some code that uses the timeIntervalSinceDate: method within the NSDate class and gets the integer of this value divided by the number of seconds in a day. This seems long winded and I feel like I am missing something obvious.

The code I am trying to fix is:

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

where key and todaysDate are NSDate objects and todaysDate is creating using:

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

Regards

Dave

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

紧拥背影 2024-08-20 14:21:33

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

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

You set the time in the date to 00:00:00 before doing the comparison:

unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar* calendar = [NSCalendar currentCalendar];

NSDateComponents* components = [calendar components:flags fromDate:date];

NSDate* dateOnly = [calendar dateFromComponents:components];

// ... necessary cleanup

Then you can compare the date values. See the overview in reference documentation.

眼眸里的那抹悲凉 2024-08-20 14:21:33

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

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

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

There's a new method that was introduced to NSCalendar with iOS 8 that makes this much easier.

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

You set the granularity to the unit(s) that matter. This disregards all other units and limits comparison to the ones selected.

夜深人未静 2024-08-20 14:21:33

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

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

请参阅 文档

For iOS8 and later, checking if two dates occur on the same day is as simple as:

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

See documentation

甜中书 2024-08-20 14:21:33

这是所有答案的简写:

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
    }

This is a shorthand of all the answers:

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
    }
浮萍、无处依 2024-08-20 14:21:33

我使用了 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;
}

I used the Duncan C approach, I have fixed some mistakes he made

-(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;
}
世界等同你 2024-08-20 14:21:33

我使用这个小 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。)

使用这个方法,可以很容易地检查日期是否像今天这样this:

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

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

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

I use this little util method:

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

(You obviously need to have an ivar called calendar_ containing an NSCalendar.)

Using this, it is easy to check if a date is today like this:

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

([NSDate date] returns the current date and time.)

This is of course very similar to what Gregory suggests. The drawback of this approach is that it tends to create lots of temporary NSDate objects. If you're going to process a lot of dates, I would recommend using some other method, such as comparing the components directly, or working with NSDateComponents objects instead of NSDates.

巨坚强 2024-08-20 14:21:33

答案比每个人想象的都要简单。 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;
}

如果上面的方法返回零,则两个日期是同一天。

The answer is simpler than everybody makes it out to be. NSCalendar has a method

components:fromDate:toDate:options

That method lets you calculate the difference between two dates using whatever units you want.

So write a method like this:

-(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;
}

If the above method returns zero, the two dates are on the same day.

﹎☆浅夏丿初晴 2024-08-20 14:21:33

从 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 差异

From iOS 8.0 onwards, you can use:

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

If the result is e.g. NSOrderedDescending, otherDate is before [NSDate date] in terms of days.

I do not see this method in the NSCalendar documentation but it is in the iOS 7.1 to iOS 8.0 API Differences

如梦 2024-08-20 14:21:33

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

if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
     // Do something
}

For developers coding in Swift 3

if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){
     // Do something
}
淡笑忘祈一世凡恋 2024-08-20 14:21:33

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


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

Calendar 有一个名为 比较(_:到:到粒度:)compare(_: to: to Granularity: ) 具有以下声明:

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

将给定日期向下与给定组件进行比较,如果给定组件和所有较大组件中的日期相同,则报告它们ordered Same,否则报告ordered Ascending降序排列

下面的 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
}

With Swift 3, according to your needs, you can choose one of the two following patterns in order to solve your problem.


#1. Using compare(_:to:toGranularity:) method

Calendar has a method called compare(_:​to:​to​Granularity:​). compare(_:​to:​to​Granularity:​) has the following declaration:

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

Compares the given dates down to the given component, reporting them ordered​Same if they are the same in the given component and all larger components, otherwise either ordered​Ascending or ordered​Descending.

The Playground code below shows hot to use it:

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. Using dateComponents(_:from:to:)

Calendar has a method called dateComponents(_:from:to:). dateComponents(_:from:to:) has the following declaration:

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

Returns the difference between two dates.

The Playground code below shows hot to use it:

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
}
仄言 2024-08-20 14:21:33
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}
唠甜嗑 2024-08-20 14:21:33

我的解决方案是使用 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  
    }

my solution was two conversions with 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  
    }
來不及說愛妳 2024-08-20 14:21:33

有关 NSDate< 的文档/a> 表示 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;
    }
}

The documentation regarding NSDate indicates that the compare: and isEqual: methods will both perform a basic comparison and order the results, albeit they still factor in time.

Probably the simplest way to manage the task would be to create a new isToday method to the effect of the following:

- (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;
    }
}
彼岸花似海 2024-08-20 14:21:33

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

bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];

This is a particularly ugly cat to skin, but here's another way to do it. I don't say it's elegant, but it's probably as close as you can get with the date/time support in iOS.

bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
等待我真够勒 2024-08-20 14:21:33
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 天的差异

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

compare hour as well to fix 1day difference

绝對不後悔。 2024-08-20 14:21:32

令我惊讶的是,没有其他答案有此选项来获取对象的“一天的开始”日期:

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

I'm surprised that no other answers have this option for getting the "beginning of day" date for the objects:

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

Which sets date1 and date2 to the beginning of their respective days. If they are equal, they are on the same day.

Or this option:

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

Which sets day1 and day2 to somewhat arbitrary values that can be compared. If they are equal, they are on the same day.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文