How to create a custom TimeDataSource?

Hello. I am working with the iOS 18b8 and Xcode 16b6 betas, updating a Live Activity Widget to adopt the new FormatStyle variants of the SwiftUI Text views.

We used to use:

Text(workoutStartDate, style: .relative)

and it seems with iOS 18 we can replace it with:

Text(workoutStartDate, format: .relative(presentation: .numeric, unitsStyle: .wide))

The former code would auto-increment, allowing a user to look at their Live Activity and see the duration of their workout so far ticking by. The new code does provide a nice relative duration string, but it doesn't auto-increment in the Live Activity's View – I need that functionality.

I also updated other Texts in the Live Activity's View to adopt the .timer and .stopwatch FormatStyles. Those auto-increment and update no problem – once I realized I needed to provide a TimeDataSource<Date>.currentDate and not a simple Date.

But in this .relative case, there is no auto-incrementing, and I'm guessing it may be due to providing a Date (workoutStartDate) and not a TimeDataSource<Date> as TimeDataSource seems to be the magic to make the Text auto-increment (or it's possible this format simply doesn't support auto-increment? bummer if so since the prior way did).

How can I have a TimeDataSource<Date> that vends my arbitrary date (workoutStartDate)?

I dug around, didn't find anything, but I wouldn't be surprised if I was overlooking something.

PS: I have tried other approaches to solve this, such as simply using a .timer or .stopwatch format. That would change the under experience under iOS 18, and we think degrade it (the relative textual representation is nicer and provides distinction from the .timer also in the same View). We could keep the former approach, despite the minor layout issues under iOS 18. I have considered additional approaches as well – and am totally open to more! Here tho, I am truly curious how one might provide a custom TimeDataSource anchored at a date we provide (perhaps dynamically). Thank you.

I've been testing TimeDataSource in a similar attempt to get the Text view to update within a LiveActivity. From what I've found so far, you would be able to use something like this to reference your workoutStartDate:

Text(TimeDataSource<Date>.durationOffset(to: workoutStartDate), format: .units(allowed: [.hours, .minutes], width: .narrow, fractionalPart: .hide(rounded: .down)))

This creates an updating Duration based on the difference between the current time and the offset date and will work within a LiveActivity view (mostly)**.

This formatting displays a timer that counts up from your workoutStartDate in Xm format. When reaching an hour, it would shift to Xh and subsequently Xh Xm.

There's been a helpful resource created here that outlines FormatStyle options:

https://goshdarnformatstyle.com/duration-styles/

**Within a regular app view, the timer value updates as expected...at the top of a new minute. However, I notice that the values seem to update inconsistently within a LiveActivity view like the Dynamic Island. If anyone has a fix for that, I'd love to see it.

How to create a custom TimeDataSource?
 
 
Q