How to handle multiple date formats?

2019-01-28 18:30发布

When I get to the df.date() line below, the app crashes when a date with this format 2016-12-27 14:40:46 +0000 is used:

fatal error: unexpectedly found nil while unwrapping an Optional value

And I also see this:

error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

I have strings that can be in this format

12/27/2016

but sometimes in this format

2016-12-27 14:40:46 +0000      

Here is the code snippet that crashes on the above format:

let mydate = "12/27/2016" //this works but not the longer format
let df = DateFormatter()
df.dateFormat = "MM/dd/yyyy" //this is the format I want both dates to be in
newDate:Date = df.date(from: mydate)

How do I handle both formats using basically one function?

3条回答
萌系小妹纸
2楼-- · 2019-01-28 19:08

Check if the date string contains a slash and set the date format accordingly:

if mydate.contains("/") {
    df.dateFormat = "MM/dd/yyyy"
}  else {
    df.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
}
查看更多
走好不送
3楼-- · 2019-01-28 19:11

You can try an approach that is very clean in your code. You can add this extension:

extension DateFormatter {

    func dateFromMultipleFormats(fromString dateString: String) -> Date? {
        var formats: [String] = [
        "yyyy-MM-dd hh:mm:ss.SSSSxx",
        "yyyy-MM-dd hh:mm:ss.SSSxxx",
        "yyyy-MM-dd hh:mm:ss.SSxxxx",
        "yyyy-MM-dd hh:mm:ss.Sxxxxx",
        "yyyy-MM-dd hh:mm:ss"
        ]
    for format in formats {
        self.dateFormat = format
        if let date = self.date(from: dateString) {
                return date
            }
        }
        return nil
    }
}

then just try changing the formats array in the function to whatever formats you may need. Now just use your formatter like this:

if let myDate = dateFormatter.dateFromMultipleFormats(fromString: mydate) {
    print("success!")
} else {
    print("add another format for \(mydate)")
}
查看更多
Ridiculous、
4楼-- · 2019-01-28 19:17

I think the best way to do this is using two DateFormatters, one for iso8601 format and other for this short format.

(My code below uses an extension of DateFormatter, but you can use a method / helper / anything else with these two formatters).

Swift 3

extension DateFormatter {
    static let iso8601DateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar.current // Set the Calendar
        formatter.timeZone = TimeZone(secondsFromGMT: 0) // Set the timezone
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
        return formatter
    }()

    static let shortDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar.current // Set the Calendar
        formatter.timeZone = TimeZone(secondsFromGMT: 0) // Set the timezone
        formatter.dateFormat = "MM/dd/yyyy"
        return formatter
    }()

    static func date(string: String) -> Date? {
        if let iso8601Date = iso8601DateFormatter.date(from: string) {
            return iso8601Date
        } else if let shortDate = shortDateFormatter.date(from: string) {
            return shortDate
        } else {
            return nil
        }
    }
}
查看更多
登录 后发表回答