web-dev-qa-db-ja.com

NSDateが今日かどうかを判断する方法は?

NSDateが今日のものであるかどうかを確認する方法は?

[aDate description]の最初の10文字を使用して確認していました。 [[aDate description] substringToIndex:10]"YYYY-MM-DD"のような文字列を返すので、文字列を[[[NSDate date] description] substringToIndex:10]によって返される文字列と比較しました。

チェックするためのより高速かつ/またはきちんとした方法はありますか?

ありがとう。

149
Seunghoon

MacOS 10.9+およびiOS 8+では、NSCalendar/Calendarにまさにこれを行うメソッドがあります!

- (BOOL)isDateInToday:(NSDate *)date 

だからあなたは単純に

目的C:

BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];

スウィフト3:

let today = Calendar.current.isDateInToday(date)
299
Catfish_Man

日付コンポーネントを比較できます。

NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
   [today month] == [otherDay month] &&
   [today year] == [otherDay year] &&
   [today era] == [otherDay era]) {
    //do stuff
}

編集:

私はステファンの方法がより好きです、私はそれがより明確で理解しやすいif文を作ると思います:

NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];

if([today isEqualToDate:otherDate]) {
    //do stuff
}

クリス、私はあなたの提案を取り入れました。私は時代が何かを調べなければならなかったので、知らない他の人にとっては、紀元前と紀元を区別します。これはおそらくほとんどの人にとっては不必要ですが、確認するのは簡単で、確実性が追加されるので、私はそれを含めました。スピードを求めるなら、おそらくこれは良い方法ではないでしょう。


NOTE SOに関する多くの回答と同様に、7年後にこれは完全に古くなっています。 Swiftで.isDateInTodayを使用するようになりました

192
David Kanarek

これは質問の派生物ですが、「今日」または「昨日」のNSDateを印刷する場合は、関数を使用します

- (void)setDoesRelativeDateFormatting:(BOOL)b

nSDateFormatterの

27
Jon

今日の日付を真夜中と2番目の日付に正規化し、真夜中に正規化してから、同じNSDateかどうかを比較しようとします。

Appleの例 から今日の真夜中に正規化し、2番目の日付についても同じように比較します:

NSCalendar * gregorian = [[NSCalendar alloc]
                               initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
    [gregorian components:
                 (NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
                 fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
16
stefanB

作業中Swift 3&4 extension Catfish_Manによる提案:

extension Date {

    func isToday() -> Bool {
        return Calendar.current.isDateInToday(self)
    }

}
13
Benno Kress

コンポーネント、時代などを扱う必要はありません。

NSCalendarは、既存の日付の特定の時間単位の開始を取得するメソッドを提供します。

このコードは、今日の開始日と別の日付を取得して比較します。 NSOrderedSameと評価される場合、両方の日付は同じ日になります。つまり、今日です。

NSDate *today = nil;
NSDate *beginningOfOtherDate = nil;

NSDate *now = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&today interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfOtherDate interval:NULL forDate:beginningOfOtherDate];

if([today compare:beginningOfOtherDate] == NSOrderedSame) {
    //otherDate is a date in the current day
}
12
vikingosegundo
extension NSDate {
  func isToday() -> Bool {
    let cal = NSCalendar.currentCalendar()
    var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
    let today = cal.dateFromComponents(components)!

    components = cal.components([.Era, .Year, .Month, .Day], fromDate:self)
    let otherDate = cal.dateFromComponents(components)!

    return today.isEqualToDate(otherDate)
}

Swift 2.0で私のために働いた

8
Omar Albeik

ベストアンサーの迅速なバージョン:

let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!

components = cal.components([.Era, .Year, .Month, .Day], fromDate:aDate);
let otherDate = cal.dateFromComponents(components)!

if(today.isEqualToDate(otherDate)) {
    //do stuff
}
6
Vojtech Vrbka

また、現在の日付と現在の日付の間の時間間隔を確認することもできます。

[myDate timeIntervalSinceNow]

これにより、myDateと現在の日付/時刻の間の時間間隔が秒単位で表示されます。

リンク

編集:皆への注意:[myDate timeIntervalSinceNow]はmyDateが今日かどうかを明確に決定しないことをよく知っています。

誰かが似たようなものを探していて、[myDate timeIntervalSinceNow]が便利な場合、ここでそれを見つけることができるように、この答えをそのまま残しています。

5
alesplin

Appleの「Performing Calendar Calculations」というタイトルのドキュメントエントリを参照してください [link]

そのページのリスト13は、日間の真夜中の数を決定するために使用することを示唆しています。

- (NSInteger)midnightsFromDate:(NSDate *)startDate toDate:(NSDate *)endDate
{
    NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
    NSInteger startDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
                                             inUnit:NSEraCalendarUnit
                                            forDate:startDate];
    NSInteger endDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
                                           inUnit:NSEraCalendarUnit
                                          forDate:endDate];
    return endDay - startDay;
}

その後、そのメソッドを使用して、0が返されるかどうかを確認することにより、2日間が同じかどうかを判断できます。

5
ArtOfWarfare

ベストアンサーに基づくSwift Extension:

extension NSDate {
    func isToday() -> Bool {
        let cal = NSCalendar.currentCalendar()
        if cal.respondsToSelector("isDateInToday:") {
            return cal.isDateInToday(self)
        }
        var components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:NSDate())
        let today = cal.dateFromComponents(components)!

        components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:self);
        let otherDate = cal.dateFromComponents(components)!
        return today.isEqualToDate(otherDate)
    }
}
4
ZiggyST

