I've extensivley tested this over the past two days. I tried timelines spanning one day, with:
72 entries, every 20 minutes
36 entries, every 40 minutes
24 entries, every hour
12 entries, every 2 hours
6 entries, every 4 hours
3 entries, every 8 hours
2 entries, every 12 hours
In every case, the policy is .atEnd, and in every case the timeline is not refreshed when it's supposed to be, which causes the widget to display the wrong timer values.
Due to the inflexibility of Text(date, style: .timer), I need to write code that calculates the correct timer value but shows less than a day. For example, if it's 11am today and the event date is tomorrow at noon, there are 25 hours between the two dates and the standard .timer would show 25:00:00, which is not what I want. So, I calculate the next occurrence of noon, and the widget shows "1 day" with a timer of "1:00:00".
Every timeline with a refresh policy of .atEnd caues the countdown timer to show the wrong values.
I've got it logging to a file, and I can see that the countdown dates are completely correct in every case. The widget is never refreshed at the right time, so the timers always show the wrong values.
The only way I've managed to get this to work is to have a timeline with one entry, and a refresh policy of .after(), i.e.
let date = Date()
let refreshDate = Calendar.autoupdatingCurrent.date(byAdding: .minute, value: 30, to: date)!
Timeline(entries: entries, policy: .after(refreshDate))
There is clearly something wrong with .atEnd.