programing tip

두 개의 NSDates 비교 및 ​​시간 구성 요소 무시

itbloger 2020. 10. 28. 07:50
반응형

두 개의 NSDates 비교 및 ​​시간 구성 요소 무시


두 NSDate를 비교하는 가장 효율적이고 권장되는 방법은 무엇입니까? 시간에 관계없이 두 날짜가 같은 날인지 확인하고 NSDate 클래스 내에서 timeIntervalSinceDate : 메서드를 사용하고이 값의 정수를 초 수로 나눈 값을 가져 오는 코드를 작성하기 시작했습니다. 하루에. 이것은 바람이 길고 분명한 것을 놓치고있는 것 같습니다.

내가 수정하려는 코드는 다음과 같습니다.

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

여기서 key와 todaysDate는 NSDate 객체이고 todaysDate는 다음을 사용하여 생성합니다.

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

문안 인사

데이브


비교를 수행하기 전에 날짜의 시간을 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

그런 다음 날짜 값을 비교할 수 있습니다. 참조 문서개요를 참조 하십시오 .


다른 답변에는 객체의 "시작일"날짜를 가져 오는이 옵션이 없다는 것에 놀랐습니다.

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

어떤 세트 day1day2비교 될 수있는 다소 임의의 값이다. 같으면 같은 날입니다.


iOS 8과 함께 NSCalendar에 도입 된 새로운 방법이있어이를 훨씬 쉽게 만들어줍니다.

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

중요한 단위에 세분성을 설정합니다. 이것은 다른 모든 단위를 무시하고 선택한 단위와 비교를 제한합니다.


iOS8 및 이후 버전의 경우 두 날짜가 같은 날에 발생하는지 확인하는 것은 다음과 같이 간단합니다.

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

문서 보기


이것은 모든 답변의 속기입니다.

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
    }

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

이 작은 유틸리티 방법을 사용합니다.

-(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.)

이것을 사용하면 날짜가 다음과 같은 오늘인지 쉽게 확인할 수 있습니다.

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

( [NSDate date]현재 날짜와 시간을 반환합니다.)

이것은 물론 Gregory가 제안한 것과 매우 유사합니다. 이 접근 방식의 단점은 많은 임시 NSDate개체 를 만드는 경향이 있다는 것 입니다. 많은 날짜를 처리하려는 경우 구성 요소를 직접 비교하거나 NSDateComponents대신 개체로 작업하는 것과 같은 다른 방법을 사용하는 것이 좋습니다 NSDates.


답은 모두가 생각하는 것보다 간단합니다. 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;
}

위의 메서드가 0을 반환하면 두 날짜는 같은 날입니다.


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 차이에 있습니다.


Swift 3로 코딩하는 개발자 용

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

Swift 3를 사용하면 필요에 따라 문제를 해결하기 위해 다음 두 가지 패턴 중 하나를 선택할 수 있습니다.


#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.

아래의 플레이 그라운드 코드는 그것을 사용하기에 뜨거운 것을 보여줍니다.

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

두 날짜의 차이를 반환합니다.

아래의 플레이 그라운드 코드는 그것을 사용하기에 뜨거운 것을 보여줍니다.

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
}

int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24);
if (interval!=0){
   //not the same day;
}

내 솔루션은 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  
    }

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

이것은 피부에 특히 못생긴 고양이이지만 여기에 다른 방법이 있습니다. 우아하다고 말하지는 않지만 iOS의 날짜 / 시간 지원을 통해 얻을 수있는 것만 큼 가깝습니다.

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

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 일 차이 수정

참고URL : https://stackoverflow.com/questions/1854890/comparing-two-nsdates-and-ignoring-the-time-component

반응형