Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dart - How to order datetime objects?

Tags:

flutter

dart

Using Flutter/Dart (newbie). I need to store users results in a game (score, time and name). I presume a GameResult class is the way to go?

I then need to order on each users results on date/time (newest to oldest) to display a results table. How can I order on datetime values?

like image 438
Kevin Dev Avatar asked Dec 02 '22 10:12

Kevin Dev


2 Answers

The Dart DateTime class is Comparable to other DateTime objects, so you can use dateTime1.compareTo(dateTime2) to compare two points in time.

Example:

class Result implements Comparable<Result> {
   final String name;
   final int score;       
   final DateTime time;
   Result(this.name, this.score, this.time);

   int compareTo(Result other) {
     int order = other.score.compareTo(score);
     if (order == 0) order = time.compareTo(other.time);
     return order;
   }

   String toString() => "Result($name, score: $score, time: $time)";
 }

This creates a class where instances can be compared to each other. The order is first by reverse score (higher score before lower score) and for equal scores, it sorts the earlier results before later results.

The Comparable.compareTo method is specified to return a negative number if the receiver is "before" the argument in the order, zero if they have the same order, and a positive number if the receiver is after the argument.

Integers are comparable too, and by using other.score.compareTo(score) instead of the other way around, we effectively switch the ordering of the scores - integers default to lower values before higher values).

When the Result class is comparable to itself, you can sort a List<Result> as just:

var results = <Result>[
   Result("Me", 0, DateTime.now().subtract(Duration(hours: 1))),
   Result("Me again", 0, DateTime.now().subtract(Duration(hours: 2))),
   Result("You", 1000000, DateTime.now().subtract(Duration(hours: 24))), 
];
results.sort();
print(results.join("\n"));

This prints:

Result(You, score: 1000000, time: 2018-10-23 15:34:16.532)
Result(Me again, score: 0, time: 2018-10-24 13:34:16.532)
Result(Me, score: 0, time: 2018-10-24 14:34:16.531)

You win by score. My earlier zero-score is before my later one.

like image 156
lrn Avatar answered Dec 19 '22 00:12

lrn


One approach is to evaluate the dates as Epoch DateTime millisecondsSinceEpoch then sort as standard int values.

With this approach you can sort an entire list in one line...

result.sort((a,b) => a.date.millisecondsSinceEpoch.compareTo(b.date.millisecondsSinceEpoch));

Here is a complete example using the Game Result scenario

// Create the game result object
class Result{

    Result(this.name, this.score, this.date);
    String name;
    int score;
    DateTime date;

    @override    
    String toString() => '$name  $score  $date';
}


// Create a list to put the results in
List<Result> result = [];


// Populate the list with results
result..add( Result('Tom',  850, DateTime.tryParse('2020-01-10')))
      ..add( Result('Dic',   600, DateTime.tryParse('2020-01-03')))
      ..add( Result('Harry', 450, DateTime.tryParse('2020-01-05')));

// print the unsorted list
print(result);

// Sort the list by datetime property
result.sort((a,b) => a.date.millisecondsSinceEpoch.compareTo(b.date.millisecondsSinceEpoch));


// print the sorted list
print(result);
like image 44
RumbleFish Avatar answered Dec 19 '22 02:12

RumbleFish