2

I have seen a lot of questions on StackOverflow that appears to be similar but none of them helped me.

I am parsing an RSS Feed and want to covert the date to the "hours ago" format instead of the default one.

else if ([elementName isEqual:@"pubDate"])
    {
    currentString = [[NSMutableString alloc] init];
    NSLog(@"CURRENT STRING %@", currentString); // THIS IS RETURNING NULL IN LOGS
    [self setPubTime:currentString]; // But this statement is correctly putting the following in the label in custom tableview cell
}

The last line in the above code is putting the label in the custom cells of tableview as below:

enter image description here

Since the line above is returning NULL in the logs for currentString, i am unable to use the function from this question (iPhone: Convert date string to a relative time stamp) to convert it to the "hours ago" format:

Can somebody point to me why the currentString is empty in the Logs but still able to set the label in next statement and how can i convert it to the hours ago format.

Thanks

UPDATE:

Anupdas's answer has solved half of the problem. Now i can see currentString showing timestamp both in NSLog and the pubTime label inside the custom tableview cell. The only thing that is left is to use this timestamps and convert them to the "hours/min/months etc ago" format.

Using the following:

    if ([elementName isEqualToString:@"pubDate"]) {

        NSLog(@"pubTime CURRENT IS %@", currentString);
//        [self setPubTime:currentString];
        NSString *myString = [self dateDiff:currentString];
        [self setPubTime:myString];
}

Here is the log after above code:

enter image description here

For some reason, the following function is not working:

 -(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";
        }   
    }

If anyone can point me to a better solution to convert my currentString to "hours/mins/days/ etc format", kindly let me know. Thanks

Community
  • 1
  • 1
Jessica
  • 1,508
  • 15
  • 25
  • post your setPubTime method code – Balu Apr 20 '13 at 13:59
  • its just a string property @property (nonatomic, strong) NSString *pubTime; and i am setting it to the label in custom view cell of tableview controller – Jessica Apr 20 '13 at 14:02
  • Can you provide a log of your pubDate, it seems like the dateFormat is not correct. The value seems to be clipped but it seems like the dateFormat year format should be "yyyy" instead of "yy", do verify. – Anupdas Apr 20 '13 at 19:05

3 Answers3

4
else if ([elementName isEqual:@"pubDate"])
    {
    currentString = [[NSMutableString alloc] init];
    NSLog(@"CURRENT STRING %@", currentString); // THIS IS RETURNING NULL IN LOGS
    [self setPubTime:currentString]; // But this statement is correctly putting the following in the label in custom tableview cell
}

By doing this your pubTime will have no value. You need to init currentString in foundCharacters delegate of xmlParser and then add the value in didEndElement method.

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if(!currentString){
        currentString = [[NSMutableString alloc] init];
    }
    [currentString appendString:string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
      namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{  
     if ([elementName isEqual:@"pubDate"]){
         NSLog(@"CURRENT STRING %@", currentString);
         [self setPubTime:currentString]; 
         currentString = nil;
     }
}

And You don't need to do all these calculation to find minutes, hours and days you can use NSDateComponents for that. Please refer this post Difference between two dates

Community
  • 1
  • 1
Anupdas
  • 10,211
  • 2
  • 35
  • 60
  • Half of the problem is solved. Now The currentString is showing the timestamp both in the log and in the label inside custom tableview cell. How can i use NSDateComponents to have "hours ago" format? Thanks a lot! – Jessica Apr 20 '13 at 15:19
  • I have asked about how to use NSDateComponents to have "hours ago" format :/ Just checked your last edit, it has nothing to do with NSDateComponents – Jessica Apr 20 '13 at 16:28
  • @Jessica In my unedited answer there was an error, I corrected it. In the post where you took how to find "hours ago", there is another answer which shows how do it with dateComponents. http://stackoverflow.com/a/903200/767730, that is more readable. – Anupdas Apr 20 '13 at 18:57
1

To measure the hour you can use this...

NSTimeInterval distanceBetweenDates = [convertedDate timeIntervalSinceDate:todayDate];
double secondsInAnHour = 3600;
NSInteger hoursBetweenDates = distanceBetweenDates / secondsInAnHour;
NULL
  • 1,848
  • 1
  • 21
  • 23
1

+1 for Anupdas's answer, If you have two date variables you can find the difference easily. You need to find how many hours ago a particular post was made (like you see in twitter 11s ago etc). So you could use NSDate's inbuilt function timeIntervalSinceDate: function. So you will be passing current date and the date you get from the feed. You would get a NSTimeInterval object, so dividing that object by 60*60 would give you the number of minutes the difference was.

Using NSDateComponent is also one viable option.

You could make use of these functions:

#define DATE_COMPONENTS (NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit |  NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit)
#define CURRENT_CALENDAR [NSCalendar currentCalendar]

+ (NSDate* )date:(NSDate*)date ByAddingHours:(int)hours
{

    return [date dateByAddingTimeInterval:60*60*hours];
}


+ (NSDateComponents *)componentsForDate:(NSDate *)date 
{
    if (date!=nil)
    {
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];

    NSDateComponents *dayComponents =
    [gregorian components:DATE_COMPONENTS fromDate:date];

    return dayComponents;
    }

    return nil;
}



+(NSString *)timeFromNSDate:(NSDate *)date
{
    int hour=[self componentsForDate:date].hour;
    int minute=[self componentsForDate:date].minute;


    NSString *returnDateString=@"";
    if (hour <= 9 ) {
        returnDateString=[NSString stringWithFormat:@"0%d", hour];
    }

    else {
        returnDateString=[NSString stringWithFormat:@"%d", hour];
    }

    if (minute <= 9 ) {
        returnDateString= [returnDateString stringByAppendingFormat:@":%@", [NSString stringWithFormat:@"0%d", minute]];
    }

    else {
        returnDateString= [returnDateString stringByAppendingFormat:@":%@", [NSString stringWithFormat:@"%d", minute]];
    }

    NSLog(@"return date string: %@",returnDateString);

    return returnDateString;
}
Satheesh
  • 10,998
  • 6
  • 50
  • 93
  • The method above is taking NSDate and returning NSString while i have a mutableString named currentString. Converting it to NSDate will return NULL and that cannot be passed to the methods above of course. – Jessica Apr 20 '13 at 16:21
  • You could use NSDateFormatter to take date out of NSString. – Satheesh Apr 20 '13 at 17:13