Programing

두 NSDate 사이의 일수

crosscheck 2020. 6. 11. 23:58
반응형

두 NSDate 사이의 일수


이 질문에는 이미 답변이 있습니다.

NSDate사이의 일 수를 어떻게 확인할 수 있습니까 (시간도 고려)?

NSDate값은 형태가 무엇이든에 [NSDate date]걸립니다.

특히, 사용자가 내 iPhone 앱에서 비활성 상태가되면 다음 값을 저장합니다.

exitDate = [NSDate date];

그리고 그들이 앱을 다시 열면 현재 시간을 얻습니다.

NSDate *now = [NSDate date];

이제 다음을 구현하고 싶습니다.

-(int)numberOfDaysBetweenStartDate:exitDate andEndDate:now

다음은 두 날짜 사이의 달력 일 수를 결정하는 데 사용한 구현입니다.

+ (NSInteger)daysBetweenDate:(NSDate*)fromDateTime andDate:(NSDate*)toDateTime
{
    NSDate *fromDate;
    NSDate *toDate;

    NSCalendar *calendar = [NSCalendar currentCalendar];

    [calendar rangeOfUnit:NSCalendarUnitDay startDate:&fromDate
        interval:NULL forDate:fromDateTime];
    [calendar rangeOfUnit:NSCalendarUnitDay startDate:&toDate
        interval:NULL forDate:toDateTime];

    NSDateComponents *difference = [calendar components:NSCalendarUnitDay
        fromDate:fromDate toDate:toDate options:0];

    return [difference day];
}

편집하다:

위의 환상적인 솔루션, 다음은 Swift 버전입니다 NSDate.

extension NSDate {
  func numberOfDaysUntilDateTime(toDateTime: NSDate, inTimeZone timeZone: NSTimeZone? = nil) -> Int {
    let calendar = NSCalendar.currentCalendar()
    if let timeZone = timeZone {
      calendar.timeZone = timeZone
    }

    var fromDate: NSDate?, toDate: NSDate?

    calendar.rangeOfUnit(.Day, startDate: &fromDate, interval: nil, forDate: self)
    calendar.rangeOfUnit(.Day, startDate: &toDate, interval: nil, forDate: toDateTime)

    let difference = calendar.components(.Day, fromDate: fromDate!, toDate: toDate!, options: [])
    return difference.day
  }
}

사용 사례에 따라 제거 할 수있는 약간의 강제 풀기 작업.

위의 솔루션은 현재 시간대 이외의 시간대에서도 작동하며 전 세계 장소에 대한 정보를 보여주는 앱에 적합합니다.


내가 찾은 최고의 솔루션은 다음과 같습니다. NSDate 사이의 모든 단위를 결정하기 위해 Apple에서 승인 한 방법을 사용하는 것 같습니다.

- (int)daysBetween:(NSDate *)dt1 and:(NSDate *)dt2 {
    NSUInteger unitFlags = NSDayCalendarUnit;
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSDateComponents *components = [calendar components:unitFlags fromDate:dt1 toDate:dt2 options:0];
    return [components day]+1;
}

예를 들어 몇 달을 원한다면 'NSMonthCalendarUnit'을 unitFlag로 포함시킬 수 있습니다.

(내가 위에 고정으니 약간의 실수가 있었지만) 원래 블로거 신용, 내가 여기에이 정보를 발견 http://cocoamatic.blogspot.com/2010/09/nsdate-number-of-days-between- two-dates.html? showComment = 1306198273659 # c6501446329564880344


스위프트 3.0 업데이트

extension Date {

    func differenceInDaysWithDate(date: Date) -> Int {
        let calendar = Calendar.current

        let date1 = calendar.startOfDay(for: self)
        let date2 = calendar.startOfDay(for: date)

        let components = calendar.dateComponents([.day], from: date1, to: date2)
        return components.day ?? 0
    }
}

스위프트 2.0 업데이트

extension NSDate {

    func differenceInDaysWithDate(date: NSDate) -> Int {
        let calendar: NSCalendar = NSCalendar.currentCalendar()

        let date1 = calendar.startOfDayForDate(self)
        let date2 = calendar.startOfDayForDate(date)

        let components = calendar.components(.Day, fromDate: date1, toDate: date2, options: [])
        return components.day
    }

}

독창적 인 솔루션

Swift의 또 다른 솔루션.

두 날짜 사이에 정확한 일 수를 얻는 것이 목적이라면이 문제를 다음과 같이 해결할 수 있습니다.

