1

I have an array of docs which has an date property as strings for example "29-10-2020-20:58" "30-10-2020-20:43" "01-11-2020-00:19" "01-11-2020-00:31"

I want to short these from new to old, how do I achieve this?

I ve tried
conversations.sort(by: {$0.latestMessage.date > $1.latestMessage.date})

there are similar questions but none of them answers my question because of my specific date string format

and it works fine until the month changes, that's another question. Why does work if the dates are in the same month? It shouldn't have worked at all I guessed.

borqalti
  • 23
  • 4
  • 1
    You need to use a DateFormatter and convert the strings to Date objects, it should not be very hard to find information about that here on stackoverflow, – Joakim Danielson Oct 31 '20 at 22:10

1 Answers1

0

The reason it works for dates in the same month is that it comes after the day in the string. I would recommend to change the date property type from String to Date. If you can not change the property type you would need to create a custom DateFormatter to parse your date strings and sort the resulting dates:

extension Formatter {
    static let date: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = .init(identifier: "en_US_POSIX")
        formatter.dateFormat = "dd-MM-yyyy-HH:mm"
        return formatter
    }()
}

extension String {
    var customDate: Date? { Formatter.date.date(from: self) }
}

This assumes your date string is always a valid date:

conversations.sort(by: { $0.latestMessage.date.customDate! > $1.latestMessage.date.customDate!})
print(conversations)

This will print:

[Conversation(latestMessage: Message(date: "01-11-2020-00:31")),
Conversation(latestMessage: Message(date: "01-11-2020-00:19")),
Conversation(latestMessage: Message(date: "30-10-2020-20:43")),
Conversation(latestMessage: Message(date: "29-10-2020-20:58"))]


If you can not guarantee your string is always a valid date you can use the nil coalescing operator to provide a default value:

conversations.sort(by: { $0.latestMessage.date.customDate ?? .distantFuture > $1.latestMessage.date.customDate  ?? .distantFuture })
print(conversations)
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • it worked just fine for me, one more little question. Does firebase realtime db store dates or only int bool and string? if that's the case how do you store dates in db? You suggested me to change the property to date but what would it change if I store and call the dates from db? Thanks – borqalti Nov 01 '20 at 09:04
  • And how to use this sort func? Every time I want the array to be ordered or just once is enough? How does it work. Thx a lot. – borqalti Nov 01 '20 at 09:09
  • 1
    No you can't store a date in firebase but you can make it easier to sort changing the format of your [date string to iso8601](https://stackoverflow.com/a/28016692/2303865) to `"yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"`. The order of the elements allows you to simply sort the strings as you were trying to do. – Leo Dabus Nov 01 '20 at 13:59
  • 1
    I don't know how you are structuring your data. You can not rely on a dictionary to maintain the order of the elements in Swift. So if you don't want to sort your elements before displaying you will need to use an array to keep the elements order. – Leo Dabus Nov 01 '20 at 14:02