NSDate가 오늘인지 확인하는 방법?


156

확인하는 방법 NSDate오늘 소속 ?

에서의 처음 10자를 사용하여 확인했습니다 [aDate description]. [[aDate description] substringToIndex:10]문자열을 반환 "YYYY-MM-DD"하므로 문자열을에서 반환 한 문자열과 비교했습니다 [[[NSDate date] description] substringToIndex:10].

더 빠르고 깔끔한 확인 방법이 있습니까?

감사.


필자는 필자의 방법이 실제로 Apple의 문서를 참조하고 이틀 내에서 동일한 지 확인하기 위해 제안한 내용을 수행하는 유일한 방법이라고 생각합니다. 다른 방법이 효과가있을 수 있지만 내 방법이 가장 확실한 증거라고 생각합니다. stackoverflow.com/a/17641925/901641
ArtOfWarfare

@ArtOfWarfare : 동의하지 않습니다. 귀하의 코드는 여전히 시간 간격을 처리해야하지만 애플은 이미 멀리이 인수 분해 방법을 제공합니다 - 참조 : stackoverflow.com/a/17642033/106435
vikingosegundo

1
NSDate "설명"방법은 일광 절약 시간에 대한 수정없이 날짜를 UTC 형식 (그리니치 표준시)으로 표시합니다. 미국의 늦은 저녁이나 인도의 이른 아침 인 경우 달력에 따라 "오늘"이 표시되지 않습니다. NSDate를 하루로 변환하고 현재 날짜를 하루로 변환 한 다음 비교하려면 NSCalendar 객체가 필요합니다.
gnasher729

답변:


308

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)

1
iOS 8 SDK를 사용하여 확인
Catfish_Man

1
위의 의견에 혼란 스럽습니다. 이것은 iOS 8입니다.-(BOOL) isDateInToday : (NSDate *) date NS_AVAILABLE (10_9, 8_0);
powerj1984

그렇습니다, 내가 말한 것입니다. 아마도 이전 의견자는 iOS 7 SDK를보고 혼란 스러웠습니다. 다른 선언이있었습니다.
Catfish_Man

'오늘'에 대한 완벽한 답변입니다 :)
Daij-Djan

훌륭한 답변!
Supertecnoboff

192

날짜 구성 요소를 비교할 수 있습니다.

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
}

크리스, 난 당신의 제안을 통합했습니다. 나는 시대가 무엇인지 찾아야했기 때문에 모르는 사람은 BC와 AD를 구분합니다. 이것은 아마도 대부분의 사람들에게는 불필요하지만 확인하기 쉽고 확실성을 추가하기 때문에 포함 시켰습니다. 속도가 빠르면 어쨌든 이것은 좋은 방법이 아닙니다.


참고 SO에 많은 답변 등은 7 년 후이 완전히 최신이 아닙니다. 스위프트에서는 이제 사용하십시오..isDateInToday


1
감사. 내 질문에 더 깔끔하고 미래에 안전한 솔루션이라고 생각합니다.
Seunghoon

1
시대 구성 요소도 포함해야한다고 생각합니다. 두 가지 접근법 사이에 동전 던지기라고 생각합니다. isEqualToDate는 더 좋게 보이지만 약간 낭비적이고 구성 요소의 날짜를 재구성하는 데 거의 같은 수의 줄이 필요합니다.
Chris 페이지

1
"otherDay"와 "today"둘 다 어쨌든 네 개의 필드 만 채웠기 때문에 (요청한 전부 임), 두 번째 필드에서 후프를 점프하지 않고 [today equalTo : otherDay]를 사용할 수 있습니다.
Glenn Maynard

@Glenn 첫 번째 NSDateComponents를 비교할 것을 제안합니까? 나는 그것에 대해 실제로 생각하지 않았지만 좋은 생각처럼 보입니다.
David Kanarek

1
@DavidKanarek 오래된 게시물 파기 ... 날짜 구성 요소를 직접 비교하지 않는 것이 좋습니다. 구성 요소 중 하나를 상쇄 해야하는 상황에 처하면 월 == 3, 일 == 34와 같은 것을 얻을 수 있습니다. 날짜로 변환하면이를 4 월 3 일로 올바르게 해석하며 날짜 구성 요소를 비교하면 월 == 4, 일 == 3과 동일하게 표시되지 않습니다.
Sean Kladek

