2009-06-27 4 views
11

iPhone 용 Objective-C에서 날짜를 계산하는 퍼지 날짜 방법을 쓰고 싶습니다. 이 누락 된 인수를 포함하지만Objective-C의 퍼지 날짜 알고리즘

Calculate relative time in C#

: 여기에 인기있는 설명이있다. 이것이 Objective-C에서 어떻게 사용될 수 있습니까? 감사.

const int SECOND = 1; 
const int MINUTE = 60 * SECOND; 
const int HOUR = 60 * MINUTE; 
const int DAY = 24 * HOUR; 
const int MONTH = 30 * DAY; 

if (delta < 1 * MINUTE) 
{ 
    return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago"; 
} 
if (delta < 2 * MINUTE) 
{ 
    return "a minute ago"; 
} 
if (delta < 45 * MINUTE) 
{ 
    return ts.Minutes + " minutes ago"; 
} 
if (delta < 90 * MINUTE) 
{ 
    return "an hour ago"; 
} 
if (delta < 24 * HOUR) 
{ 
    return ts.Hours + " hours ago"; 
} 
if (delta < 48 * HOUR) 
{ 
    return "yesterday"; 
} 
if (delta < 30 * DAY) 
{ 
    return ts.Days + " days ago"; 
} 
if (delta < 12 * MONTH) 
{ 
    int months = Convert.ToInt32(Math.Floor((double)ts.Days/30)); 
    return months <= 1 ? "one month ago" : months + " months ago"; 
} 
else 
{ 
    int years = Convert.ToInt32(Math.Floor((double)ts.Days/365)); 
    return years <= 1 ? "one year ago" : years + " years ago"; 
} 

답변

23

날짜는 NSDate 클래스를 사용하여 코코아로 표시됩니다. 두 개의 날짜 인스턴스 사이의 초 단위의 델타 (timeIntervalSinceDate:)를 얻으려면 NSDate에 구현 된 편리한 방법이 있습니다. 이 인스턴스는 NSDate 인스턴스에서 호출되며 다른 NSDate 개체를 인수로 사용합니다. 두 날짜 사이의 초 수를 나타내는 NSTimeInterval (double에 대한 typedef)을 반환합니다.

이 점을 감안할 때 위에서 제시 한 코드를 Objective-C/Cocoa 컨텍스트에 적용하는 것은 상당히 간단합니다. 시작을 전달

//Constants 
#define SECOND 1 
#define MINUTE (60 * SECOND) 
#define HOUR (60 * MINUTE) 
#define DAY (24 * HOUR) 
#define MONTH (30 * DAY) 

- (NSString*)timeIntervalWithStartDate:(NSDate*)d1 withEndDate:(NSDate*)d2 
{ 
    //Calculate the delta in seconds between the two dates 
    NSTimeInterval delta = [d2 timeIntervalSinceDate:d1]; 

    if (delta < 1 * MINUTE) 
    { 
     return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%d seconds ago", (int)delta]; 
    } 
    if (delta < 2 * MINUTE) 
    { 
     return @"a minute ago"; 
    } 
    if (delta < 45 * MINUTE) 
    { 
     int minutes = floor((double)delta/MINUTE); 
     return [NSString stringWithFormat:@"%d minutes ago", minutes]; 
    } 
    if (delta < 90 * MINUTE) 
    { 
     return @"an hour ago"; 
    } 
    if (delta < 24 * HOUR) 
    { 
     int hours = floor((double)delta/HOUR); 
     return [NSString stringWithFormat:@"%d hours ago", hours]; 
    } 
    if (delta < 48 * HOUR) 
    { 
     return @"yesterday"; 
    } 
    if (delta < 30 * DAY) 
    { 
     int days = floor((double)delta/DAY); 
     return [NSString stringWithFormat:@"%d days ago", days]; 
    } 
    if (delta < 12 * MONTH) 
    { 
     int months = floor((double)delta/MONTH); 
     return months <= 1 ? @"one month ago" : [NSString stringWithFormat:@"%d months ago", months]; 
    } 
    else 
    { 
     int years = floor((double)delta/MONTH/12.0); 
     return years <= 1 ? @"one year ago" : [NSString stringWithFormat:@"%d years ago", years]; 
    } 
} 

이것은 다음 호출 할 것이며 인수로 NSDate 객체를 종료하고를 반환 : NSDate에 의해 계산 된 델타 초에 주어진 두 날짜를 부여하기 때문에, 당신은 쉽게 위의 코드를 적용 할 수 NSString과 시간 간격.

