NSDateFormatter with 24 hour times

2019-01-08 21:54发布

问题:

I have a countdown timer which countsdown from the current date/time to a specific future date/time. It is working great except for one problem. I input the future date using NSDateFormatter and dateFromString. It doesn't seem to be able to accept any time (hour) over 12 though indicating it is not support 24 hour clock. Is there a way to enable 24 hour clock support or a workaround? Here is some of my code:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
NSDate *myDate = [df dateFromString:@"2010-03-14 15:00:00"];

Thanks

回答1:

NSDateFormatter follows the Unicode standard for date and time patterns. Use 'H' for the hour on a 24-hour clock:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myDate = [df dateFromString:@"2010-03-14 15:00:00"];


回答2:

I had the same problem and using HH worked only on some devices, like Roger also verified. In the end this was the solution that worked for me, I hope it works for others. Finding this answer was difficult, there are no forums with it, it was literally trial and error following the apple documentation.

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

    [dateFormatter setLocale:enUSPOSIXLocale];

    NSString *dateFormat = @"dd/MM/yyyy HH:mm"; //MM for month, mm for minutes

    [dateFormatter setDateFormat:dateFormat];
    [dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
    date = [dateFormatter dateFromString:string];


回答3:

My solution on Swift:

let formatter = NSDateFormatter()
var defIdentifer = formatter.locale.localeIdentifier
if !defIdentifer.hasSuffix("_POSIX") {
    defIdentifer = defIdentifer+"_POSIX"
    let locale = NSLocale(localeIdentifier: defIdentifer)
    formatter.locale = locale
}
formatter.dateFormat = "HH:mm"


回答4:

Taken from the Apple Technical Q&A on NSDateFormatters

Q: I'm using NSDateFormatter to parse an Internet-style date, but this fails for some users in some regions. I've set a specific date format string; shouldn't that force NSDateFormatter to work independently of the user's region settings?

A: No. While setting a date format string will appear to work for most users, it's not the right solution to this problem. There are many places where format strings behave in unexpected ways.

This is how I have done mine in Swift:

private let dateFormatter: NSDateFormatter = {
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    dateFormatter.timeZone = NSTimeZone.init(forSecondsFromGMT: 0)
    return dateFormatter
}()


回答5:

I had a similar problem recently, instead of HH, NSDateFormatter ignored hh, a(AM/PM Symbol) and G (cyclic era name) in my app.

And I was surprised to find that if I go to localization setting of my device and make some random choice, all the freaks are gone and the error cannot be produced again. Very weird.

Then I tested on simulator to do some study on it. There is my solution:

After you created the NSDateFormatter, explicitly set the locale property even you are using current locale, more importantly, DON'T use [NSLocale currentLocale], this one is bugged and can be somehow "overriden" by user setting, use systemLocale or explicitly create an NSLocale instance using a locale identifer.



回答6:

Objective C version of getting NSDate from 24-hour string when user has set 12 hour format on their iPhone without changing locale and setting timezone:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSString *localeId = dateFormatter.locale.localeIdentifier;
if (! [localeId hasSuffix:@"_POSIX"]) {
    localeId = [localeId stringByAppendingString:@"_POSIX"];
    dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:localeId];
}
dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH.mm.ss";

NSDate *date  = [dateFormatter dateFromString:dateText];