Sort list by date flutter - flutter

I need to sort the list by date, but sorting only by first number.
I get this format from JSON 20-JAN-23
and I'm trying to order with model.data.sort((a, b) => b.time!.compareTo(a.time!));
I need to sort the list by date.
I get this format from JSON 20-JAN-23
and I'm trying to order with model.data.sort((a, b) => b.time!.compareTo(a.time!));
but if the year is different, sort only by day. I need to sort by full date.
e.x:
20-SEP-20
02-DEC-21
29-JAN-23
12-JUN-20
My sorting is :
02-DEC-21
12-JUN-20
20-SEP-20
29-JAN-23
but I want to be:
12-JUN-20
20-SEP-20
02-DEC-21
29-JAN-23

import 'package:intl/intl.dart';
int sortDates(String a, String b) {
String formatDate(String s) => s.replaceRange(4, 6, s.substring(4, 6).toLowerCase());
DateTime parse(String s) => DateFormat("dd-MMM-yy").parse(formatDate(s));
return parse(a).compareTo(parse(b));
}
...
model.data.sort(sortDates);
...

Related

How to sort list of object by ISO8601

I've got a list of object which after looping I'm trying to sort the final list by given ISO8601 format favouriteDateTime: 2022-12-16T10:46:55.551Z. There are mutiple sorting method but which one to use and how to sort it.
List<Movies> get Movies{
List<Movies> favMoviesList = <Movies>[];
for (final category in _appData.categories) {
for (final series in category.series!) {
final favMovies = series.movie!
.where((movie) =>
movie.stats != null && movie.stats!.isFavourite == true)
.toList();
if (favMovies.length > 0) {
List<Movies> sorted = favMovies
..sort((a, b) => b.stats!.favoriteDateTime!
.compareTo(a.stats!.favoriteDateTime!));
favMoviesList.addAll(sorted);
}}}
return favMoviesList;
}
Looks like you've already got a working implementation here. ISO8601 timestamps can just be sorted with string comparison - for two ISO strings a and b, a > b will always be true if time a is after time b, and the inverse is also true.
As far as the actual sorting method goes, you've got the right idea here with using sort(). Just make sure you only have one period -- favMovies.sort(), not favMovies..sort().
Also, List.sort() does not return the sorted list, it sorts the list in place. So your sorting code should be:
favMovies.sort((a, b) =>
b.stats!.favoriteDateTime!.compareTo(a.stats!.favoriteDateTime!)
);
favMoviesList.addAll(favMovies);

how to sort a list of data by ISO8601 format

I've got a list of data which also contains ISO8601 DateTime format. How can I sort it by time not date?
[2022-12-06T22:37:49.292343,
2022-12-06T18:37:49.300045,
2022-12-06T15:37:49.307976]
To sort the list of dates by their hour, you can use:
void main() {
final dates = [
'2022-12-06T22:39:50.292343',
'2022-12-06T18:37:49.300045',
'2022-12-06T15:37:49.307976'
];
dates
.sort((a, b) => DateTime.parse(a).hour.compareTo(DateTime.parse(b).hour));
print(dates);
}
Output:
[2022-12-06T15:37:49.307976, 2022-12-06T18:37:49.300045, 2022-12-06T22:39:50.292343]
Parse the strings to DateTime objects.
If you want to ignore the date and sort only by time, create new DateTime objects that copy the times and that all use the same date.
Sort by those new DateTime objects.
void main() {
var dateTimeStrings = [
'2022-12-01T22:37:49.292343',
'2022-12-02T18:37:49.300045',
'2022-12-03T15:37:49.307976',
];
/// Replaces the date portion of a [DateTime] with a fixed date,
/// retaining the time portion.
///
/// The returned [DateTime] object will be in UTC.
///
/// In Dart 2.19, this implementation can be simplified with the
/// [DateTime.copyWith] extension.
DateTime clobberDate(DateTime dateTime) => DateTime.utc(
2022,
1,
1,
dateTime.hour,
dateTime.minute,
dateTime.second,
dateTime.millisecond,
dateTime.microsecond,
);
dateTimeStrings.sort((a, b) {
var dt1 = clobberDate(DateTime.parse(a));
var dt2 = clobberDate(DateTime.parse(b));
return dt1.compareTo(dt2);
});
dateTimeStrings.forEach(print);
}
which prints:
2022-12-03T15:37:49.307976
2022-12-02T18:37:49.300045
2022-12-01T22:37:49.292343
Note that the above sort callback could be unnecessarily expensive for long lists since it could call DateTime.parse multiple times on the same Strings. It'd be better to convert your List<String> to a List<DateTime> first and then sort that. Or, if you must start and end with Strings, you could use a Schwartzian transform.

