web-dev-qa-db-ja.com

2つのNSDateを比較し、時間コンポーネントを無視する

2つのNSDateを比較する最も効率的/推奨される方法は何ですか?時間に関係なく両方の日付が同じ日になっているかどうかを確認したいと思います。NSDateクラス内でtimeIntervalSinceDate:メソッドを使用して、この値を秒数で割った整数を取得するコードの記述を開始しました一日に。これは長く巻き込まれているように見え、明らかな何かを見逃しているように感じます。

私が修正しようとしているコードは次のとおりです。

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

keyとtodaysDateはNSDateオブジェクトであり、todaysDateは以下を使用して作成しています:

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

よろしく

デイブ

71

比較を行う前に、日付の時刻を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

その後、日付値を比較できます。 リファレンスドキュメントの概要 を参照してください。

72
Gregory Pakosz

オブジェクトの「1日の始まり」の日付を取得するためのオプションが他にないことには驚かされます。

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

date1およびdate2それぞれの日の初めまで。それらが等しい場合、それらは同じ日にあります。

または、このオプション:

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

day1およびday2比較可能なやや任意の値。それらが等しい場合、それらは同じ日にあります。

83
Ed Marty

IOS 8でNSCalendarに導入された新しいメソッドがあり、これが非常に簡単になります。

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

粒度を重要な単位に設定します。これにより、他のすべてのユニットが無視され、選択したユニットとの比較が制限されます。

19
static0886

IOS8以降では、同じ日に2つの日付が発生するかどうかを確認するのは簡単です。

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

ドキュメント を参照してください

14
James

これはすべての答えの速記です:

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
    }
10
Bms270

私はダンカン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;
}
6
jcesarmobile

私はこの小さなユーティリティメソッドを使用します:

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

(明らかに、NSCalendarを含むcalendar_というivarが必要です。)

これを使用すると、次のように日付が今日かどうかを簡単に確認できます。

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

[NSDate date]は現在の日付と時刻を返します。)

これはもちろん、グレゴリーが示唆するものと非常に似ています。このアプローチの欠点は、多くの一時的なNSDateオブジェクトを作成する傾向があることです。多くの日付を処理する場合は、コンポーネントを直接比較するか、NSDateComponentsの代わりにNSDatesオブジェクトを操作するなど、他の方法を使用することをお勧めします。

6
Felixyz

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の違い

3
Arjan

答えは誰よりも簡単です。 NSCalendarにはメソッドがあります

components:fromDate:toDate:options

この方法では、希望する単位を使用して2つの日付の差を計算できます。

そのため、次のようなメソッドを作成します。

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

上記のメソッドがゼロを返す場合、2つの日付は同じ日になります。

3
Duncan C

Swift 3を使用すると、ニーズに応じて、問題を解決するために次の2つのパターンのいずれかを選択できます。


#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​Ascending_または_ordered​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
_

2つの日付の差を返します。

以下の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
}
_
2
Imanou Petit

Swift 3でコーディングする開発者向け

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

私の解決策は、NSDateFormatterを使用した2つの変換でした。

    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  
    }
1
Zaster
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}
1
ChihHao
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日の差を修正します

0
Minho Lee

これは皮膚にとって特にい猫ですが、これを行う別の方法があります。私はそれがエレガントだとは言いませんが、おそらくiOSの日付/時刻のサポートで得られるものに近いでしょう。

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

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;
    }
}
0
Kaji