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
toString
- Converting
String
toNSDate
- Getting components of an
NSDate
- Setting components of an
NSDate
- Creating new
NSDate
instances fromNSDateComponent
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
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'.
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:
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
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
:
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 .