4

I am curious how to sort dates in form of Strings in an array. Most likely I would leave them in the same array and sort them the right way. Many attempts I have seen are with two. Also, they weren't the right time format so I want to know how to sort it with the "dd.MM.yyyy" format. Most likely with only the last two numbers of the year. Is that possible?

Here is what I did. I want it to take the date in the struct to sort:

import UIKit

struct Post {
var title: String
var date: String
var user: String
}

var uploadTimes = [Post(title: "Hello", date: "02.10.2018", user: "Roman"),
                Post(title: "Hi", date: "01.10.2018", user: "Roman"),
                Post(title: "", date: "05.09.2018", user: "")]


uploadTimes = uploadTimes.map{ $0.components(separatedBy: ".").reversed().joined(separator: ".")}
print(uploadTimes)
//["2002.02.02", "2002.02.03", "2002.02.05", "2002.02.04"]


let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withFullDate,]


let dates = uploadTimes.compactMap { isoFormatter.date(from: $0) }
print(dates)
let sortedDates = dates.sorted { $0 > $1 }
print(sortedDates)
Thomas22
  • 225
  • 1
  • 3
  • 11
  • What errors are you getting? – Scriptable Dec 11 '18 at 11:51
  • "only throwing errors back:" What errors? – Larme Dec 11 '18 at 11:51
  • "Value of type 'ISO8601DateFormatter' has no member 'dateFormat'" - this one for example – Thomas22 Dec 11 '18 at 11:52
  • That's not ISO8601. `let formatter = DateFormatter(); formatter.dateFormat = "dd.MM.yyyy"` – Larme Dec 11 '18 at 11:53
  • Well that's a pre configured formatter as it's name suggests. – Desdenova Dec 11 '18 at 11:53
  • You don't need to map them to date objects and back to sort them btw. Take a look at these https://stackoverflow.com/questions/53719381/about-comparing-and-generating-character-strings/53719671?r=SearchResults#53719671 https://stackoverflow.com/questions/53704110/ambiguous-reference-to-member-filter-swift4/53704173?r=SearchResults#53704173 – Rakesha Shastri Dec 11 '18 at 12:04

3 Answers3

8

You can't specify the date format for an ISO8601DateFormatter, it only accepts dates in the normal ISO format.

If you replace it with a normal DateFormatter() you can specify date format. See below code:

var uploadTimes = ["02.02.2002","03.02.2002","05.02.2002","04.02.2002"]

print(uploadTimes)

let isoFormatter = DateFormatter()
isoFormatter.dateFormat = "dd.MM.yyyy"

let dates = uploadTimes.compactMap { isoFormatter.date(from: $0) }

let sortedDates = dates.sorted { $0 > $1 }

print(sortedDates)

let dateStrings = sortedDates.compactMap { isoFormatter.string(from: $0)}

print(dateStrings)
mlidal
  • 1,111
  • 14
  • 27
  • It prints out the actual date objects. I've added code to convert back into strings of the original format – mlidal Dec 11 '18 at 12:02
7

This is another answer with an updated POST structure.

struct Post {
var title: String
var date: String
var user: String
}

extension Post{
static  let isoFormatter : ISO8601DateFormatter = {
    let formatter =  ISO8601DateFormatter()
        formatter.formatOptions = [.withFullDate,]
    return formatter
   }()

var dateFromString : Date  {
    let  iSO8601DateString = date.components(separatedBy: ".").reversed().joined(separator: ".")
    return  Post.isoFormatter.date(from: iSO8601DateString)!
}
}

var uploadTimes = [Post(title: "", date: "05.09.2018", user: ""),
               Post(title: "Hello", date: "02.10.2018", user: "Roman"),
               Post(title: "Hi", date: "01.10.2018", user: "Roman"),
               ]

//sort dates
let dates = uploadTimes.compactMap { $0.dateFromString }
print(dates)
let sortedDates = dates.sorted { $0 > $1 }
print(sortedDates)

//sort posts
let sortedPost = uploadTimes.sorted{ $0.dateFromString > $1.dateFromString  }
print(sortedPost)

If the format is hh:mm dd.MM.yyyy . The updated answer is like this:

extension Post{
static  let isoFormatter : ISO8601DateFormatter = {
    let formatter =  ISO8601DateFormatter()
        formatter.formatOptions = [.withInternetDateTime]
    return formatter
   }()

   var dateFromString : Date  {

  let components = date.components(separatedBy: " ")
  let  iSO8601DateString =
        (components.last!).components(separatedBy: ".").reversed().joined(separator: ".") + "T" + (components.first!) + ":00+00:00"
    return  Post.isoFormatter.date(from: iSO8601DateString)!
   }
}

 var uploadTimes = [Post(title: "", date: "01:20 05.09.2018", user: ""),
               Post(title: "Hello", date: "01:21 02.10.2018", user: "Roman"),
               Post(title: "Hi", date: "01:22 02.10.2018", user: "Roman"),
               ]
E.Coms
  • 11,065
  • 2
  • 23
  • 35
  • It fits perfectly – Thomas22 Dec 13 '18 at 09:55
  • I noticed that posts with the same dates will be sorted under each other. So now the newest Post of the same day will be displayed under the other new ones. So I thought about adding a hour and minute display. Can you maybe expand your code so it will compare those to? – Thomas22 Dec 13 '18 at 10:35
  • hh:mm dd.mm.yyyy – Thomas22 Dec 17 '18 at 17:58
  • in my case it is sorting fine but not updating value in backend and sometime its not sorting. Any solution??? – Mr Abbasi Mar 03 '21 at 10:59
1

If you insist in using the ISODateFormatter, you may have to change to format of input as they assume an "yyyy.MM.dd" format.

 import UIKit

 var uploadTimes = ["02.02.2002","03.02.2002","05.02.2002","04.02.2002"]
 uploadTimes = uploadTimes.map{ $0.components(separatedBy: ".").reversed().joined(separator: ".")}
 print(uploadTimes)
  //["2002.02.02", "2002.02.03", "2002.02.05", "2002.02.04"]


 let isoFormatter = ISO8601DateFormatter()
 isoFormatter.formatOptions = [.withFullDate,]


 let dates = uploadTimes.compactMap { isoFormatter.date(from: $0) }
 print(dates)
 let sortedDates = dates.sorted { $0 > $1 }
 print(sortedDates)
E.Coms
  • 11,065
  • 2
  • 23
  • 35