+3  A: 

I've had this problem also, I'm not sure if it's a API bug within Apple's code, or my lack of understanding, but I've worked around it by using hour offsets in my date strings.

If you change the code in your example to:

NSDateFormatter* df = [[NSDateFormatter alloc]init];
[df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
NSString* str = @"2009-08-11T06:00:00.000-0700";   // NOTE -0700 is the only change
NSDate* date = [df dateFromString:str];

It will now parse the date string. Of course the -0700 hours is my offset, you'd have to change it to yours. Hope this helps.

NWCoder
In your example, the change in -0700 is not only 7 in place of 0 but also removing of trailing Z. Did you investigate that also?
mouviciel
Yes, the Z is an alternate form of -0000, Greenwich Mean.It's in RFC 3339 (I just skimmed it though, it might need perusing.)http://www.ietf.org/rfc/rfc3339.txt
NWCoder
This approach is simple enough, but in my particular situation I can't control which format I get the date strings in, and the only way they're provided is in zulu time (with a `Z`). I'll look into doing a string replace though, replacing the `Z` with `-0000` beforehand, and if it works out, I'll post the code and mark this as the answer. Thanks!
Eric Freese
Ok, I got it fixed. Here's the pertinent line: `[df dateFromString:[str stringByReplacingOccurrencesOfString:@"Z" withString:@"-0000"]]`
Eric Freese
+1  A: 

I think you need to put single quotes around the Z in the format string, because the Z actually means something to the formatter and you want it to represent a literal character instead.

    [df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
Charles Gamble
Yup, it's exactly the same as the T field which you're quoting.
AlBlue
That would work, except when the Z is parsed as a literal, the date loses offset information, and so is ambiguous, and therefore interpreted to be local time.For example, if the string to parse was `2009-08-11T06:00:00.000Z` (6:00 zulu time) it would be interpreted as 6:00 local time, and an incorrect offset would then be applied. It would then be parsed as `2009-08-11T06:00:00.000-600` (12:00 zulu time) with the offset depending on the user's offset. You can see how this would be incorrect.I'll work on a workaround, possibly replacing the Z with -0000 prior to parsing or something.
Eric Freese
A: 

this may help you.. the "Z" is a literal for the time zone code. try using "o" (the letter, not zero). The literal "o" means UTC offset. I ran into this a while back, I hope this helped you.

Terence F
OK, i think that "o" is for cold fusion.. I found this info:"z" With DateTime values, represents the signed offset of the local operating system's time zone from Coordinated Universal Time (UTC), measured in hours. (e.g. +6) "zz" As z but with leadin zero (e.g. +06) "zzz" With DateTime values, represents the signed offset of the local operating system's time zone from UTC, measured in hours and minutes. (e.g. +06:00) -Terence F
Terence F
A: 
-(NSDate*)dateFromZulu:(NSString*)str {
    if (str == nil) {
        NSLog(@"Error getting date");
        return [NSDate date];
    }

    NSDateFormatter *f = [[NSDateFormatter alloc] init];
    [f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss Z"];
    NSDate *ret = [f dateFromString:[str stringByReplacingOccurrencesOfString:@"Z" withString:@" +0000"]];
    [f release];

    if (ret == nil) {
        ret = [NSDate date];
        NSLog(@"Error formatting date (%@)",str);       
    }   
    return ret;     
}
valexa
A: 

It's been almost a year since Eric's "fix" post. Just confirming that the substitution hack is still necessary for iOS 4.0.x.

Chuck Han