27

이것은 귀하의 질문에 대한 파생물이지만 "오늘"또는 "어제"로 NSDate를 인쇄하려면이 함수를 사용하십시오

- (void)setDoesRelativeDateFormatting:(BOOL)b

NSDateFormatter 용


3
영리한 아이디어. 그러나 현지화하면 "오늘"문자열을 찾는 것이 중단 될 것이라고 가정합니다.
Basil Bourque

16

오늘 날짜를 자정과 두 번째 날짜로 표준화하고 자정으로 표준화 한 다음 동일한 NSDate인지 비교하려고합니다.

에서 애플의 예를 여기에 두 번째 날짜와 비교를위한 방법을 정상화 자정 오늘 날짜에 수행 동일합니다 :

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

당신도 시대를 포함시켜야한다고 생각합니다.
Chris 페이지

자정이 아닌 정오를 12로 설정하여 날짜를 정규화해서는 안됩니까? 날짜가 GMT에 있기 때문에 날짜를 정오로 설정하면 시간대 변형이 두 가지 방식으로 (그리고 두 가지 방식으로 만 12 시간까지 이동) 전날과 그 다음날로 '점프'하지 않습니다.
artooras 2016

13

작업 스위프트 3, 4 연장 Catfish_Man에 의해 제안의 :

extension Date {

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

}

12

구성 요소, 시대 및 물건으로 저글링 할 필요가 없습니다.

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
}

9
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에서 나를 위해 일했습니다.


6

최상의 답변의 신속한 버전 :

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
}

5

"캘린더 계산 수행"이라는 제목의 Apple 설명서 항목을 참조하십시오. [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
시대는 00:00 GMT에서 시작한다는 것을 명심하십시오! 날짜 중 하나 (또는 ​​둘 다)가 GMT 시간대에없는 경우이 방법이 올바르게 작동하지 않을 수 있습니다.
Andreas Ley

5

보유한 날짜와 현재 날짜 사이의 시간 간격을 확인할 수도 있습니다.

[myDate timeIntervalSinceNow]

그러면 myDate와 현재 날짜 / 시간 사이의 시간 간격 (초)이 표시됩니다.

링크 .

편집 : 모두 참고 : [myDate timeIntervalSinceNow]는 myDate가 오늘인지 확실하게 결정하지 않는다는 것을 잘 알고 있습니다.

나는 누군가가 비슷한 것을 찾고 있고 [myDate timeIntervalSinceNow]가 유용하다면 여기에서 찾을 수 있도록이 대답을 그대로 둡니다.


1
당신이 말하는 것은 정확하지만 간격이 실제로 날짜가 오늘인지 확인하는 데 도움이되지 않습니다.
Jaanus

3
지금부터 24 시간 이내에 있는지 여부를 알려주지 만 날짜가 같은 경우는 아닙니다. 1 초 차이는 다른 날짜 일 수 있으며 86399 초 차이는 동일한 날짜 일 수 있습니다.
David Kanarek 님

@David : 맞습니다. 질문에 대답하면서 3 가지 다른 일을하고 있었기 때문에 그것에 대해 생각하지 않았으며 페이지를로드 할 때 귀하의 답변이 게시되지 않았습니다.
alesplin

1
이 질문에 전혀 대답하지 않습니다. 삭제해야합니다.
vikingosegundo

1
이 답변은 소음 일뿐입니다. 질문에 대답하려고 시도하지 않으며 timeIntervalSinceNow다른 많은 게시물에서 다루는 것처럼 언급 할 필요도 없습니다 . 또한 초 검사로 일 비교 처리는 86400에 의해 오류가 발생하기 쉬운 부문을 장려
vikingosegundo

4

최상의 답변을 기반으로 한 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)
    }
}

2

이 날짜 비교가 많으면 통화 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

고마워 허용되는 방식은 앱에 CPU를 너무 많이 사용했기 때문에이를 최적화해야했습니다.
Accatyyc

