0

I have the following code which is being called in cellForRowAtIndexPath for a UITableView.

self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateFormat:@"EEEE, dd MMM yyyy HH:mm:ss z"];

OLVisit *visit = [self.visits objectAtIndex:indexPath.row];
NSString *strVisitDate = [NSString stringWithFormat:@"%@", visit.olcreatedat];
NSDate *visitDate = [self.dateFormatter dateFromString:strVisitDate];
strVisitDate = [self.dateFormatter stringFromDate:visitDate];

The string returned from visit.olcreatedat is in the following format (as can be seen in the debugger screenshot below) "2013-04-09 11:55:25 +0000".

enter image description here

I get a nil NSDate value returned into visitDate.

Could somebody help me figure this out?

motionpotion
  • 2,656
  • 6
  • 42
  • 60
  • 2
    Maybe if you set the date format to match the format of the date you'd have better luck. – Hot Licks May 01 '13 at 20:32
  • 1
    possible duplicate of [How to parse a date string into an NSDate object in iOS?](http://stackoverflow.com/questions/4999396/how-to-parse-a-date-string-into-an-nsdate-object-in-ios) – Hot Licks May 01 '13 at 20:33
  • What is the type of `visit.olcreatedat`? Is it an `NSString`? If so, get rid of the call to `stringWithFormat:`. – rmaddy May 01 '13 at 20:41
  • @HotLicks that link also helps and I had previously read through it before posting but it does not solve the problem I have of getting the date formatted into the format of "EEEE, dd MMM yyyy HH:mm:ss z" – motionpotion May 01 '13 at 20:47
  • @rmaddy visit.olcreatedat is in my visit entity defined as an Date data type. I am pulling back this field from core data in the scenario above. – motionpotion May 01 '13 at 20:49
  • @motionpotion Is it's already an `NSDate`, then why do you convert to a string and then back to another date? All you need to do is call `[self.dateFormatter stringFromDate:visit.olcreatedat];` and you are done. Get rid of `strVisitDate` and `visitDate`. – rmaddy May 01 '13 at 20:54

2 Answers2

2

UPDATE: As pointed out by @rmaddy, there was a misunderstanding about what visit.olcreatedat was. This first answer is based on the assumption that visit.olcreatedat is an NSDate. For an answer that assumes that visit.olcreatedat is an NSString containing a formatted date, read the second part of this answer.

visit.olcreatedat is an NSDate

- (void)viewDidLoad {
    [super viewDidLoad];

    // Alloc the date formatter in a method that gets run only when the controller appears, and not during scroll operations or UI updates.
    self.outputDateFormatter = [[NSDateFormatter alloc] init];
    [self.outputDateFormatter setDateFormat:@"EEEE, dd MMM yyyy HH:mm:ss z"];
}


- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath: {
   // dequeue or create the cell... 
   // ...
   // ...

   OLVisit *visit = [self.visits objectAtIndex:indexPath.row];
   NSString * strVisitDate = [self.outputDateFormatter stringFromDate:visit.olcreatedat];

   // Here you can assign the string to the right UILabel
   cell.textLabel.text = strVisitDate;

   return cell;
}

visit.olcreatedat is an NSString

Do you want to convert the visit.olcreatedat to the format EEEE, dd MMM yyyy HH:mm:ss z? If so, let's go through each step.

First, you need to convert the visit.olcreatedat string (stored in strVisitDate) to an actual NSDate object, visitDate. So to make this step work, you need an NSDateFormatter that accepts the visit.olcreatedat format: yyyy-MM-dd HH:mm:ss z.

Then, you want to convert the obtained visitDate NSDate to the format you like, so you need another NSDateFormatter, with the format EEEE, dd MMM yyyy HH:mm:ss z.

- (void)viewDidLoad {
    [super viewDidLoad];

    // Alloc the date formatter in a method that gets run only when the controller appears, and not during scroll operations or UI updates.
    self.inputDateFormatter = [[NSDateFormatter alloc] init];
    [self.inputDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
    self.outputDateFormatter = [[NSDateFormatter alloc] init];
    [self.outputDateFormatter setDateFormat:@"EEEE, dd MMM yyyy HH:mm:ss z"];
}

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath: {
   // dequeue or create the cell... 
   // ...
   // ...

   OLVisit *visit = [self.visits objectAtIndex:indexPath.row];
   NSString *strVisitDate = visit.olcreatedat;
   NSDate *visitDate = [self.inputDateFormatter dateFromString:strVisitDate];
   strVisitDate = [self.outputDateFormatter stringFromDate:visitDate];

   // Here you can assign the string to the right UILabel
   cell.textLabel.text = strVisitDate;

   return cell;
}
Alessandro Orrù
  • 3,443
  • 20
  • 24
  • Exactly what I was trying to do. Thank you so much for all responses. – motionpotion May 01 '13 at 20:56
  • Just a side note: avoid to allocate many NSDateFormatter or to change their date format if you need fast responses, since it is an heavy operation to do. If you do that in `tableView:cellForRowAtIndexPath:` for example you could have sluggy performances. In that case, use one or more static NSDateFormatter instead, or reuse the same NSDateFormatter stored in a property, as you are doing here. – Alessandro Orrù May 01 '13 at 21:01
  • thanks for the extra tip. It looks like I am doing it correctly then by setting NSDateFormatter as a property on my ViewController. – motionpotion May 01 '13 at 21:19
  • Yes, but are you assigning the date formatter to that property in viewDidLoad or init method? – Alessandro Orrù May 01 '13 at 21:22
  • no I am assigning the date formatter to the property each time I need to use it ... in this case in the cellForRowAtIndexPath. I am using it elsewhere in other methods in the View controller but each time I set it. I presume you mean that I should set it once in the init or viewDidLoad and then reuse it elsewhere without setting it again. – motionpotion May 01 '13 at 21:37
  • I see your example now. Thanks again for all your help. – motionpotion May 01 '13 at 21:38
  • Exactly, you should just set it once in the lifetime of the controller . You're welcome. – Alessandro Orrù May 01 '13 at 21:40
  • Much of this code is pointless since `visit.olcreatedat` is already an `NSDate` object. There is no reason to convert the `NSDate` to an `NSString` using `stringWithFormat:`, then to convert that string back to a new `NSDate` (especially since the format of the string is not documented and has changed in the past). – rmaddy May 01 '13 at 22:04
  • @rmaddy I don't know if olcreatedat is an NSDate or a NSString containing a formatted date, @motionpotion didn't specified that. I assumed that it is an NSString. If it is an NSDate you are absolutely right, and obviously @motionpotion just needs the outputDateFormatter, using just `[self.outputDateFormatter stringFromDate:visit.olcreatedat]` – Alessandro Orrù May 01 '13 at 22:11
  • The OP mentioned that it's a date in the reply to my question about what type it was. See the 5th comment below the question. – rmaddy May 01 '13 at 22:12
  • Oh ok, it has been written while I was writing my answer or after that :) I update my answer now, to reflect this. Thank you – Alessandro Orrù May 01 '13 at 22:15
1

change your date format and replace code :

Old :

[self.dateFormatter setDateFormat:@"EEEE, dd MMM yyyy HH:mm:ss z"];

New :

[self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];

This is because you are using different date format while strVisitDate date format is "yyyy-MM-dd HH:mm:ss z". So you need to set the same format.

Edit :

Replace your code with this.

self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];

