Reputation: 459
So I have an array of dates that are already formatted as strings. But I want to further format it. What I have currently prints me nil. I want to be able to convert it into something like "June, 23, 2020" or "June-23", etc. What am I missing?
let dates = ["2020-06-23", "2021-06-24", "2022-06-25", "2020-06-26", "2020-06-29"]
for i in dates {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd"
let date = dateFormatter.date(from: i)
print(date)
}
Upvotes: 0
Views: 1126
Reputation: 12034
Try with:
let dates = ["2020-06-23", "2021-06-24", "2022-06-25", "2020-06-26", "2020-06-29"]
var datesFormated = [Date]()
let initialDateFormatter = DateFormatter()
let dateFormatter = DateFormatter()
initialDateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.dateFormat = "MMM d, yyyy"
dates.forEach {
datesFormated.append( initialDateFormatter.date(from: $0)! )
}
datesFormated.forEach {
print(dateFormatter.string(from: $0))
}
Output:
Jun 23, 2020
Jun 24, 2021
Jun 25, 2022
Jun 26, 2020
Jun 29, 2020
Upvotes: 2
Reputation: 13970
First of all, initializing DateFormatter
on every iteration is very wasteful. Make it constant or static, and only change format when needed.
Secondly, when working with DateFormatter, you should always think of it as transformation where date to string, or vice versa, but you cannot transform one string to another directly. In your case, you need:
string > date > string
So basic code would look like this:
let dates = ["2020-06-23", "2021-06-24", "2022-06-25", "2020-06-26", "2020-06-29"]
let dateFormatter = DateFormatter()
for i in dates {
// string > date
dateFormatter.dateFormat = "YYYY-MM-dd"
guard let fromDate = dateFormatter.date(from: i) else {
// not a valid date, skip
continue
}
// date > string
dateFormatter.dateFormat = "MMM, YYYY" // or whatever you need
let toDate = dateFormatter.string(from: fromDate)
print(toDate)
}
But also, if you have this same formatting in multiple places in your code, it's best to create an extension:
extension Date {
static let dateFormatter = DateFormatter()
// If you are dealing with the same date as input often, you can do this:
init?(fromDateOnlyString: String) {
Date.dateFormatter.dateFormat = "YYYY-MM-dd"
guard let date = Date.dateFormatter.date(from: fromDateOnlyString) else {
return nil
}
self = date
}
// If you need the same output format often, you can do this:
func toMyDesiredFormat() -> String {
Date.dateFormatter.dateFormat = "MMM, YYYY" // Or whatever you need
return Date.dateFormatter.string(from: self)
}
}
And you use this extension like this:
for i in dates {
guard let fromDate = Date(fromDateOnlyString: i) else {
// not a valid date, skip
continue
}
let toDate = fromDate.toMyDesiredFormat()
print(toDate)
}
Upvotes: 1
Reputation: 1324
I was writing this as you posted your answer, but I'll post anyway as there's a slight difference in approaches.
I suggest using both DateFormatter.date(from: string)
AND DateFormatter.string(from: date)
. In other words, build two distinct date formatters: one to read in your date in "yyyy-MM-DD" format, and another to make a string in a different format. You can then change each of the formatters as needed, or even have a method wrapping this code where you can insert different formatters or format strings, making it flexible if you want to change formats.
Also, there's no need to instance a new formatter every time you go through the loop.
let dates = ["2020-06-23", "2021-06-24", "2022-06-25", "2020-06-26", "2020-06-29"]
// use this formatter to read in dates from initial strings
let originalDateFormatter = DateFormatter()
originalDateFormatter.dateFormat = "yyyy-MM-dd"
// use this formatter to generate new strings from dates
let newDateFormatter = DateFormatter()
newDateFormatter.dateFormat = "MMMM d" // or choose whatever new string format you want
for i in dates {
if let date: Date = originalDateFormatter.date(from: i) {
let dateInNewStringFormat: String = newDateFormatter.string(from: date)
print(dateInNewStringFormat) // prints as "June 23"
}
}
Upvotes: 1
Reputation: 161
First you get the right format. Then you can change it.
You can use
let dates = ["2020-06-23", "2021-06-24", "2022-06-25", "2020-06-26", "2020-06-29"]
//create an empty array of dates
var datesFormated = [Date]()
let initialDateFormatter = DateFormatter()
initialDateFormatter.dateFormat = "yyyy-MM-dd"
for i in dates {
let date = initialDateFormatter.date(from: i)!
//but you have to make sure that the date format of the strings match the date formatter, otherwise it will crash
datesFormated.append(date)
}
//then change the format to the one you need
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d, yyyy"
for date in datesFormated {
let date = dateFormatter.string(from: date)
print(date)
}
Output would be
Jun 23, 2020
Jun 24, 2021
Jun 25, 2022
Jun 26, 2020
Jun 29, 2020
Hope this helps.
Upvotes: 3
Reputation: 459
Found the solution. You have you first convert it into Dates then convert those Dates into Formatted strings again. I had the format for the initial dateFormatter wrong as "dd".
let dates = ["2020-06-23", "2020-06-24", "2020-06-25", "2020-06-26", "2020-06-29"]
var formattedDates = [Date]()
for i in dates {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let date = dateFormatter.date(from: i) {
formattedDates.append(date)
}
}
print(formattedDates) //prints [2020-06-23 04:00:00 +0000, 2020-06-24 04:00:00 +0000, 2020-06-25 04:00:00 +0000, 2020-06-26 04:00:00 +0000, 2020-06-29 04:00:00 +0000]
Upvotes: 0