Sort by Date - Swift 3

(Swift 3) Trying to sort an array of class objects by Date in swift 3?

The compare is a NSDate function. With Date you can just use < operator. For example:

alarms.sort { $0.time < $1.time }

Having said that, compare should work, too, though. I suspect there's some deeper issue here, that perhaps your time values have different dates. You might only be looking at the time portion, but when comparing Date objects, it considers both the date and time. If you only want to look at the time portion, there are several ways of doing that, for example, look at the time interval between time and the start of the day:

let calendar = Calendar.current

alarms.sort {
let elapsed0 = $0.time.timeIntervalSince(calendar.startOfDay(for: $0.time))
let elapsed1 = $1.time.timeIntervalSince(calendar.startOfDay(for: $1.time))
return elapsed0 < elapsed1
}

There are lots of ways to do this, but hopefully this illustrates the idea.

Swift - Sort array by date and time in one go

This answer picks up on the refinement to the question in the below comment from the OP in response to the answer from @vadian. The actual requirement is to sort football goal times provided by the API. The solution below creates a struct for this data with a calculated variable for actual goal time and then sorts by that.

struct Goal{
let matchDate: String
let matchTime: String
let goalTime: String

var timeOfGoal: Date {
let goalComponents = goalTime.components(separatedBy: "+").map{$0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines.union(CharacterSet.decimalDigits.inverted))}
let goalSeconds = TimeInterval(60 * goalComponents.compactMap({Int($0)}).reduce(0, +))
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
let startTime = dateFormatter.date(from: matchDate + " " + matchTime)!
return startTime.addingTimeInterval(goalSeconds)
}
}

I tested this as below

let goals = [
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90 +7"),
Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "22"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "99"),
Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "45 + 3"),
Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "45+6"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90+6"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "35"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "85"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90"),
Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90+ 8"),
Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "44")]

let ordered = goals.sorted{$0.timeOfGoal > $1.timeOfGoal}

ordered.forEach{print("\($0.matchDate) - \($0.matchTime) - \($0.goalTime) ")}

and it correctly produced:

2019-11-18 - 22:00 - 99 
2019-11-18 - 22:00 - 90+ 8
2019-11-18 - 22:00 - 90 +7
2019-11-18 - 22:00 - 90+6
2019-11-18 - 22:00 - 90
2019-11-18 - 22:00 - 85
2019-11-18 - 22:00 - 35
2019-11-18 - 19:00 - 45+6
2019-11-18 - 19:00 - 45 + 3
2019-11-18 - 19:00 - 44
2019-11-18 - 19:00 - 22

There is room for improvement by not force unwrapping the Date?, although the string cleaning makes this reasonably safe, and by using a class-level static DateFormatter. But I'll leave that refinement for the implementation :-)

Sort Objects in Array by date

Using Swift 4 & Swift 3

let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [Date] = []

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
let date = dateFormatter.date(from: dat)
if let date = date {
convertedArray.append(date)
}
}

var ready = convertedArray.sorted(by: { $0.compare($1) == .orderedDescending })

print(ready)

Using Swift 2

For example you have the array with dates and another 1 array, where you will save the converted dates:

var testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [NSDate] = []

After that we convert the dates:

var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
var date = dateFormatter.dateFromString(dat)
convertedArray.append(date!)
}

And the result:

var ready = convertedArray.sort({ $0.compare($1) == .OrderedDescending })

print(ready)

How do I sort date components in Swift?

You should probably also group by the year, otherwise the same day in different years will be in the same group:

let date = Calendar.current.dateComponents([.day, .month, .year], from: (dateObj))

One way to sort the keys is to convert the date components back into Dates, using Calendar.current.date(from:):

let sortedList = groupedList.sorted {
Calendar.current.date(from: $0.key) ?? Date.distantFuture <
Calendar.current.date(from: $1.key) ?? Date.distantFuture
}

sortedList.forEach { key, values in
print("Group keys \(key)")
groupedtransactionsList.append(values ?? [])
}

How to sort items by date in tableview Swift 3

I have done something similar, But I am using a library that already has xib and methods to adjust everything. Here is just a small help from my side.

You can prepare one xib to show dates and data in tableView. Here, you can hide the row if next date is same as previous date and show whenever the date changes.
To show data according to dates you can do something like this (If data is added according to dates)

let expenses = [ExpensesClass]()

// in `cellForItemAt indexPath`

let expense = expenses[indexPath.row]
let date = expense.date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM d, yyyy"
let dateString = dateFormatter.string(from: date! as Date)

. . . . . .

if indexPath.row > 0 {
let previousExpensesData = expenses[indexPath.row - 1].date
let day = Calendar.current.component(.day, from: expense.date) // Do not add above 'date' value here, you might get some garbage value. I know the code is redundant. You can adjust that.
let previousDay = Calendar.current.component(.day, from: expenses[indexPath.row - 1].date)
if day == previousDay {
cell.dateTitle.text = ""
} else {
cell.dateTitle.text = dateString
}
}else{
cell.dateTitle.text = dateString
print("Cannot return previous Message Index...\n\n")
}

You can adjust height in this method -> func tableView(UITableView, heightForRowAt: IndexPath).

I am not sure about this method -> func tableView(UITableView, titleForHeaderInSection: Int) . You can try it in this method as well if the above one doesn't work for you and adjust the height accordingly in -> func tableView(UITableView, titleForHeaderInSection: Int)

func tableView(_ tableView: UITableView, 
heightForRowAt indexPath: IndexPath) -> CGFloat
{
let expense = expenses[indexPath.row]

if indexPath.row > 0{
let day = Calendar.current.component(.day, from: expense.date)
let previousDay = Calendar.current.component(.day, from: expense[indexPath.row - 1].date)
if day == previousDay {
return 0.0
}else{
return 20.0
}
}
return 20.0
}

Sorting of array of dictionary with date Swift 3

You don't need to convert to date time for this sort. The international format (yyyy/MM/dd HH:mm:ss) you're using provides the right sorting order as a string.

Sort by date - Swift 3

Predicates are for filtering your search results. To sort them you need to use an NSSortDescriptor. Assuming you have an attribute on your Expenses entity called date of type Date:

func getData() {
let context = appDelegate.persistentContainer.viewContext

let fetchRequest = NSFetchRequest<Expenses>(entityName: "Expenses")
let sort = NSSortDescriptor(key: #keyPath(Expenses.date), ascending: true)
fetchRequest.sortDescriptors = [sort]
do {
expenses = try context.fetch(fetchRequest)
} catch {
print("Cannot fetch Expenses")
}
}

EDIT: I should have mentioned that the sort selector is added in an array so that multiple sort descriptors can be added if needed. e.g. sort first by date, then by number of legs, then by volume, etc.

Sort array of custom objects by date swift

For Swift 4, Swift 5

Sorting by timestamp

values.sorted(by: { $0.meetingDateTimestamp > $1. meetingDateTimestamp })


Related Topics



Leave a reply



Submit