上記の回答の多くよりも簡単な方法があります!

NSDate *date = ... // The date you wish to test
NSCalendar *calendar = [NSCalendar currentCalendar];

if([calendar isDateInToday:date]) {
    //do stuff
}
2
aryland

これらの日付の比較が多数ある場合、calendar:components:fromDateの呼び出しに多くの時間がかかります。私が行ったいくつかのプロファイリングによると、それらはかなり高価なようです。

NSArray *datesToCompareなどの日付の配列から特定の日と同じ日、たとえば[NSDate *baseDate]と同じ日を決定しようとしている場合、次のようなものを使用できます(回答から部分的に適応)上記):

NSDate *baseDate = [NSDate date];

NSArray *datesToCompare = [NSArray arrayWithObjects:[NSDate date], 
                           [NSDate dateWithTimeIntervalSinceNow:100],
                           [NSDate dateWithTimeIntervalSinceNow:1000],
                           [NSDate dateWithTimeIntervalSinceNow:-10000],
                           [NSDate dateWithTimeIntervalSinceNow:100000],
                           [NSDate dateWithTimeIntervalSinceNow:1000000],
                           [NSDate dateWithTimeIntervalSinceNow:50],
                           nil];

// determine the NSDate for midnight of the base date:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) 
                                       fromDate:baseDate];
NSDate* theMidnightHour = [calendar dateFromComponents:comps];

// set up a localized date formatter so we can see the answers are right!
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];

// determine which dates in an array are on the same day as the base date:
for (NSDate *date in datesToCompare) {
    NSTimeInterval interval = [date timeIntervalSinceDate:theMidnightHour];
    if (interval >= 0 && interval < 60*60*24) {
        NSLog(@"%@ is on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
    }
    else {
        NSLog(@"%@ is NOT on the same day as %@", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
    }
}

出力:

Nov 23, 2011 1:32:00 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:33:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:48:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 10:45:20 AM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 24, 2011 5:18:40 PM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Dec 5, 2011 3:18:40 AM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:32:50 PM is on the same day as Nov 23, 2011 1:32:00 PM
2

iOS7以前の場合:

//this is now => need that for the current date
NSDate * now = [NSDate date];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];

NSDateComponents * components = [calendar components:( NSYearCalendarUnit|    NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: now];

[components setMinute:0];
[components setHour:0];
[components setSecond:0];

//this is Today's Midnight
NSDate *todaysMidnight = [calendar dateFromComponents: components];



//now timeIntervals since Midnight => in seconds
NSTimeInterval todayTimeInterval = [now timeIntervalSinceDate: todaysMidnight];

//now timeIntervals since OtherDate => in seconds
NSTimeInterval otherDateTimeInterval = [now timeIntervalSinceDate: otherDate];

if(otherDateTimeInterval > todayTimeInterval) //otherDate is not in today
{
    if((otherDateTimeInterval - todayTimeInterval) <= 86400) //86400 == a day total seconds
    {
        @"yesterday";
    }
    else
    {
        @"earlier";
    }
}
else
{
    @"today";
}


now = nil;
calendar = nil;
components = nil;
todaysMidnight = nil;

NSLog("Thank you :-)");
0
user3744424

これはおそらくNSDateカテゴリとして作り直すことができますが、私は使用しました:

// Seconds per day (24h * 60m * 60s)
#define kSecondsPerDay 86400.0f

+ (BOOL) dateIsToday:(NSDate*)dateToCheck
{
    // Split today into components
    NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents* comps = [gregorian components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit) 
                                        fromDate:[NSDate date]];

    // Set to this morning 00:00:00
    [comps setHour:0];
    [comps setMinute:0];
    [comps setSecond:0];
    NSDate* theMidnightHour = [gregorian dateFromComponents:comps];
    [gregorian release];

    // Get time difference (in seconds) between date and then
    NSTimeInterval diff = [dateToCheck timeIntervalSinceDate:theMidnightHour];
    return ( diff>=0.0f && diff<kSecondsPerDay );
}

(ただし、元の質問のように2つの日付文字列を比較すると、「よりクリーン」に感じられます。)

0
LeoN

Erica SadunのすばらしいNSDate extensionをチェックしてください。非常に使いやすい。ここでそれを罰金:

http://github.com/erica/NSDate-Extensions

この投稿には既にあります: https://stackoverflow.com/a/4052798/36231

0
Vaibhav Saran

強制的にアンラップせずにSwift 2.2およびiOS 8より前で動作する正しい安全なソリューション:

func isToday() -> Bool {
    let calendar = NSCalendar.currentCalendar()
    if #available(iOS 8.0, *) {
        return calendar.isDateInToday(self)
    }

    let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
    let dayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:self)

    guard let today = calendar.dateFromComponents(todayComponents),
        day = calendar.dateFromComponents(dayComponents) else {
        return false
    }

    return today.compare(day) == .OrderedSame
}
0
fpg1503