How to format a Date in iOS 15 and macOS 12
During WWDC 2021, Apple introduced the new APIs that make date formatting a lot easier. Before iOS 15, we had to create a DateFormatter
and later use it to convert a Date into a String:
static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateStyle = .medium
formatter.timeStyle = .medium
return formatter
}()
let now = Date.now
let dateString = dateFormatter.string(from: now)
// Oct 21, 2020 at 7:48 AM
From iOS 15, we can condense the code above to just two lines:
let now = Date.now
let dateString = now.formatted()
// 10/21/2020, 7:48 AM
By default, the formatted()
method will use a sensible default format. What's cool is that it will respect the user's preferences. For example, for October 21st, 2020 at 07:48 in the US region, we will get 10/21/2020, 7:48 AM
, but in Poland, we will have 21/10/2020 07:48
.
Of course, we can adjust the formatting to our needs by customizing the date and time styles separately:
let now = Date.now
let dateString = now.formatted(date: .long, time: .standard)
// October 21, 2020, 7:48:43 AM
And we can also completely omit the part we don't need:
let onlyDate = now.formatted(date: .numeric, time: .omitted)
// 10/21/2020
let onlyTime = now.formatted(date: .omitted, time: .shortened)
// 7:48 AM
Here is the list of currently available DateStyle
s:
Name | Example |
---|---|
omited | |
numeric | 10/21/2020 |
abbreviated | Oct 21, 2010 |
long | October 21, 2020 |
complete | Wednesday, October 21, 2020 |
And TimeStyle
s:
Name | Example |
---|---|
omited | |
shortened |
04:29 PM or 16:29 |
standard |
4:29:24 PM or 16:29:24 |
complete |
4:29:24 PM PDT or 16:29:24 GMT |
If the built-in styles are not suitable, we can define a custom format:
let now = Date.now
let dateString = now.formatted(.dateTime.year().month(.wide).day(.twoDigits).weekday().hour(.twoDigitsNoAMPM).minute(.defaultDigits))
// Wed, October 21, 2020, 07:48
Using this method, we can select and customize the date or time components we need. The order of components does not matter as the formatted()
method will adjust the output to the user's locale. Beside the .dateTime
style, Apple also provided the .iso8601
style:
let now = Date.now
let dateString = now.formatted(.iso8601)
// 20201021T074843Z
let dateString = now.formatted(.iso8601.year().month().day().dateSeparator(.dash).dateTimeSeparator(.space).time(includingFractionalSeconds: false) .timeSeparator(.colon))
// 2020-10-21 07:48:43
If we need our custom style, we can do this by creating a formatter that conforms to the FormatStyle
protocol:
struct BrackedDateTimeStyle: FormatStyle {
typealias FormatInput = Date
typealias FormatOutput = String
func format(_ value: Self.FormatInput) -> Self.FormatOutput {
return "[\(value)]"
}
}
let now = Date.now
let dateString = now.formatted(BrackedDateTimeStyle())
// [2020-10-21 07:48:43 +0000]
We can also add an extension to the FormatStyle
to make usage of our custom format more similar to Apple's API:
extension FormatStyle where Self == BrackedDateTimeStyle {
static var brackedDateTime: BrackedDateTimeStyle {
BrackedDateTimeStyle()
}
}
let now = Date.now
let dateString = now.formatted(.brackedDateTime)
That's it. The new Date formatting APIs will not replace the good old DateFormatter
. But in most cases, it's going to make our life easier.
If you want to know how to convert a String into a Date, check out my other article: