Reputation: 227
I am trying to convert UTC date time to local date time and below is my code.
func dateTimeStatus(date: String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy hh:mm:ss a"
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let dt = dateFormatter.date(from: date)
dateFormatter.timeZone = TimeZone.current
dateFormatter.dateFormat = "MM/dd/yy hh:mm:ss a"
return dateFormatter.string(from: dt!) // .string(from: dt!)
}
The above set of code works when the system(iPhone or iPad) language is set to English(India). If I change the language to Japanese then a exception is thrown as below.
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
at return
statement.
I very well know that I am messing up with dateFormatter due to which date is not recognised by the dateFormatter.date(from: date). Hence a nil value is assigned to the dt.
Any suggestions for generically using the date time format for all system language would be appreciable.
Upvotes: 2
Views: 6883
Reputation: 318774
Whenever you attempt to parse a fixed format date string, you need to set the formatter's locale to a special locale of en_US_POSIX
. This deals with many possible issues including the user's region and language, and the user's 12/24 hour settings.
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
Then reset it to the user's locale along with the time zone.
dateFormatter.locale = Locale.current
You should also avoid forced unwrapping in case you get an unexpected date string.
Updated code:
func dateTimeStatus(date: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy hh:mm:ss a"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
if let dt = dateFormatter.date(from: date) {
dateFormatter.locale = Locale.current
dateFormatter.timeZone = TimeZone.current
dateFormatter.dateFormat = "MM/dd/yy hh:mm:ss a"
return dateFormatter.string(from: dt)
} else {
return "Unknown date"
}
}
You should also consider using a date and time style instead of a fixed format when presenting a date/time to a user. This ensures the date is in a friendly format. In your case you have a real issue.
Let's say you get a result of "06/05/18 10:30:00 am".
What date is that? Depending on where you live that could be June 5, 2018. It could be May 6, 2018. It could be May 18, 2006. It's very ambiguous.
Better to use something like:
func dateTimeStatus(date: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yy hh:mm:ss a"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
if let dt = dateFormatter.date(from: date) {
let userFormatter = DateFormatter()
userFormatter.dateStyle = .medium // Set as desired
userFormatter.timeStyle = .medium // Set as desired
return userFormatter.string(from: dt)
} else {
return "Unknown date"
}
}
Upvotes: 6