// Assuming that firstDate and secondDate are defined
// ...

var calendar: NSCalendar = NSCalendar.currentCalendar()

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)

let flags = NSCalendarUnit.DayCalendarUnit
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: nil)

components.day  // This will return the number of day(s) between dates

NSDate 클래스의 카테고리 메소드로 이것을 사용합니다.

// returns number of days (absolute value) from another date (as number of midnights beween these dates)
- (int)daysFromDate:(NSDate *)pDate {
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSInteger startDay=[calendar ordinalityOfUnit:NSCalendarUnitDay
                                           inUnit:NSCalendarUnitEra
                                          forDate:[NSDate date]];
    NSInteger endDay=[calendar ordinalityOfUnit:NSCalendarUnitDay
                                         inUnit:NSCalendarUnitEra
                                        forDate:pDate];
    return abs(endDay-startDay);
}

시작일을 포함하여 두 날짜 사이의 일수가 필요했습니다. 예를 들어 14-2-2012에서 16-2-2012 사이의 날짜는 3의 결과를 생성합니다.

+ (NSInteger)daysBetween:(NSDate *)dt1 and:(NSDate *)dt2 {
        NSUInteger unitFlags = NSDayCalendarUnit;
        NSCalendar* calendar = [NSCalendar currentCalendar];
        NSDateComponents *components = [calendar components:unitFlags fromDate:dt1 toDate:dt2 options:0];
        NSInteger daysBetween = abs([components day]);
    return daysBetween+1;
}

날짜를 제공 한 순서는 중요하지 않습니다. 항상 양수를 반환합니다.


NSDate *lastDate = [NSDate date];
NSDate *todaysDate = [NSDate date];
NSTimeInterval lastDiff = [lastDate timeIntervalSinceNow];
NSTimeInterval todaysDiff = [todaysDate timeIntervalSinceNow];
NSTimeInterval dateDiff = lastDiff - todaysDiff;

그러면 dateDiff는 두 날짜 사이의 초 수입니다. 하루의 초 수로 나눕니다.


@ 브라이언

Brian의 대답은 훌륭하지만 24 시간 청크 단위로 일의 차이 만 계산하지만 달력 날짜의 차이는 계산하지 않습니다. 예를 들어 12 월 24 일 23:59는 여전히 하루로 간주되는 많은 응용 프로그램의 목적으로 크리스마스 날로부터 1 분 거리에 있습니다. Brian의 daysBetween 함수는 0을 반환합니다.

Brian의 원래 구현 및 시작 / 끝에서 차용하여 프로그램에서 다음을 사용합니다. ( NSDate 시작 및 끝 )