How to find documents with a combination of two fields in pymongo

I have a collection which stores documents like this
{
// Other fields
'date':'07/01/2021',
'time':'09:21:10'
}
and I want to find documents greater than a specific date
yesterdays_date = (datetime.now() - timedelta(hours=24))
docs = db.collection.find({'date': {'$gte': yesterdays_date}}
How can I do that?
Ideally refactor your collection to store the date/times as a BSON date object; then your query would work.
you stored data like string :
{
// Other fields
'date':'07/01/2021', // => type = string
'time':'09:21:10' // => type = string
}
yesterdays_date // => returns datetime
if u wanna compare u should compare with datetime , not string with datetime
other problem is :
you should compare date with date ( not datetime format)

Dart: Map class, reduce (or otherwise find certain information)

New to Dart (Flutter), and the docs don't seem to have a method for the Map class that will allow me to do this easily...
I want to have a Map with keys of Datetime and values of calories eaten.
{'2019-07xxx': 350, '2019-07xxx': 500, ...}
Now, what's the best way to filter this so that I only get values from today? (i.e. when starting the app and pulling the data from storage)
Ideally once I do that, I can get the cumulative value of today's calories so far with:
var sum = todaysCaloriesArray.reduce((a, b) => a + b);
Unless there is some Dart-fu that would allow this in a better way?
You could use .where on the map's entries. For example:
var map = Map<String, int>();
var sum = map.entries
.where((e) => e.key.startsWith('2019-07-22'))
.map<int>((e) => e.value)
.reduce((a, b) => a + b);
The first answer was great! But you can use the fold method so you can use in empty collections.
var map = Map<String, int>();
var sum = map.entries
.where((e) => e.key.startsWith('2019-07-22'))
.fold(0,(int a, b) => a + b.value);

How to use nest in d3 to group using the 'month' as key, but my csv file contains the whole date?

var data = d3.nest()
.key(function(d) { return d.date;})
.rollup(function(d) {
return d3.sum(d, function(g) {return g.something; });
}).entries(csv_data);
using this code above I can group by date which is in the format yyyy-mm-dd , but I want to group using the month as key. How do I do this ?
You can use the builtin method d3.timeMonth() to get the first day of the month for a date like:
d3.nest()
.key(function(d){ return d3.timeMonth(d.date); });
If d.date is not already a javascript Date object you have to first parse it to be one.
var date_format = d3.timeFormat("%Y-%m-%d");
csv_data.forEach(function(d, i) {
d.date = date_format.parse(d.date);
};
You need to change the key function to return the value you want to nest by. In most cases, the key function just returns a property of the data object (like d.date), but in your case the function will require a little more calculation.
If your date is stored as a string of the format "yyyy-mm-dd" you have two options for extracting the month: either
use regular expressions to extract the portion of the string in between the "-" characters, or
convert it to a date object and use date methods to extract a component of the date.
Browsers differ in which date formats they can convert using the native Javascript new Date(string) constructor, so if you're using date objects you may want to use a d3 date format function's format.parse(string) method to be sure of consistent results.