extension Date {
func string(formatter: DateFormatter) -> String {
return formatter.string(from: self)
}
}
extension DateFormatter {
static var shortDateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .short
return formatter
}
static var longDateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}
static var customDateWithDashFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}
}
let date = Date()
print(date.string(formatter: .shortDateFormatter)) // 3/12/23
print(date.string(formatter: .longDateFormatter)) // March 12, 2023
print(date.string(formatter: .customDateWithDashFormatter)) // 2023-03-12
At first glance, everything seems fine here. But what if we need to add one more custom style to display Date — “yyyy/MM/dd”? The main problem is we have to extend our date formatters with adding new:
extension DateFormatter {
static var customDateWithSlashFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd"
return formatter
}
}
print(Date().string(formatter: .customDateWithSlashFormatter)) // 2023/03/12
Let’s take a look at how Apple helps us resolve that issue. They have created a few methods that assist us in solving problems described above.
public func formatted() -> String
print(Date().formatted()) // 3/12/2023, 2:05 PM
The basic method that converts Date into localized string using default transformation style.
public func formatted<F>(_ format: F) -> F.FormatOutput where F : FormatStyle, F.FormatInput == Date
print(Date().formatted(.dateTime.day(.twoDigits).month(.twoDigits).year(.twoDigits))) // 03/12/23
As we see here, we must pass a parameter that conforms to the FormatStyle protocol. Apple took care of that too: Swift offers us a built-in struct that conforms to the FormatStyle protocol and we do not need to create our own. Also, it has a static variable “static var dateTime: Date.FormatStyle”.
Besides we have a possibility to create a new instance of Date.FormatStyle:
print(Date().formatted(Date.FormatStyle().day().month(.wide).year())) // March 12, 2023
Date.FormatStyle has a lot of methods like “day(…), month(…), year(…) etc”, they have their own parameters for customization and return the same type (Date.FormatStyle type). These instance methods offer us many options for creating a multitude of options. Furthermore, we do not need to worry about the order we call the functions, Swift takes care about that and chooses the correct format based on the user’s preferences.
public func formatted(date: Date.FormatStyle.DateStyle, time: Date.FormatStyle.TimeStyle) -> String
print(Date().formatted(date: .long, time: .omitted)) // March 12, 2023
Here, Swift provides some default pre-defined format styles for date and time — Date.FormatStyle.DateStyle and Date.FormatStyle.TimeStyle.
public func ISO8601Format(_ style: Date.ISO8601FormatStyle = .init()) -> String
print(Date().ISO8601Format(.iso8601.day().month().year().dateSeparator(.dash))) // 2023-03-12
It is used to convert Date to localized string using iso8601 format. Date.ISO8601FormatStyle also has a static variable “static var iso8601: Date.ISO8601FormatStyle” and has similar methods like Date.FormatStyle. Moreover, we can use “formatted(…)” method to do the same:
print(Date().formatted(.iso8601.day().month().year().dateSeparator(.dash))) // 2023-03-12