OLVisit *visit = [self.visits objectAtIndex:indexPath.row];
NSString *strVisitDate = [NSString stringWithFormat:@"%@", visit.olcreatedat];

NSDate *visitDate = [dateFormatter dateFromString:strVisitDate];
strVisitDate = [dateFormatter stringFromDate:visitDate];

//Here you can set any date Format as per your need

[dateFormatter setDateFormat:@"EEEE, dd MMM yyyy HH:mm:ss z"];
strVisitDate = [dateFormatter stringFromDate:visitDate];

Hope it helps you.

Nishant Tyagi
  • 9,893
  • 3
  • 40
  • 61
  • That helped a lot and it works but how do I then get the date into the format that I need "EEEE, dd MM yyyy HH:mm:ss z". I need it to output to a UILabel in that specific format. – motionpotion May 01 '13 at 20:45
  • @NishantTyagi, just a side note: changing the dateFormat is an heavy operation. If you do that in `tableView:cellForRowAtIndexPath:` for example you could have sluggy scroll performance, so it is better to have a separate NSDateFormatter instance with the right format. – Alessandro Orrù May 01 '13 at 21:03
  • @AlessandroOrrù do you have an example of where I should perform this date formatting outside of cellForRowAtIndexPath? I am currently performing this in this method. I am only returning a few cells at the moment but will eventually be returning thousands potentially depending on filter selected by users. – motionpotion May 01 '13 at 21:12
  • @motionpotion I have updated my answer with an example, look at it – Alessandro Orrù May 01 '13 at 21:17