The 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.
import Foundation
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.
import Foundation
// Create String
let string = "01/02/2016"
We create a DateFormatter
instance to convert the string to a date.
import Foundation
// Create String
let string = "01/02/2016"
// Create Date Formatter
let dateFormatter = DateFormatter()
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.
import Foundation
// Create String
let string = "01/02/2016"
// Create Date Formatter
let dateFormatter = DateFormatter()
// Convert String to Date
dateFormatter.date(from: string)
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.
import Foundation
// Create String
let string = "01/02/2016"
// Create Date Formatter
let dateFormatter = DateFormatter()
// Set Date Format
dateFormatter.dateFormat = "dd/MM/yy"
// Convert String to Date
dateFormatter.date(from: string)
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.
"dd/MM/yy" // 29/10/20
"y, M d" // 2020, 10 29
"YY, MMM d" // 20, Oct 29
"YY, MMM d, hh:mm" // 20, Oct 29, 02:18
"YY, MMM d, HH:mm:ss" // 20, Oct 29, 14:18:31
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?
import Foundation
// Create String
let string = "12/13/2020"
// Create Date Formatter
let dateFormatter = DateFormatter()
// Set Date Format
dateFormatter.dateFormat = "dd/MM/yy"
// Convert String to Date
dateFormatter.date(from: string) // nil
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.
import Foundation
// Create String
let string = " 29 October 2019 20:15:55 +0200"
// Create Date Formatter
let dateFormatter = DateFormatter()
// Set Date Format
dateFormatter.dateFormat = "dd MMM yyyy HH:mm:ss Z"
// Convert String to Date
dateFormatter.date(from: string) // Oct 29, 2019 at 7:15 PM
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.