2

I'm using the NSDate-TimeAgo library to format relative time in my iOS application. It displays the relative time of each post in its cell header, as so:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        NSDate *myDate = [df dateFromString: self.datePostedString];
        UILabel *time = [[UILabel alloc]initWithFrame:CGRectMake(230,0,80,50)];
        DDLogVerbose(@"Output is: \"%@\"", [myDate dateTimeAgo]);
        time.text = [myDate dateTimeAgo];
        time.textAlignment = NSTextAlignmentRight;
        [time setFont:[UIFont systemFontOfSize:10]];

However, this library gives me strings that I find are too long. A post in the last minute would be labeled as "a minute ago". I'd like it to be shorter, such as "1m".

Is this possible to do without having to modify the library, or is there an alternative that already does this?

swiftcode
  • 3,039
  • 9
  • 39
  • 64

5 Answers5

3

I think you should probably write you own function.

- (NSString *)timeAgo:(NSDate *)compareDate{
  NSTimeInterval timeInterval = -[compareDate timeIntervalSinceNow];
  int temp = 0;
  NSString *result;
  if (timeInterval < 60) {
    result = [NSString stringWithFormat:@"Just now"];   //less than a minute
  }else if((temp = timeInterval/60) <60){
    result = [NSString stringWithFormat:@"%dm",temp];   //minutes ago
  }else if((temp = temp/60) <24){
    result = [NSString stringWithFormat:@"%dh",temp];   //hours ago
  }else{
    temp = temp / 24;
    result = [NSString stringWithFormat:@"%dd",temp];   //days ago
  }
  return  result;
}
icodesign
  • 876
  • 1
  • 6
  • 12
2

Here's a Swift implementation based on Lei Wang answer.

func getShortRelativeDateFor(date: NSDate) ->String { 

    let timeInterval = -date.timeIntervalSinceNow

    switch timeInterval {
    case 0..<60:
            return String(format: "%.fs", timeInterval)
    case 60..<(60 * 60):
        return String(format: "%.fm", timeInterval / 60)
    case (60 * 60)..<(60 * 60 * 24):
        return String(format: "%.fh", timeInterval / (60 * 60))
    case (60 * 60 * 24)..<(60 * 60 * 24 * 365):
        return String(format: "%.fd", timeInterval / (60 * 60 * 24))
    default:
        return String(format: "%.fy", timeInterval / (60 * 60 * 24 * 365))
    }
}
pteofil
  • 4,133
  • 17
  • 27
1

You can not achieve this without changing the third-party class. In your situation, NSDate-TimeAgo library is too powerful for you. You even don't need any 'ago' result. So, personally I suggest you to convert time string on your own code, something like (just an example, maybe there are some performance issues here, you can use Time Profile to test it):

+ (NSString *)stringForDisplayFromDate:(NSDate *)date
{
    if (!date) {
        return nil;
    }

    NSDate *currentDate = [NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:(kCFCalendarUnitYear
                                                     |kCFCalendarUnitMonth
                                                     |kCFCalendarUnitWeek
                                                     |kCFCalendarUnitDay
                                                     |kCFCalendarUnitHour
                                                     |kCFCalendarUnitMinute)
                                           fromDate:date
                                             toDate:currentDate
                                            options:0];
    if (components.year == 0) {
        // same year
        if (components.month == 0) {
            // same month
            if (components.week == 0) {
                // same week
                if (components.day == 0) {
                    // same day
                    if (components.hour == 0) {
                        // same hour
                        if (components.minute < 10) {
                            // in 10 mins
                            return @"now";
                        } else {
                            // 10 mins age
                            return [NSString stringWithFormat:@"%dm", (int)(components.minute/10)*10];
                        }
                    } else {
                        // different hour
                        return [NSString stringWithFormat:@"%dh", components.hour];
                    }
                } else {
                    // different day
                    return [NSString stringWithFormat:@"%dd", components.day];
                }    
            } else {
                // different week
                return [NSString stringWithFormat:@"%dW", components.week];
            }
        } else {
            // different month
            return [NSString stringWithFormat:@"%dM", components.month];
        }
    } else {
        // different year
        return [NSString stringWithFormat:@"%dY", components.year];
    }

    return [self stringForDisplayFromDate:date prefixed:NO];
}
Danny Xu
  • 401
  • 3
  • 10
  • This will not work for localized strings, unfortunately. – swiftcode Dec 27 '13 at 03:03
  • 1
    Actually, it works for me, as I said, you can change this kind of code, add your localised strings in formatting job. [NSString stringWithFormat:@"%d%@", (int)(components.minute/10)*10, localised string here]; – Danny Xu Dec 27 '13 at 03:07
1

You should use DateTools. See the Time Ago section in the README, it does exactly what you want:

NSDate *timeAgoDate = [NSDate dateWithTimeIntervalSinceNow:-4];
NSLog(@"Time Ago: %@", timeAgoDate.shortTimeAgoSinceNow);

//Output:
//Time Ago: 4s

Note that this solution supports 33 languages (at the time of writing).

ndbroadbent
  • 13,513
  • 3
  • 56
  • 85
0

This function will return NSString starting from sec to years. Like if your date is of "1 sec ago" or if it is of "1 min ago" or "1 year ago" and so on.. it will return likewise..

-(NSString*)HourCalculation:(NSString*)PostDate

{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    [dateFormat setTimeZone:gmt];
    NSDate *ExpDate = [dateFormat dateFromString:PostDate];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:(NSDayCalendarUnit|NSWeekCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit|NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:ExpDate toDate:[NSDate date] options:0];
    NSString *time;
    if(components.year!=0)
    {
        if(components.year==1)
        {
            time=[NSString stringWithFormat:@"%ld year",(long)components.year];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld years",(long)components.year];
        }
    }
    else if(components.month!=0)
    {
        if(components.month==1)
        {
            time=[NSString stringWithFormat:@"%ld month",(long)components.month];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld months",(long)components.month];
        }
    }
    else if(components.week!=0)
    {
        if(components.week==1)
        {
            time=[NSString stringWithFormat:@"%ld week",(long)components.week];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld weeks",(long)components.week];
        }
    }
    else if(components.day!=0)
    {
        if(components.day==1)
        {
            time=[NSString stringWithFormat:@"%ld day",(long)components.day];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld days",(long)components.day];
        }
    }
    else if(components.hour!=0)
    {
        if(components.hour==1)
        {
            time=[NSString stringWithFormat:@"%ld hour",(long)components.hour];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld hours",(long)components.hour];
        }
    }
    else if(components.minute!=0)
    {
        if(components.minute==1)
        {
            time=[NSString stringWithFormat:@"%ld min",(long)components.minute];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld mins",(long)components.minute];
        }
    }
    else if(components.second>=0)
    {
        if(components.second==0)
        {
            time=[NSString stringWithFormat:@"1 sec"];
        }
        else
        {
            time=[NSString stringWithFormat:@"%ld secs",(long)components.second];
        }
    }
    return [NSString stringWithFormat:@"%@ ago",time];
}
Nikita Khandelwal
  • 1,741
  • 16
  • 25