How to parse a date string into an NSDate object in iOS?

43,129

Solution 1

You don't need near as many single quotes as you have (only needed on non date/time characters), so change this:

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

To this:

[self.dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZ"];
...
self.currentQuestion.updated = [self.dateFormatter dateFromString:[self.currentParsedCharacterData stringByReplacingOccurrencesOfString:@":" withString:@"" options:0 range:NSMakeRange([self.currentParsedCharacterData length] – 5,5)]];

Documentation here: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1

Unicode Format Patterns: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns

Dealing with TimeZones with Colons (+00:00): http://petersteinberger.com/2010/05/nsdateformatter-and-0000-parsing/

Solution 2

It took me a while to find the simple answer for this. and there are a lot of solutions that involve bringing in extra third party code.

For those who are struggling with this now and are only supporting iOS 6 and above.

You can set the date formatter to

[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]

And this will properly handle the "-05:00" with the colon.

Solution 3

I was having the same problems with the colon at the end. Here's a function I used to normalize the date to make NSDate happy.

/**
 * Timezones are returned to us in the format +nn:nn
 * The date formatter currently does not support IS 8601 dates, so
 * we convert timezone from the format "+07:30" to "+0730" (removing the colon) which
 * can then be parsed properly.
 */
- (NSString *)applyTimezoneFixForDate:(NSString *)date {
    NSRange colonRange = [date rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@":"] options:NSBackwardsSearch];
    return [date stringByReplacingCharactersInRange:colonRange withString:@""];
}

Solution 4

The problem is the 'Z' at the end. The way you are writing it within quotes, your parser expects a literal character Z in your time string, and there isn't one. What you want is the Z formatting character without quotes, which indicates that your time string contains time zone information. Which it does, the -05:00 at the end of your string is the time zone.

Since you expect time zone information, setting the time zone in your date formatter is rather pointless. And check the link to the Unicode formatting patterns, that link contains the definitive information that you should trust above all answers you get here.

Solution 5

Solutions is to change :

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

To this notation :

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

i hope it will help you.

Share:
43,129

Related videos on Youtube

JohnRock
Author by

JohnRock

merge keep

Updated on September 06, 2020

Comments

  • JohnRock
    JohnRock over 3 years

    I am trying to parse a date string from xml into an NSDate object in an iPhone app

    I am aware this must have been asked before, however, I believe I have the right syntax, but it is not working. Is there a problem with my code?

    The date string I need to parse is:

    2011-01-21T12:26:47-05:00
    

    The code I am using to parse it is:

    self.dateFormatter = [[NSDateFormatter alloc] init];
        [self.dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
        [self.dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]];
        [self.dateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
    
    
    
    ... 
    
    else if([elementName isEqualToString:kUpdated]){
        self.currentQuestion.updated = [self.dateFormatter dateFromString:self.currentParsedCharacterData ];
    }
    

    Any help greatly appreciated. Thanks!

    **Based on the link reference from theChrisKent I fixed the problem like so:

    else if([elementName isEqualToString:kLastOnDeck]){
    
        NSString *dateStr = self.currentParsedCharacterData;
        // we need to strip out the single colon
        dateStr = [dateStr stringByReplacingOccurrencesOfString:@":" 
                                                     withString:@"" 
                                                        options:0 
                                                          range:NSMakeRange([dateStr length] - 5,5)];
    
    
    
    
        self.currentQuestion.lastOnDeck = [dateFormatter dateFromString:dateStr];
    
    }
    
  • JohnRock
    JohnRock about 13 years
    I found someone asking the same exact question, also with no answer: stackoverflow.com/questions/3561029/… They mention it could be a problem with the colon in the timezone?
  • theChrisKent
    theChrisKent about 13 years
    @JohnRock I've updated my answer with a solution and a link. Basically, the formatters aren't setup to deal with that colon, so you remove it prior to the parse.
  • JohnRock
    JohnRock about 13 years
    theChrisKent has saved me. Thanks a lot, the last link you provided explained how to solve this issue. Much Obliged!
  • JohnRock
    JohnRock about 13 years
    This looks to be a great function to solve the problem. THanks.
  • Srinivas G
    Srinivas G about 11 years
    It returned nil If the date string is 0000-00-00T00:00:00 +0530
  • Badre
    Badre about 11 years
    its logic :D, all time is 000000, no time :p
  • Juguang
    Juguang over 10 years
    Year 0 does not exist! Next year of BC1 is AD1 ;-)
  • Hot Licks
    Hot Licks over 10 years
    Note that the formatter standard now supports "ZZZZZ" for timezone with colon in it.
  • Cameron Lowell Palmer
    Cameron Lowell Palmer almost 9 years
    I believe your issue is Z.
  • ucangetit
    ucangetit almost 9 years
    For iOS 6 and above, using the "yyyy-MM-dd'T'HH:mm:ssZZZZZ" format is the better solution. please see my answer below.
  • BergQuester
    BergQuester over 6 years
    This answer needs to be updated. As of iOS 10 the system provided NSISO8601DateFormatter is available for this particular format.