+0

이 아름답게 작동합니다

이 내가 함께 던진 것입니다. 감사! –

+3

이 구현의 유일한 문제점은 하루 24 시간과 달력 하루를 구별하지 않는다는 것입니다. 즉 오후 11시와 오전 2시를 비교하는 경우 차이는 "3 시간 전"이 아닌 "어제"가되어야합니다. NSCalendar와 그 부속 NSDateComponents 클래스를 살펴보십시오. – retainCount

1

당신은 timeIntervalSinceDate: 방법을 사용하여 두 NSDate 객체 사이의 델타를 얻을 수 있습니다. 델타가 몇초 만에 줄거야.

그로부터 적절한 시간으로 나누어 분/시간/일/수/년을 계산할 수 있습니다.

1

대안으로, 당신은 당신이 두 날짜 사이의 차이에서 풀 수있는 달력 구성 요소에 의존하여 오류가 발생하기 쉬운 달력 연산을 피할 수 있습니다 :

NSDate *nowDate = [[NSDate alloc] init]; 
NSDate *targetDate = nil; // some other date here of your choosing, obviously nil isn't going to get you very far 

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
NSUInteger unitFlags = NSMonthCalendarUnit | NSWeekCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit; 
NSDateComponents *components = [gregorian components:unitFlags 
              fromDate:dateTime 
               toDate:nowDate options:0]; 
NSInteger months = [components month]; 
NSInteger weeks = [components week]; 
NSInteger days = [components day]; 
NSInteger hours = [components hour]; 
NSInteger minutes = [components minute]; 

키는 단위 플래그의 설정입니다.이 키를 사용하여 날짜/시간을 세분화 할 시간 단위를 설정할 수 있습니다. 몇 시간을 원한다면 NSHourCalendarUnit을 설정하면됩니다. 증분을 시작할 단위가 더 크기 때문에 날짜가 멀어 질수록 그 값은 계속 증가 할 것입니다.

일단 구성 요소가 있으면 @ alex의 조건부 흐름을 수정하여 원하는 논리로 진행할 수 있습니다.

if (months > 1) { 
    // Simple date/time 
    if (weeks >3) { 
     // Almost another month - fuzzy 
     months++; 
    } 
    return [NSString stringWithFormat:@"%ld months ago", (long)months]; 
} 
else if (months == 1) { 
    if (weeks > 3) { 
     months++; 
     // Almost 2 months 
     return [NSString stringWithFormat:@"%ld months ago", (long)months]; 
    } 
    // approx 1 month 
    return [NSString stringWithFormat:@"1 month ago"]; 
} 
// Weeks 
else if (weeks > 1) { 
    if (days > 6) { 
     // Almost another month - fuzzy 
     weeks++; 
    } 
    return [NSString stringWithFormat:@"%ld weeks ago", (long)weeks]; 
} 
else if (weeks == 1 || 
     days > 6) { 
    if (days > 6) { 
     weeks++; 
     // Almost 2 weeks 
     return [NSString stringWithFormat:@"%ld weeks ago", (long)weeks]; 
    } 
    return [NSString stringWithFormat:@"1 week ago"]; 
} 
// Days 
else if (days > 1) { 
    if (hours > 20) { 
     days++; 
    } 
    return [NSString stringWithFormat:@"%ld days ago", (long)days]; 
} 
else if (days == 1) { 
    if (hours > 20) { 
     days++; 
     return [NSString stringWithFormat:@"%ld days ago", (long)days]; 
    } 
    return [NSString stringWithFormat:@"1 day ago"]; 
} 
// Hours 
else if (hours > 1) { 
    if (minutes > 50) { 
     hours++; 
    } 
    return [NSString stringWithFormat:@"%ld hours ago", (long)hours]; 
} 
else if (hours == 1) { 
    if (minutes > 50) { 
     hours++; 
     return [NSString stringWithFormat:@"%ld hours ago", (long)hours]; 
    } 
    return [NSString stringWithFormat:@"1 hour ago"]; 
} 
// Minutes 
else if (minutes > 1) { 
    return [NSString stringWithFormat:@"%ld minutes ago", (long)minutes]; 
} 
else if (minutes == 1) { 
    return [NSString stringWithFormat:@"1 minute ago"]; 
} 
else if (minutes < 1) { 
    return [NSString stringWithFormat:@"Just now"]; 
}