1
이 코드는 일광 절약 시간제에 실패합니다. 악명 높은 숫자 86,400의 코드를 사용하는 사람은 누구나 두통을 일으킬 수 있습니다.
vikingosegundo

2

위의 많은 답변보다 쉬운 방법이 있습니다!

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

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

1
Catfish_Man의 답변과 동일합니다!
Thanh Pham

0

이것은 아마도 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 );
}

(그러나 원래 질문에서와 같이 두 날짜 문자열을 비교하면 거의 '깨끗합니다'..)


comps즉시 0으로 설정할 때 만들 때 왜 시간, 분 및 초를 포함 합니까? 또한 시대를 포함시켜야한다고 생각합니다.
Chris 페이지

이것은 거의 모든 경우에 작동하지만 윤초와 같은 것들이 있습니다. Apple의 NSDate 클래스가 이들을 처리하는지 여부 또는 방법을 모르겠지만 이것이 작동하지 않을 가능성이 있습니다. 이것은 매우 드물기 때문에 (역사상 24 개) 당신의 방법에 대한 비판보다는“알고있는 것”입니다.
David Kanarek

일광 절약 시간 제로 인해 24 시간이 아니라 23 또는 25 일인 날짜는 어떻습니까?
vikingosegundo

0

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

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
}

-1

다음은 허용 된 답변을 기반으로하지만 최신 API를 지원하는 2 센트 답변입니다. 참고 : 대부분의 타임 스탬프는 GMT이므로 Gregorian 캘린더를 사용하지만 적절하다고 생각되면 변경하십시오.

func isDateToday(date: NSDate) -> Bool {
    let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    if calendar.respondsToSelector("isDateInToday:") {
        return calendar.isDateInToday(date)
    }
    let dateComponents = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay
    let today = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: NSDate()))!
    let dateToCompare = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: date))!

    return dateToCompare == today
}

-3

내 솔루션은 1970 년 이후로 며칠이 지 났는지 계산하여 정수 부분을 비교하는 것입니다.

#define kOneDay (60*60*24)
- (BOOL)isToday {
  NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT];

  NSInteger days =[self timeIntervalSince1970] + offset;
  NSInteger currentDays = [[NSDate date] timeIntervalSince1970] + offset;
  return (days / kOneDay == currentDays / kOneDay);
}

실제로 나쁜 해결책은 아닙니다. 왜 그렇게 하향 조정되었는지 확실하지 않습니다. 정수 나누기를 사용하면 GMT를 수정 한 후 나머지를 잘라 내고 유닉스 오랜 시간의 "일"값만 비교합니다. 나는 이것이 가장 솔직한 해결책이라고 생각합니다.
devios1

1
@chaiguy : 이것은 하루 24 시간의 길이라고 가정하는 나쁜 해결책입니다. 일광 절약 시간 제로 인해 기간은 23, 24 또는 25 시간입니다.
vikingosegundo

흠. 그러나 연간 평균은 정확히 24 시간이므로 내가 본 것처럼 최악의 경우에는 1 시간 정도만 중단 될 수 있습니다. 아마도 그것은 명시 적으로 점검 될 수 있습니다.
devios1

2
@chaiguy : 아뇨. 60 * 60 * 24가 포함 된 코드를 사용하지 마십시오. 또는 두통과 함께 산다.
vikingosegundo

"secondsFromGMT"는 전 세계 대부분의 지역에서 1 년에 두 번 갑자기 변경됩니다. NSCalendar 방법을 사용하는 것이 훨씬 안전합니다.
gnasher729

-4
NSDate *dateOne = yourDate;
NSDate *dateTwo = [NSDate date];  

switch ([dateOne compare:dateTwo])
{  
    case NSOrderedAscending:  
        NSLog(@”NSOrderedAscending”);  
        break;  

    case NSOrderedSame: 
        NSLog(@”NSOrderedSame”);  
        break;

    case NSOrderedDescending:  
        NSLog(@”NSOrderedDescending”);  
        break;  
}  

4
NSDate 두 날짜가 모두 같은 날짜인지, 날짜가 같은 날짜라도 더 빠른 날짜를 알려주지는 않습니다.
David Kanarek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.