Swift Date Formats

When parsing ISO8601 internet dates, always use ISO8601DateFormatter; If you can't because your API format doesn't fit ISO8601 and you still absolutely need to use a custom dateFormat, then be sure to also set your dateFormatter.locale to the special value Locale(identifier: 'enUSPOSIX'). Formatting user-visible dates for your UI. The JSON date format for a Date got the value of 57786402. This almost looks like a unix epoch timestamp, but if you put it into an online converter it’ll come out as @ 4:06pm. It’s not a unix timestamp. It’s actually using a different reference date – 2001 instead of 1970.

Working with NSDate, NSDateFormatter, and NSDateComponents can be a little convoluted, so I’ve created myself a cheat sheet that will be updated as I discover new tips and tricks in this realm.

The new cheat sheet can be found over at GitHub in the form of an Xcode Playground:

  • Swift Dates Cheat Sheet Playground

Topics that are included in the Playground are as follows:

  • Getting today’s date
  • Converting NSDate to String
  • Converting String to NSDate
  • Getting components of an NSDate
  • Setting components of an NSDate
  • Creating new NSDate instances from NSDateComponent instances

The best way to view this cheat sheet is by downloading the playground from GitHub, but here’s a straight copy-paste from the repo in case you just want to copy and paste it into a playground of your own from here:

  • Parse PFCloud – “JSON text did not start with array or object”
  • Working with Swift: Adopt a Protocol or Pass a Function?
  • Listing Calendar Events with Event Kit and Swift
  • Adding Buttons to the Navigation Bar with Storyboards
  • FIX – Query in Parse Cloud Code Returns Unauthorized Error
Please enable JavaScript to view the comments powered by Disqus.comments powered by DisqusDate

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'.

Swift Date Formats

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?

Swift Date Formatter Formats

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

Swift
Interesting

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:

Swift Date Formats

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

Formats

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

🎉

Swift Parse Date From String

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.

Swiftui Format Date

Sample code for this post is available on GitHub .