- (NSDate *)beginningOfDay:(NSDate *)date
{
    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDateComponents *components = [cal components:( NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond:0];
    return [cal dateFromComponents:components];
}

- (NSDate *)endOfDay:(NSDate *)date
{
    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDateComponents *components = [cal components:( NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];
    [components setHour:23];
    [components setMinute:59];
    [components setSecond:59];
    return [cal dateFromComponents:components];
}

- (int)daysBetween:(NSDate *)date1 and:(NSDate *)date2 {
    NSDate *beginningOfDate1 = [self beginningOfDay:date1];
    NSDate *endOfDate1 = [self endOfDay:date1];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *beginningDayDiff = [calendar components:NSDayCalendarUnit fromDate:beginningOfDate1 toDate:date2 options:0];
    NSDateComponents *endDayDiff = [calendar components:NSDayCalendarUnit fromDate:endOfDate1 toDate:date2 options:0];
    if (beginningDayDiff.day > 0)
        return beginningDayDiff.day;
    else if (endDayDiff.day < 0)
        return endDayDiff.day;
    else {
        return 0;
    }
}

다른 접근법 :

NSDateFormatter* dayFmt = [[NSDateFormatter alloc] init];
[dayFmt setTimeZone:<whatever time zone you want>];
[dayFmt setDateFormat:@"g"];
NSInteger firstDay = [[dayFmt stringFromDate:firstDate] integerValue];    
NSInteger secondDay = [[dayFmt stringFromDate:secondDate] integerValue];
NSInteger difference = secondDay - firstDay;

timeIntervalSince...시간대를 고려할 수있는 구성표 보다 장점이 있으며 하루 또는 몇 초 간격으로 모호성이 없습니다.

그리고 NSDateComponents 접근 방식보다 약간 더 작고 덜 혼란 스럽습니다.


Swift 에서이 페이지를 방문하는 사람들에게 답을 추가하십시오. 접근 방식은 거의 동일합니다.

private class func getDaysBetweenDates(startDate:NSDate, endDate:NSDate) -> NSInteger {

    var gregorian: NSCalendar = NSCalendar.currentCalendar();
    let flags = NSCalendarUnit.DayCalendarUnit
    let components = gregorian.components(flags, fromDate: startDate, toDate: endDate, options: nil)

    return components.day
}

이 답변은 다음 방법의 토론 섹션에서 찾을 수 있습니다 .

components(_:fromDate:toDate:options:)

다음은 Swift에서 Brian의 기능을 구현 한 것입니다.

class func daysBetweenThisDate(fromDateTime:NSDate, andThisDate toDateTime:NSDate)->Int?{

    var fromDate:NSDate? = nil
    var toDate:NSDate? = nil

    let calendar = NSCalendar.currentCalendar()

    calendar.rangeOfUnit(NSCalendarUnit.DayCalendarUnit, startDate: &fromDate, interval: nil, forDate: fromDateTime)

    calendar.rangeOfUnit(NSCalendarUnit.DayCalendarUnit, startDate: &toDate, interval: nil, forDate: toDateTime)

    if let from = fromDate {

        if let to = toDate {

            let difference = calendar.components(NSCalendarUnit.DayCalendarUnit, fromDate: from, toDate: to, options: NSCalendarOptions.allZeros)

            return difference.day
        }
    }

    return nil
}

Do you mean calendar days or 24-hour periods? i.e. is Tuesday at 9PM a day before Wednesday at 6AM, or less than one day?

If you mean the former, it's a bit complicated and you'll have to resort to manipulations via NSCalendar and NSDateComponent which I don't recall off the top of my head.

If you mean the latter, just get the dates' time intervals since the reference date, subtract one from the other, and divide by 24 hours (24 * 60 * 60) to get the approximate interval, leap seconds not included.


Got one, not sure it's exactly what you want, but it could help some of you, (helped me!!)

My goal was to know if, between two date (less than 24h difference) i had a "overday" day+1:

i did the following (a bit archaic i admit)

NSDate *startDate = ...
NSDate *endDate = ...

NSDate already formatted by another NSDateFormatter (this one is just for this purpose :)

NSDateFormatter *dayFormater = [[NSDateFormatter alloc]init];
[dayFormater setDateFormat:@"dd"];

int startDateDay = [[dayFormater stringFromDate:startDate]intValue];

int endDateDay = [[dayFormater stringFromDate:dateOn]intValue];

if (endDateDay > startDateDay) {
    NSLog(@"day+1");
} else {
    NSLog(@"same day");
}

maybe something like this already exist, but didn't find it

Tim


Why not just:

int days = [date1 timeIntervalSinceDate:date2]/24/60/60;

The solution I found was:

+(NSInteger)getDaysDifferenceBetween:(NSDate *)dateA and:(NSDate *)dateB {

  if ([dateA isEqualToDate:dateB]) 
    return 0;

  NSCalendar * gregorian = 
        [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];



  NSDate * dateToRound = [dateA earlierDate:dateB];
  int flags = (NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit);
  NSDateComponents * dateComponents = 
         [gregorian components:flags fromDate:dateToRound];


  NSDate * roundedDate = [gregorian dateFromComponents:dateComponents];

  NSDate * otherDate = (dateToRound == dateA) ? dateB : dateA ;

  NSInteger diff = abs([roundedDate timeIntervalSinceDate:otherDate]);

  NSInteger daysDifference = floor(diff/(24 * 60 * 60));

  return daysDifference;
}

Here I am effectively rounding the first date to start from the beginning of the day and then calculating the difference as Jonathan is suggesting above...


I have published an open-source class/library to do just this.

Have a look at RelativeDateDescriptor, which can be used to obtain the time difference as follows...

RelativeDateDescriptor *descriptor = [[RelativeDateDescriptor alloc] initWithPriorDateDescriptionFormat:@"%@ ago" postDateDescriptionFormat:@"in %@"];

// date1: 1st January 2000, 00:00:00
// date2: 6th January 2000, 00:00:00
[descriptor describeDate:date2 relativeTo:date1]; // Returns '5 days ago'
[descriptor describeDate:date1 relativeTo:date2]; // Returns 'in 5 days'

Why note use the following NSDate method:

- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate

This will return the number of seconds between your two dates and you can divide by 86,400 to get the number of days !!

참고URL : https://stackoverflow.com/questions/4739483/number-of-days-between-two-nsdates

반응형