Home > Mobile >  Swift Why is DateFormatter working so strange and sometimes returns nil?
Swift Why is DateFormatter working so strange and sometimes returns nil?

Time:06-15

I am trying to set the default time of the DatePicker(Which only asks for Hour and Minute) to 7:00 using codes below:

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat =  "HH:mm"
    let date1 = dateFormatter.date(from: "07:00")
    datePicker1.date = date1!

and it works just fine on all of my devices and simulators, but I've got one crash report from my users that when unwrapping date1, it unexpectedly found nil. I can't reproduce the same error and my app works so fine when I'm testing. I don't know how to do fix the problem, neither reproducing it. What should I do?

Besides, when running the code in swift playground, I found a strange phenomenon.strange phenomenon Why is it happening? Why did the value of date1 change when I print it?

CodePudding user response:

You can easily opt to choose the datePicker in 12hr format by setting its local property.

For 24-Hour Format:

datePicker.local = Locale.init(identifier: "en_gb")   // en_gb is for British English, which prefers 24 hr format.

For 12-Hour Format:

datePicker.local = Locale.init(identifier: "en_us")   // en_us is for American English which prefers 12 hr format.

Extension to set the Date/time:

extension UIDatePicker {
    
    func setDate(from string: String, format: String, animated: Bool = true) {
        let formater = DateFormatter()
        formater.dateFormat = format
        let date = formater.date(from: string) ?? Date()  // Use default date in case of nil.
        setDate(date, animated: animated)
    }
}

Usage:

datePicker.setDate(from: "7:00", format: "HH:mm")

To check whether current device's formate is 12/24 Hour :

func is24Hour() -> Bool {
    let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!
    return dateFormat.firstIndex(of: "a") == nil
}

CodePudding user response:

I think the problem doesn't lie on DatePicker, but on String-Date conversion. Thanks to Kush Bhavsar, I've figured out a solution which sets locale of the DateFormatter to "en_gb". So you can write code like this:

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.init(identifier: "en_gb")
dateFormatter.dateFormat =  "HH:mm"
let date1 = dateFormatter.date(from: "07:00")
datePicker1.date = date1!

so it works fine on both 12Hrs and 24Hrs phone.

Alternatively, you can write an extension like this if you prefer 24Hrs mode as default when writing codes(like me):

extension DateFormatter{
    static func tf() -> DateFormatter{//Returns TwentyFour Hours mode DateFormatter
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: "en_gb")
        return dateFormatter
    }
}

Usage:

let dateFormatter = DateFormatter.tf()
dateFormatter.dateFormat =  "HH:mm"
let date1 = dateFormatter.date(from: "07:00")
datePicker1.date = date1!
  • Related