Reputation: 69
I have a list storing Date Objects in this form:
Mon Jan 30 18:00:00 GMT+00:00 2017
Mon Jan 30 21:00:00 GMT+00:00 2017
Tue Jan 31 00:00:00 GMT+00:00 2017
Tue Jan 31 03:00:00 GMT+00:00 2017
Tue Jan 31 06:00:00 GMT+00:00 2017
I need a way to filter my list and keep only the last date for each day.
This is the current status of my code:
for(int i = 0; i< timeDate.size(); i++){
Calendar calendar = Calendar.getInstance();
calendar.setTime(timeDate.get(i));
int day = calendar.get(Calendar.DAY_OF_MONTH);
int month = calendar.get(Calendar.MONTH);
int hour = calendar.get(Calendar.HOUR);
for(int j=i; j<timeDate.size(); j++){
Date currentDate = timeDate.get(j);
calendar.setTime(currentDate);
int dayC = calendar.get(Calendar.DAY_OF_MONTH);
int monthC = calendar.get(Calendar.MONTH);
int hourC = calendar.get(Calendar.HOUR);
if(day==dayC && month==monthC && hourC > hour){
timeDate.remove(i);
}
}
}
Upvotes: 2
Views: 3924
Reputation: 339382
The Calendar
and Date
classes have supplanted by the java.time classes. Avoid the troublesome legacy classes like the Plague.
Convert each Date
you say you are given to an Instant
, a moment on the timeline in UTC.
Instant instant = myDate.toInstant();
Collect into a List
.
List<> instants = new ArrayList<>();
instants.add( myDate.toInstant() );
…
Collections.reverse( instants ); // if not already in descending sorted order.
As seen in the Answer by Darshan, make a Map but of LocalDate
and ZonedDateTime
.
We need to assign a time zone to Instant
to get à ZonedDateTime
. For any given moment, the date varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
Extract a LocalDate
.
LocalDate ld = zdt.toLocalDate();
Use that as your key to map. If no such key, add it and add the ZonedDateTime
as the value for that Map entry.
If there is a key for that date, retrieve the value, the ZonedDateTime
and compare. Compare with isAfter
method. Replace the value if one in hand is later.
Tip: if you sort the inputs by latest ones first such as Collections.reverse( instants )
, you can optimize. If you find a key for a particular LocalDate
, don't bother checking with a call to isAfter
. You know any value entered for that key is already the latest. So move on to next input.
You can further optimize by not even checking the Map. Just remember the last LocalDate
added to the Map. Compare against the incoming LocalDate
with a call to isEqual
. If equal, move on to next input.
Upvotes: 1
Reputation: 30839
Here you go:
public static void main(String[] args){
List<String> list = new ArrayList<>();
SimpleDateFormat dateFomat = new SimpleDateFormat("E MMM dd hh:mm:ss z yyyy");
SimpleDateFormat yyyyMMddFormat = new SimpleDateFormat("yyyyMMdd");
list.add("Mon Jan 30 18:00:00 GMT+00:00 2017");
list.add("Mon Jan 30 21:00:00 GMT+00:00 2017");
list.add("Tue Jan 31 00:00:00 GMT+00:00 2017");
list.add("Tue Jan 31 03:00:00 GMT+00:00 2017");
list.add("Tue Jan 31 06:00:00 GMT+00:00 2017");
Map<String, List<Date>> dateMap = list.stream()
.map(s -> {
try {
return dateFomat.parse(s);
} catch (ParseException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.groupingBy(s -> yyyyMMddFormat.format(s), Collectors.toList()));
List<Date> lastDates = new ArrayList<>();
for(Map.Entry<String, List<Date>> entry : dateMap.entrySet()){
lastDates.add(Collections.max(entry.getValue()));
}
System.out.println(lastDates);
}
Upvotes: 3