Post marked as solved
Post marked as solved with 4 replies, 1,305 views
I’ve been trying to debug a seemingly random issue that involves dates, timezones, formatters and locales. I wanted to make sure I got my basics right.
This I a test that passes “locally” as well as on a second computer but failed on a third. It should come down to this code once I strip away all the noise.
func testExample() throws {
//formatter to create date from string
let DateFormatterSecondsFromGmT = DateFormatter()
//notice how the order is different to the other formatter
DateFormatterSecondsFromGmT.dateFormat = "dd/MM/yyyy HH:mm" //format first
DateFormatterSecondsFromGmT.timeZone = TimeZone(secondsFromGMT: 0)
DateFormatterSecondsFromGmT.locale = Locale(identifier: "en_GB") //locale second
let string = "08/03/2023 12:10"
//date the test failed (approx.): 21 Apr 2023, 11:20:32
let date = DateFormatterSecondsFromGmT.date(from: string) ?? Date()
//formatter to create string from date
let DateFormatterUTC = DateFormatter()
DateFormatterUTC.timeZone = TimeZone(identifier: "UTC")
DateFormatterUTC.locale = Locale(identifier: "en_GB")
DateFormatterUTC.dateFormat = "HH:mm"
let actual = DateFormatterUTC.string(from: date) //On the computer that failed, this date was at 17:10 (i.e. off by 5 hours)
let expected = "12:10"
//One case where actual was 17:10 and expected 12:10.
XCTAssertEqual(actual, expected)
}
According to the Technical Q&A QA1480 NSDateFormatter and Internet Dates, when using a fixed-format date "you should first set the locale of the date formatter to something appropriate for your fixed format. In most cases the best locale to choose is 'en_US_POSIX'".
Based on the TN, "On iOS, the user can override the default AM/PM versus 24-hour time setting, which causes NSDateFormatter to rewrite the format string you set". Emphasis mine.
AFAIK the DateFormatter does not log a warning so I am not sure exactly what is the underlying cause for the test to fail.
Also, It’s not immediately obvious to me looking at the code what could be going wrong, given that both formatters have a fixed locale (and for what is worth timezone) which leads me to believe the DateFormatter did not rewrite the format string set.
On that note. I understand that setting the TimeZone to the DateFormatter will take that into account when formatting a Date to a String. Does setting the Timezone also play a role when converting a String to a Date? If so, how?
Ideally, if possible, would be good for me to understand how the test ended up failing. In other words, how can I reproduce the failure which should then give me a clue into what is wrong and coming up with a solution to the root cause.