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 setDat开发者_运维技巧eFormat:@"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?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
.
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.
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")
}
精彩评论