objective-c 比较两个 NSDates 并忽略时间分量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1854890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing two NSDates and ignoring the time component
提问by Magic Bullet Dave
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.
比较两个 NSDates 的最有效/推荐的方法是什么?我希望能够查看两个日期是否在同一天,无论时间如何,并且已经开始编写一些使用 NSDate 类中的 timeIntervalSinceDate: 方法并获取此值的整数除以秒数的代码一天内。这似乎冗长乏味,我觉得我错过了一些明显的东西。
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:
其中 key 和 todaysDate 是 NSDate 对象,而 todaysDate 正在使用:
NSDate *todaysDate = [[NSDate alloc] init];
Regards
问候
Dave
戴夫
回答by Ed Marty
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 date1and date2to the beginning of their respective days. If they are equal, they are on the same day.
其中规定date1和date2各自的日子的开始。如果它们相等,则它们在同一天。
Or this option:
或者这个选项:
NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];
Which sets day1and day2to somewhat arbitrary values that can be compared. If they are equal, they are on the same day.
哪个集合day1和day2可以比较的有点任意的值。如果它们相等,则它们在同一天。
回答by Gregory Pakosz
You set the time in the date to 00:00:00 before doing the comparison:
在进行比较之前,您将日期中的时间设置为 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
Then you can compare the date values. See the overview in reference documentation.
回答by static0886
There's a new method that was introduced to NSCalendar with iOS 8 that makes this much easier.
iOS 8 中向 NSCalendar 引入了一种新方法,使这变得更加容易。
- (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.
您将粒度设置为重要的单位。这会忽略所有其他单位并限制与所选单位的比较。
回答by James
For iOS8 and later, checking if two dates occur on the same day is as simple as:
对于 iOS8 及更高版本,检查两个日期是否出现在同一天非常简单:
[[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2]
See documentation
查看文档
回答by Bms270
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
}
回答by Felixyz
I use this little util method:
我使用这个小util方法:
-(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.)
(您显然需要有一个calendar_包含NSCalendar.的 ivar 调用。)
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.)
([NSDate date]返回当前日期和时间。)
This is of course very similar to what Gregory suggests. The drawback of this approach is that it tends to create lots of temporary NSDateobjects. 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 NSDateComponentsobjects instead of NSDates.
这当然与格雷戈里的建议非常相似。这种方法的缺点是它往往会创建许多临时NSDate对象。如果您要处理大量日期,我建议您使用其他一些方法,例如直接比较组件,或使用NSDateComponents对象而不是NSDates.
回答by jcesarmobile
I used the Duncan C approach, I have fixed some mistakes he made
我使用了 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;
}
回答by Arjan
From iOS 8.0 onwards, you can use:
从 iOS 8.0 开始,您可以使用:
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.
如果结果是例如 NSOrderedDescending,则 otherDate 在 [NSDate date] 之前就天数而言。
I do not see this method in the NSCalendar documentation but it is in the iOS 7.1 to iOS 8.0 API Differences
我在 NSCalendar 文档中没有看到这种方法,但它在iOS 7.1 到 iOS 8.0 API 差异中
回答by Duncan C
The answer is simpler than everybody makes it out to be. NSCalendar has a method
答案比大家想象的要简单。NSCalendar 有一个方法
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.
如果上述方法返回零,则两个日期在同一天。
回答by Imanou Petit
With Swift 3, according to your needs, you can choose one of the two following patterns in order to solve your problem.
使用 Swift 3,您可以根据需要,选择以下两种模式之一来解决您的问题。
#1. Using compare(_:to:toGranularity:)method
#1. 使用compare(_:to:toGranularity:)方法
Calendarhas a method called compare(_:?to:?to?Granularity:?). compare(_:?to:?to?Granularity:?)has the following declaration:
Calendar有一个方法叫做compare(_:?to:?to?Granularity:?). compare(_:?to:?to?Granularity:?)有以下声明:
func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
Compares the given dates down to the given component, reporting them
ordered?Sameif they are the same in the given component and all larger components, otherwise eitherordered?Ascendingorordered?Descending.
将给定日期与给定组件进行比较,
ordered?Same如果它们在给定组件和所有更大的组件中相同,则报告它们,否则为ordered?Ascending或ordered?Descending。
The Playground code below shows hot to use it:
下面的 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. Using dateComponents(_:from:to:)
#2. 使用dateComponents(_:from:to:)
Calendarhas a method called dateComponents(_:from:to:). dateComponents(_:from:to:)has the following declaration:
Calendar有一个方法叫做dateComponents(_:from:to:). dateComponents(_:from:to:)有以下声明:
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:
下面的 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
}

