Download Your
Swift Date Formatting. Tag: swift,nsdateformatter. This one has me perplexed. I'm trying to pull a date string from a button and format is as a date to be store. Since the date calculation occurs here, By setting the minimum date in the calculation, we prevent and catch all backwards dates, and reset them to the current date in one statement. The Whole Code // // ViewController.swift // SwiftDatePickerDemo // // Created by Steven Lipton on 9/21/14.
Free Copy ofThe Missing Manual
for Swift Development
The Guide I Wish I Had When I Started Out
Join 20,000+ Developers Learning About Swift Development
Download Your Free CopyThe Foundation framework makes it painless to convert a string to a date, but there are a few pitfalls you need to watch out for. The class we use to convert a string to a date in Swift is DateFormatter
(or NSDateFormatter
if you are using Objective-C). I encourage you to follow along with me. Fire up Xcode and create a playground.
As I mentioned in the introduction, the DateFormatter
class is defined in the Foundation framework. This means we add an import statement for Foundation at the top of the playground.
Let's define the string we plan to convert to a Date
object. We start simple. I show you a more advanced example later in this post.
We create a DateFormatter
instance to convert the string to a date.
To convert the string to a date, we pass it to the date(from:)
method of the DateFormatter
class. Let's give that a try.
The method seems to work fine since we don't see any errors or warnings. The problem is that it returns nil
. Something is missing.
What is missing isn't too surprising. We passed a string to the date formatter's date(from:)
method without specifying the date format of the string. The DateFormatter
is powerful, but it isn't magical. It cannot infer the date format of the string. That is something we need to do. Let's set the dateFormat
property of the DateFormatter
instance and give it another try.
This looks much better.
The dateFormat
property is of type String
. The value you assign to the dateFormat
property needs to conform to UTS or Unicode Technical Standard. The format is quite simple. Here are a few examples.
Pitfalls
You always need to be careful when using the date(from:)
method of the DateFormatter
class. If the string you pass to the date formatter doesn't match the date format of the date formatter, then date(from:)
returns nil
. Take a look at this example. Can you spot the mistake?
The date format of the string that is passed to date(from:)
method is MM/dd/yy
while the dateFormat
property has a value of dd/MM/yy
. In the eyes of the date formatter, the string that is passed to the date(from:)
method is invalid.
This means that you should never forced unwrap the value returned by the date(from:)
method. The return type is of type String?
, an optional. There is a valid reason for that.
A More Complex Example
The DateFormatter
class supports more complex date formats than the one we explored earlier. Take a look at this example. It includes the time and the time zone.
More to Explore
I encourage you to explore the documentation of DateFormatter
to explore the other options this class has to offer. We only scratched the surface in this post.
Swift Date Formatter
The Missing Manualfor Swift Development
The Guide I Wish I Had When I Started Out
Join 20,000+ Developers Learning About Swift Development
Download Your Free CopyIn 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 Format
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:
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.
Swift Parse Date From String
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:
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
:
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 .