3

How can I parse a string that represents a date and/or time using iPhone SDK if I do not know the format? I am building an application that will allow a range of possible dates and times to be used, and I don't want it to fail because the format was "01/01/2001" instead of "01-01-2001", etc. Time may or may not be included.

Is there any way to do this? I have tried using NSDateFormatter with date and time styles set to "NoStyle", and setLenient = YES, but it still fails to parse the simplest of strings: "1/22/2009 12:00:00 PM"

I have no way of knowing the format in advance, I need a method that will heuristically determine the format.

I am coming from a .NET background, where this is as simple as new DateTime(string_in_any_format); but I have no idea how to do this in Obj-C.

Dan Berlin
  • 45
  • 5

3 Answers3

5

Old post, but there are better ways to handle this that I found on other posts.

You can use a method like this:

  • First, try and parse the date in a couple of expected formats.
  • If that doesn't work, use NSDataDetector to try and find date information (reference: this SO post).

Here's a sample of code I used for this (I expected a couple date formats, but couldn't be certain that's the only date I'd ever see and didn't want to fail if possible):

// your date formats may vary, the OP might try "MM/dd/yyyy" and "MM-dd-yyyy", along with combos that include time info
NSArray *dateFormatsToTry = @[@"yyyy-MM-dd'T'HH:mmZZZZ", @"yyyy-MM-dd'T'HH:mm:ssZZZ"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];

for (NSString * format in dateFormatsToTry) {
    [dateFormatter setDateFormat:format];
    NSDate *date = [[[self class] sharedDateFormatter] dateFromString:dateString];
    if (date) {
        return date;
    }
}

// try and figure out the date if the all of the expected formats failed to
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeDate error:nil];
NSTextCheckingResult *result = [detector firstMatchInString:dateString options:0 range:NSMakeRange(0, [dateString length])];
if ([result resultType] == NSTextCheckingTypeDate) {
    NSDate * date = [result date];
    if (date) {
        return date;
    }
}

return [NSDate date]; // default to now :(
Community
  • 1
  • 1
manroe
  • 1,645
  • 20
  • 35
4

Unfortunately, NSDateFormatter on the iPhone isn't that smart. You need to give it a little guidance. When you set both the date and time styles to NoStyle it expects to see neither a date nor time. You'll need at least one of them set to some other style. You can do something like the following and it should work fine (it does for me).

NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterLongStyle];
[formatter setTimeStyle:NSDateFormatterNoStyle];
[formatter setLenient:YES];

NSDate * date = [formatter dateFromString:@"01-01/2001"];

NSLog(@"%@", date);
Cory Kilger
  • 13,034
  • 3
  • 33
  • 24
  • Thank you for your help. I could see that this would be a helpful thing to build, but since it doesn't seem to be provided, I will just build my own. For the time being I will just support limited formats. – Dan Berlin Aug 14 '10 at 22:04
0

How would your potential parser determine if 01/02/10 is jan 2, 2010; feb 1, 2010; or something entirely different? Bboth mm/dd/yy and dd/mm/yy are reasonable to expect, depending on where your customers are.

erikkallen
  • 33,800
  • 13
  • 85
  • 120
  • 1
    The parser can assume one format or the other based on locale, so it is acceptable to make that one assumption. This is the only acceptable assumption, however. – Dan Berlin Aug 15 '10 at 16:37
  • So basically what you're asking for is how to make the parser not make any difference between - and / ? – erikkallen Aug 15 '10 at 17:32