VoiceOver times read out as numbers

We format times in a localized way using the DateFormatter APIs.


DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .short)


However if the result of this localization is say "22:00" VoiceOver just reads this out as "22". The VoiceOver user is given no indication that this numeric value is a time of the day.


I've read online that one approach is to use DateComponentsFormatter and the spellOut unitsStyle e.g.


let hourComponents = Calendar.current.dateComponents([.hour, .minute], from: date)
cell.accessibilityLabel = DateComponentsFormatter.localizedString(from: hourComponents, unitsStyle: .spellOut)


But again for a time "22:00" this reads out "22 hours". Sure if gives more context that this is related to time but it doesn't really indicate it is a time of the day i.e. it could be an interval (22 hours until something happens).


We've trawled through the Apple documenation but we can't find anything that covers this.


The best possible workaround we've found would be to force the accessibility label to be read out in 12 hour time i.e.


let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm")
accessibilityLabel =dateFormatter.string(from: date)

that way it is clear to the user that it is a time of the day. Although this approach has the downside that ignores the user's preference of a 24 hour or 12 hour time display.


The VoiceOver readout is handled perfectly in the Calendar app. It reads out "10 o'clock" and "22 hundred hours" in English and it is fully localized so for example it reads out "midi" for 12:00pm in French. It is possible that this is being done with private APIs though.


So my question is, what is the recommended approach for formatting times for VoiceOver?

What does VoiceOver read out in similar situations in Apple’s built-in apps?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Apple’s built-in apps handle this well. For example in the UK English locale, 24 hour display the Calendar app and the Clock read out “17:00” as “seventeen hundred hours. Another really good localisation example. In French language “12:00” is read out as “midi” the French for midday. This a very mature localisation which we would like to use in our apps but I can’t find any API that produces this result.

Apple’s built-in apps handle this well.

Hmmm. That’s good to hear, but it does continue the mystery as to how you achieve this functionality yourself. I had a good look at this today and, like you, struck out )-: At this point my recommendation is that you open a DTS tech support incident to get one-on-one help from our accessibility specialist.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Did you end up filing a bug about this? If so, what was the bug number?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ah yes I did. Forgive me for not getting back to you.


The bug ID is FB7380536

To summarize at time of writing there is no API that results in the same behaviour as native iOS Calendar and Clock apps. Furthermore there is no official recommended approach to this. Personally we will go with a solution where we always use 12 hour representations of times when read out for VoiceOver so that the context provided by "am/pm" read out is always available.

It looks like this is still an unresolved issue?

An acceptable solution would be to be able to do something like this:

someLabel.attributedText = NSAttributedString(string: "John Doe 1861-1938", attributes: [.numbersAreDateTime: true])

Here is a bug id FB9835553

VoiceOver times read out as numbers
 
 
Q