I need to display the date of posts in my app to the user, right now I do it in this format: "Fri, 25 May". How would I format an NSDate to read something like "2 hours ago"? To make it more user friendly.
-
1possible duplicate of [Smart Formatting of time span](http://stackoverflow.com/questions/5741952/smart-formatting-of-time-span) – Sergey Kalinichenko Apr 09 '12 at 16:01
-
check [this answer](http://stackoverflow.com/a/34359788/1106035) which has sample link. – Paresh Navadiya Dec 18 '15 at 16:25
9 Answers
Take a look at FormaterKit https://github.com/mattt/FormatterKit
Created by mattt who also created AFNetworking.
- 11,310
- 14
- 73
- 120
-
1This should get ore upvotes, its a great kit created by a great developer and its so easy to use. – NodeDad Jun 09 '13 at 04:46
NSDateFormatter can't do things like that; you're going to need to establish your own rules. I guess something like:
- (NSString *)formattedDate:(NSDate *)date
{
NSTimeInterval timeSinceDate = [[NSDate date] timeIntervalSinceDate:date];
// print up to 24 hours as a relative offset
if(timeSinceDate < 24.0 * 60.0 * 60.0)
{
NSUInteger hoursSinceDate = (NSUInteger)(timeSinceDate / (60.0 * 60.0));
switch(hoursSinceDate)
{
default: return [NSString stringWithFormat:@"%d hours ago", hoursSinceDate];
case 1: return @"1 hour ago";
case 0:
NSUInteger minutesSinceDate = (NSUInteger)(timeSinceDate / 60.0);
/* etc, etc */
break;
}
}
else
{
/* normal NSDateFormatter stuff here */
}
}
So that's to print 'x minutes ago' or 'x hours ago' up to 24 hours from the date, which will usually be one day.
- 98,579
- 12
- 179
- 201
I wanted a date format like Facebook does for their mobile apps so I whipped up this NSDate category - hope it is useful for someone (this kind of stuff should really be in a standard library!) :)
- 732
- 1
- 6
- 21
-
I went through your library and it was very useful. But in ur library, things like "just now", "6mins ago", "7 hrs ago" work well. But i also want things like "3 days ago", "4 weeks ago", "2 yrs ago". How to get that done? – The X-Coder Aug 05 '13 at 05:50
-
This was created to mimic the Facebook style of date format. It's meant to be human readable and easily understandable (they have put a lot of thought into how to best represent the date and I think its pretty clear when you are using it that this is a good format. Things like 4 weeks ago doesn't give you enough specific information when you are looking at past time intervals. If you want to get something like that just modify the strings which are output by the if statement. – N V Aug 08 '13 at 05:57
-
But that was my company's requirement and also i thought instead of displaying "Oct 3 at 12.42am', it could consume a lot of space, if i write "1 w"(one week ago) – The X-Coder Aug 08 '13 at 07:23
There's also SEHumanizedTimeDiff which does/is about to support multiple languages if that's an issue for you:
- 2,810
- 1
- 23
- 39
-
1This is a nice little library, and the Localisation alone deserves an up vote; since its something none of the other proposed solutions do. – Carlos P Feb 04 '13 at 14:57
-
1Agree with @CarlosP. There are already plenty of languages contributed by the looks too. – djskinner Jun 20 '13 at 22:25
There are about a million ways you could do this, but here's a quick one:
NSString* hoursAgo = [NSString stringWithFormat:@"%.0lf hours ago", fabs([date timeIntervalSinceNow] / 3600.0)]
Of course, this doesn't check that date is actually from the past, doesn't do anything but hours, etc. But, you probably get the idea.
timeIntervalSinceNow returns how many seconds have passed since a given date, with positive numbers being a date in the future and negative numbers being a date in the past. So, we get how many seconds have passed, divide it by 3600 seconds in an hour to compute the hours that have passed, and then put its absolute value into the string "n hours ago".
- 4,076
- 1
- 23
- 33
Here is a pretty good answer this will take in seconds since the epoch(Jan 1, 1970) and return you a nice formatted string like '3 minutes ago'. Simply call it with your date object like so:
[timeAgoFromUnixTime:[myDateObject timeIntervalSince1970]];
+ (NSString *)timeAgoFromUnixTime:(double)seconds
{
double difference = [[NSDate date] timeIntervalSince1970] - seconds;
NSMutableArray *periods = [NSMutableArray arrayWithObjects:@"second", @"minute", @"hour", @"day", @"week", @"month", @"year", @"decade", nil];
NSArray *lengths = [NSArray arrayWithObjects:@60, @60, @24, @7, @4.35, @12, @10, nil];
int j = 0;
for(j=0; difference >= [[lengths objectAtIndex:j] doubleValue]; j++)
{
difference /= [[lengths objectAtIndex:j] doubleValue];
}
difference = roundl(difference);
if(difference != 1)
{
[periods insertObject:[[periods objectAtIndex:j] stringByAppendingString:@"s"] atIndex:j];
}
return [NSString stringWithFormat:@"%li %@%@", (long)difference, [periods objectAtIndex:j], @" ago"];
}
- 562
- 5
- 7
In newer versions of iOS since this question was asked, NSDateFormatter has had this ability added. It can now do it using the doesRelativeDateFormatting property.
- 17,853
- 8
- 77
- 100
-
Can't get this to work. Checked docs and not sure what I am doing wrong. If I format to a regular date I get a string. However if I cal setDoesRelativeDateFormatting I don't get anything back. Ideas? Code example? – lostintranslation Jul 15 '14 at 13:38
-
You can find it in some tutorials using Google, but I think you should post your question as a new SO question so we can see your code! Its hard to give advice without it. – Peter DeWeese Jul 15 '14 at 13:53
+(NSString*)HourCalculation:(NSString*)PostDate
{
NSLog(@"postdate=%@",PostDate);
// PostDate=@"2014-04-02 01:31:04";
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];
NSLog(@"expdate=%@",ExpDate);
NSLog(@"expdate=%@",[NSDate date ]);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSDayCalendarUnit|NSWeekCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit|NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:ExpDate toDate:[NSDate date] options:0];
// NSLog(@"year=%d",components.year);
//
// NSLog(@"month=%d",components.month);
//
// NSLog(@"week=%d",components.week);
//
// NSLog(@"day=%d",components.day);
//
// NSLog(@"hour=%d",components.hour);
//
// NSLog(@"min=%d",components.minute);
//
// NSLog(@"sce=%d",components.second);
//
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];
}
// NSLog(@"%@",time);
}
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];
}
// NSLog(@"%@",time);
}
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];
}
// NSLog(@"time=%@",time);
}
else if(components.second>=0){
// NSLog(@"postdate=%@",PostDate);
// NSLog(@"expdate=%@",[NSDate date ]);
if(components.second==0)
{
time=[NSString stringWithFormat:@"1 sec"];
}
else{
time=[NSString stringWithFormat:@"%ld secs",(long)components.second];
}
}
return [NSString stringWithFormat:@"%@ ago",time];
}
This code will show you time in ------------sec like 2 sec ago ------------min like 2 mins ago ------------hours like 2 hours ago ------------days like 2 days ago ------------week like 2 weeks ago ------------month like 2 months ago Lastly.... years like 2 years ago :) try this
- 1
- 1
- 1,741
- 15
- 25
Adding to the solution try this more simplified method
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:passed toDate:[NSDate date] options:0];
NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:date];
if (interval < 60) timestampString = [NSString stringWithFormat:@"%d seconds ago" ,today.second];
else if (interval < 60 * 60) timestampString = [NSString stringWithFormat:@"%d minutes ago" ,today.minute];
else if (interval < 60 * 60 * 24) timestampString = [NSString stringWithFormat:@"%d hours ago" ,today.hour];
else timestampString = [NSString stringWithFormat:@"%d days ago" ,today.day];
- 844
- 9
- 14