Swift Date Formats

In the wild world of 2019 SwiftUI development, lots of things aren't documented. One such thing I ran into recently was the usage of RelativeDateTimeFormatter in a Text view.

RelativeDateTimeFormatter is a new formatter which is available in iOS 13+ and macOS 10.15+. Though it's not documented at the time of writing (just like 14.6% of Foundation), there have been a fairamount of folks online writing about it. This formatter formats dates relative each other as well as relative DateComponents - its output looks like 'one minute ago' or 'two minutes from now'.

SwiftUI, date formatters, and string interpolation. SwiftUI declares a custom string interpolation (which is a new feature in Swift 5) called LocalizedStringKey.StringInterpolation (also undocumented at the time of writing, like 59.4% of SwiftUI) which allows you to write Text views with formatters like so. For the MTXML format, FTM SWIFT provides a set of XSD files for both types of FIN system messages (category 0 for FIN and GPA) and FIN financial messages (categories 1 through 9). These files can be integrated into the IBM® Integration Bus tooling to make it easier to use a message management routing node to route FIN messages. The Usage Guideline Editor allows the formalization of a field/element format as an MT Format. The MT format language is defined by SWIFT. It describes how a field is structure by specifying: which type of characters can be used in that field.

Most blog posts about RelativeDateTimeFormatter show its usage like this:

SwiftUI declares a custom string interpolation (which is a new feature in Swift 5) called LocalizedStringKey.StringInterpolation (also undocumented at the time of writing, like 59.4% of SwiftUI) which allows you to write Text views with formatters like so:

Let's assume I want to show the relative time from the Unix Epoch until now. I'll just write a Text the same way, right?

Unfortunately this doesn't work - the middle text doesn't show up:

Interesting

Swift Date From String

Swift Date FormatsSwift

There's also an error in the console!

As far as I can tell, the reason this happens is because RelativeDateTimeFormatter has a few different methods, with different signatures, for formatting its relative dates:

Only one of those matches the Formatter superclass definition that SwiftUI's string interpolation uses. I'm guessing that RelativeDateTimeFormatter's string(for:) method doesn't call into the same code that localizedString(from:) uses - it seems like string(for:) handles the Date case, but not the DateComponents case.

Hopefully this changes in a future version of iOS, but for now, we can solve the problem in a couple of ways:

Solution #1

Since what we want is the date relative to right now, and that's the default behavior of RelativeDateTimeFormatter, we can just pass in epochTime:

This gets us the result we want:

Note: if you want minutes, seconds, etc, set the formatter's dateTimeStyle and unitStyle

Also note: even though nothing at the surface level is calling localizedString, the string will be properly localized as long as you set the formatter's locale.

Solution #2

We can also ignore the custom string interpolation, and just call the formatter's localizedString:

Ios Date Formatter

🎉
Swift Date Formats

Either of the solutions above would work for this specific issue, though if you want to output the relative time between two dates (instead of between one date and now) with the formatter: string interpolation, looks like you're out of luck.

Sample code for this post is available on GitHub .