iPhone: Convert date string to a relative time stamp

后端 未结 11 976
醉梦人生
醉梦人生 2020-11-27 09:30

I\'ve got a timestamp as a string like:

Thu, 21 May 09 19:10:09 -0700

and I\'d like to convert it to a relative time stamp like

相关标签:
11条回答
  • 2020-11-27 10:06

    Use the NSDate class:

    timeIntervalSinceDate
    

    returns the interval in seconds.

    Quick exercise to implement this in objective-c:

    1. Get time "now" NSDate
    2. Get the NSDate you wish to compare with
    3. Get the interval in seconds using timeIntervalSinceDate

    Then implement this pseudo code:

    if (x < 60) // x seconds ago
    
    else if( x/60 < 60) // floor(x/60) minutes ago
    
    else if (x/(60*60) < 24) // floor(x/(60*60) hours ago
    
    else if (x/(24*60*60) < 7) // floor(x(24*60*60) days ago
    

    and so on...

    then you need to decide whether a month is 30,31 or 28 days. Keep it simple - pick 30.

    There might be a better way, but its 2am and this is the first thing that came to mind...

    0 讨论(0)
  • 2020-11-27 10:09

    I can't edit yet, but I took Gilean's code and made a couple of tweaks and made it a category of NSDateFormatter.

    It accepts a format string so it will work w/ arbitrary strings and I added if clauses to have singular events be grammatically correct.

    Cheers,

    Carl C-M

    @interface NSDateFormatter (Extras)
    + (NSString *)dateDifferenceStringFromString:(NSString *)dateString
                                      withFormat:(NSString *)dateFormat;
    
    @end
    
    @implementation NSDateFormatter (Extras)
    
    + (NSString *)dateDifferenceStringFromString:(NSString *)dateString
                                      withFormat:(NSString *)dateFormat
    {
      NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
      [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
      [dateFormatter setDateFormat:dateFormat];
      NSDate *date = [dateFormatter dateFromString:dateString];
      [dateFormatter release];
      NSDate *now = [NSDate date];
      double time = [date timeIntervalSinceDate:now];
      time *= -1;
      if(time < 1) {
        return dateString;
      } else if (time < 60) {
        return @"less than a minute ago";
      } else if (time < 3600) {
        int diff = round(time / 60);
        if (diff == 1) 
          return [NSString stringWithFormat:@"1 minute ago", diff];
        return [NSString stringWithFormat:@"%d minutes ago", diff];
      } else if (time < 86400) {
        int diff = round(time / 60 / 60);
        if (diff == 1)
          return [NSString stringWithFormat:@"1 hour ago", diff];
        return [NSString stringWithFormat:@"%d hours ago", diff];
      } else if (time < 604800) {
        int diff = round(time / 60 / 60 / 24);
        if (diff == 1) 
          return [NSString stringWithFormat:@"yesterday", diff];
        if (diff == 7) 
          return [NSString stringWithFormat:@"last week", diff];
        return[NSString stringWithFormat:@"%d days ago", diff];
      } else {
        int diff = round(time / 60 / 60 / 24 / 7);
        if (diff == 1)
          return [NSString stringWithFormat:@"last week", diff];
        return [NSString stringWithFormat:@"%d weeks ago", diff];
      }   
    }
    
    @end
    
    0 讨论(0)
  • 2020-11-27 10:10
    -(NSString *)dateDiff:(NSString *)origDate {
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setFormatterBehavior:NSDateFormatterBehavior10_4];
        [df setDateFormat:@"EEE, dd MMM yy HH:mm:ss VVVV"];
        NSDate *convertedDate = [df dateFromString:origDate];
        [df release];
        NSDate *todayDate = [NSDate date];
        double ti = [convertedDate timeIntervalSinceDate:todayDate];
        ti = ti * -1;
        if(ti < 1) {
            return @"never";
        } else  if (ti < 60) {
            return @"less than a minute ago";
        } else if (ti < 3600) {
            int diff = round(ti / 60);
            return [NSString stringWithFormat:@"%d minutes ago", diff];
        } else if (ti < 86400) {
            int diff = round(ti / 60 / 60);
            return[NSString stringWithFormat:@"%d hours ago", diff];
        } else if (ti < 2629743) {
            int diff = round(ti / 60 / 60 / 24);
            return[NSString stringWithFormat:@"%d days ago", diff];
        } else {
            return @"never";
        }   
    }
    
    0 讨论(0)
  • 2020-11-27 10:10

    I took Carl Coryell-Martin's code and made a simpler NSDate category that doesn't have warnings about the string formatting of the singulars, and also tidys up the week ago singular:

    @interface NSDate (Extras)
    - (NSString *)differenceString;
    @end
    
    @implementation NSDate (Extras)
    
    - (NSString *)differenceString{
        NSDate* date = self;
        NSDate *now = [NSDate date];
        double time = [date timeIntervalSinceDate:now];
        time *= -1;
        if (time < 60) {
            int diff = round(time);
            if (diff == 1)
                return @"1 second ago";
            return [NSString stringWithFormat:@"%d seconds ago", diff];
        } else if (time < 3600) {
            int diff = round(time / 60);
            if (diff == 1)
                return @"1 minute ago";
            return [NSString stringWithFormat:@"%d minutes ago", diff];
        } else if (time < 86400) {
            int diff = round(time / 60 / 60);
            if (diff == 1)
                return @"1 hour ago";
            return [NSString stringWithFormat:@"%d hours ago", diff];
        } else if (time < 604800) {
            int diff = round(time / 60 / 60 / 24);
            if (diff == 1)
                return @"yesterday";
            if (diff == 7)
                return @"a week ago";
            return[NSString stringWithFormat:@"%d days ago", diff];
        } else {
            int diff = round(time / 60 / 60 / 24 / 7);
            if (diff == 1)
                return @"a week ago";
            return [NSString stringWithFormat:@"%d weeks ago", diff];
        }   
    }
    
    @end
    
    0 讨论(0)
  • 2020-11-27 10:12

    Here are methods from Cocoa to help you to get relevant info (not sure if they are all available in coca-touch).

        NSDate * today = [NSDate date];
        NSLog(@"today: %@", today);
    
        NSString * str = @"Thu, 21 May 09 19:10:09 -0700";
        NSDate * past = [NSDate dateWithNaturalLanguageString:str
                                locale:[[NSUserDefaults 
                                standardUserDefaults] dictionaryRepresentation]];
    
        NSLog(@"str: %@", str);
        NSLog(@"past: %@", past);
    
        NSCalendar *gregorian = [[NSCalendar alloc]
                                 initWithCalendarIdentifier:NSGregorianCalendar];
        unsigned int unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | 
                                 NSDayCalendarUnit | 
                                 NSHourCalendarUnit | NSMinuteCalendarUnit | 
                                 NSSecondCalendarUnit;
        NSDateComponents *components = [gregorian components:unitFlags
                                                    fromDate:past
                                                      toDate:today
                                                     options:0];
    
        NSLog(@"months: %d", [components month]);
        NSLog(@"days: %d", [components day]);
        NSLog(@"hours: %d", [components hour]);
        NSLog(@"seconds: %d", [components second]);
    

    The NSDateComponents object seems to hold the difference in relevant units (as specified). If you specify all units you can then use this method:

    void dump(NSDateComponents * t)
    {
        if ([t year]) NSLog(@"%d years ago", [t year]);
        else if ([t month]) NSLog(@"%d months ago", [t month]);
        else if ([t day]) NSLog(@"%d days ago", [t day]);
        else if ([t minute]) NSLog(@"%d minutes ago", [t minute]);
        else if ([t second]) NSLog(@"%d seconds ago", [t second]);
    }
    

    If you want to calculate yourself you can have a look at:

    NSDate timeIntervalSinceDate
    

    And then use seconds in the algorithm.

    Disclaimer: If this interface is getting deprecated (I haven't checked), Apple's preferred way of doing this via NSDateFormatters, as suggested in comments below, looks pretty neat as well - I'll keep my answer for historical reasons, it may still be useful for some to look at the logic used.

    0 讨论(0)
  • 2020-11-27 10:14

    There are already a lot of answers that come to the same solution but it can't hurt to have choices. Here's what I came up with.

    - (NSString *)stringForTimeIntervalSinceCreated:(NSDate *)dateTime
    {
        NSDictionary *timeScale = @{@"second":@1,
                                    @"minute":@60,
                                    @"hour":@3600,
                                    @"day":@86400,
                                    @"week":@605800,
                                    @"month":@2629743,
                                    @"year":@31556926};
        NSString *scale;
        int timeAgo = 0-(int)[dateTime timeIntervalSinceNow];
        if (timeAgo < 60) {
            scale = @"second";
        } else if (timeAgo < 3600) {
            scale = @"minute";
        } else if (timeAgo < 86400) {
            scale = @"hour";
        } else if (timeAgo < 605800) {
            scale = @"day";
        } else if (timeAgo < 2629743) {
            scale = @"week";
        } else if (timeAgo < 31556926) {
            scale = @"month";
        } else {
            scale = @"year";
        }
    
        timeAgo = timeAgo/[[timeScale objectForKey:scale] integerValue];
        NSString *s = @"";
        if (timeAgo > 1) {
            s = @"s";
        } 
        return [NSString stringWithFormat:@"%d %@%@ ago", timeAgo, scale, s];
    }
    
    0 讨论(0)
提交回复
热议问题