NSDateFormatter, am I doing something wrong or is this a bug?

后端 未结 8 979
-上瘾入骨i
-上瘾入骨i 2020-11-30 06:18

I\'m trying to print out the date in a certain format:

NSDate *today = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]         


        
相关标签:
8条回答
  • 2020-11-30 06:57

    Here's the explanation of the iPhone SDK bug (also still there in 3.1 beta SDK)

    First, a little background on the iPhone user interface. When iPhone users change their region format between, say, “United States” and “France”, the users’ “24-Hour Time” setting is automatically switched to the mode that is most prevalent in that region. In France, that would set 24-Hour Time to “ON”, and in the U.S., that would set it to “OFF”. The users can then manually override that setting and that’s where trouble starts.

    The problem comes from NSDateFormatter somehow “getting stuck” in the 12 or 24-hour time mode that the user has manually selected. So if a French user manually selects 12-hour mode, and the application requested NSDateFormatter to output time with the 24-hour format “HHmm”, it would actually receive time in a 12-hour format, e.g. “01:00 PM”, as if the application had instead requested “hhmm aa”. The reverse would happen if a US user manually selected 24-hour mode: outputting time with the 12-hour format “hhmm aa” would actually get you time in the 24-hour format instead, e.g. “17:00″.

    More details and a possible workaround can be found on this blog.

    0 讨论(0)
  • 2020-11-30 06:59

    For those finding this question who want to use NSDateFormatter to parse 24-hour time and are hitting this bug, using NSDateComponents to parse dates and times which have a known format sidesteps this issue:

    NSString *dateStr = @"2010-07-05";
    NSString *timeStr = @"13:30";
    
    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.year = [[dateStr substringToIndex:4] intValue];
    components.month = [[dateStr substringWithRange:NSMakeRange(5, 2)] intValue];
    components.day = [[dateStr substringFromIndex:8] intValue];
    components.hour = [[timeStr substringToIndex:2] intValue];
    components.minute = [[timeStr substringFromIndex:3] intValue];
    
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    NSDate *date = [calendar dateFromComponents:components];
    
    [components release];
    [calendar release];
    
    0 讨论(0)
  • 2020-11-30 07:06

    Setting locale on date formatter to en_US fixes the problem for me:

        NSDateFormatter * f = [[NSDateFormatter alloc] init];
        [f setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
        f.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
        f.calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
        f.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease];
    

    I'm not sure if adding the calendar is also needed, but this works well.

    0 讨论(0)
  • 2020-11-30 07:07

    The reason for this behaviour is Locale, It sets the correct Locale.

    Set the local of your NSDateFormatter to en_US_POSIX will fix this. It works for both 24-hour and 12 hour format.

    On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set. From apple doc

    Try this,

    NSDate *today = [[NSDate alloc] init];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
    [dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
    NSString *dateStr = [dateFormatter stringFromDate:today];
    
    0 讨论(0)
  • 2020-11-30 07:10

    This should also work (I am seeing some bizzare results though).

    -(NSString*)lowLevTime:(NSString*)stringFormat {
        char buffer[50];
        const char *format = [stringFormat UTF8String];
        time_t rawtime;
        struct tm * timeinfo;
        time(&rawtime);
        timeinfo = localtime(&rawtime);
        strftime(buffer, sizeof(buffer), format, timeinfo);
        return [NSString  stringWithCString:buffer encoding:NSASCIIStringEncoding];
    }
    
    0 讨论(0)
  • 2020-11-30 07:16

    Short answer: try [dateFormatter setDateFormat:@"yyyyMMddhhmmss"]; for 12 hour format (note the lowercase hh).

    It's been a frustrating topic because so many websites indicate to use HH for hours (including the official Apple documentation), but that sets it to 24 hour format, whereas hh uses 12 hour format. See http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns for more details.

    As a bonus, note that you can also use KK or kk for hour of the day format, which will likely be off by one.

    Update: I was recently looking at NSLocale (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSLocale_Class/Reference/Reference.html) and it would seem that you can use autoupdatingCurrentLocale to apply changes made from within the app to the Locale. The upshot of this is that even if the phone is set to use a 24 hour clock (like when you switched to France), you can make a 12/24 toggle for the app that won't impact any other apps on the phone, or require you to leave the app to make the change.

    0 讨论(0)
提交回复
热议问题