HeikoG
HeikoG

Reputation: 1813

NSDateFormatter dateFrom String with era

I am trying to parse dates that only consist of years like 145 or 123 BC into NSDate Objects - with not much success so far.

NSDateFormatter f = [[NSDateFormatter alloc]init];
[f setTimeZone:[NSTimeZone systemTimeZone]];
[f setFormatterBehavior:NSDateFormatterBehaviorDefault];
[f setDateFormat:@"y GG"];
date = [f dateFromString:yearString];

yearString contains e.g. 145 or 123 BC

The results are:
I get nil if I specify the era (GG) in the dateFormat.
If I just specify the year (y) in setDateFormat and the year I parse is 145 I get a date, but it is actually 1 hour before 145.

Two questions:
1. What is the proper way to parse years with era suffixes into NSStrings? 2. Why do I get the hour difference?

Upvotes: 1

Views: 415

Answers (3)

Grimxn
Grimxn

Reputation: 22497

Just came across this problem myself. @OleBergmann's answer to the second part of your question is correct, but although @bosmac's answer to the main part of your question is technically right, it's not very helpful.

Here's what I did...

func laxDate(str: String) -> Date? {
    let strictDF = DateFormatter()
    strictDF.dateFormat = "yyyy GG"
    let laxDF = DateFormatter()
    laxDF.dateFormat = "yyyy"

    if let d = strictDF.date(from: str) {
        return d
    } else if let d = laxDF.date(from: str) {
        return d
    } else {
        return nil
    }
}

print(String(describing: laxDate(str: "1901"))) // "Optional("1901-01-01 00:00:00 +0000")\n"
print(String(describing: laxDate(str: "10 BC"))) // "Optional("-0009-01-01 00:01:15 +0000")\n"

Or, more tersely...

func laxDate(str: String) -> Date? {
    func df(_ f: String) -> Date? {
        let df = DateFormatter()
        df.dateFormat = f
        return df.date(from: str)
    }

    return df("yyyy GG") ?? df("yyyy")
}

Upvotes: 1

bosmacs
bosmacs

Reputation: 7483

You'll get nil from the formatter if you don't include an era suffix, as is the case for '145'. Make it '145 AD', and I think you'll find it works. The date format components aren't optional — you have to match the whole pattern.

Upvotes: 1

Ole Begemann
Ole Begemann

Reputation: 135548

how come the hour difference?

Your time zone is probably GMT+1. So you're not actually getting a date one hour earlier but (because your date formatter is set to your time zone), you are parsing the date as 145-01-01 00:00 +0100. When you now output the date with -[NSDate description], it will give you the equivalent point in time in GMT, which is 144-12-31 23:00 +0000.

Upvotes: 2

Related Questions