This question is continuation of my previous post I have two date fields:
start date (2021-03-07T07:37:15) and end date (2021-03-07T07:37:25) and temp date (2021-03-07T07:37:20) .
I have a list where I have returned 6 records between the start date and end date. How can I filter the records and return the datetime which is closest to temp date?
here in the example records I need to get the 3rd record because the 2021-03-07T07:37:20.004 is closet to the temp date. Example
2021-03-07T07:37:15.000
2021-03-07T07:37:19.999
2021-03-07T07:37:20.004
2021-03-07T07:37:20.809
2021-03-07T07:37:22.100
2021-03-07T07:37:22.814
In the Example 2 i need to get the 2nd recod , since there are no records found in the same second and 2021-03-07T07:37:19.999 is closest to the target date
2021-03-07T07:37:15.000
2021-03-07T07:37:19.999
2021-03-07T07:37:22.100
2021-03-07T07:37:22.814
2021-03-07T07:37:22.815
2021-03-07T07:37:22.816
can i acheive this using two filters ? when i tried with the below code it is returning me null for the first scenario. Please suggest
public RequiredRecord findCloseRecord(List<RequiredRecord > list, Date tempDate) {
Date startTime = new Date(tempDate.getTime() - 5000);
Date endTime = new Date(tempDate.getTime() 5000);
Log.logInfo(this, "Find close record");
if (list != null && !list.isEmpty()) {
List<RequiredRecord > filteredRec = list.stream()
.filter(rec -> (rec.getLogRecDateTime() != null ))
.sorted(Comparator.comparing(RequiredRecord ::getLogRecDateTime))
.collect(Collectors.toList());
if (!ClrUtils.isCollectionEmpty(filteredRec)) {
List<RequiredRecord > filteredRecEqual = list.stream()
.filter(rec1 -> (rec1.getLogRecordDateTime() != null && tempDate.equals(rec1.getLogRecordDateTime()))).collect(Collectors.toList());
if (!ClrUtils.isCollectionEmpty(filteredRecEqual)) {
filteredRecEqual.get(0);
return (filteredRecEqual.get(0));
} else {
List<RequiredRecord > filteredRec2 =
list.stream().sorted(Comparator.comparingLong(d -> Math.abs(tempDate.getTime() - d.getLogRecordDateTime().getTime())))
.collect(Collectors.toList());
return (filteredRec2.get(0));
}
}
return null;
}
CodePudding user response:
It seems like getLogReqDateTime returns a Date. We can then compare how close these dates are by looking at their time and using the min method from Java Streams.
private static Date exampleWithDates(List<Date> dates, Date tempDate) {
return dates.stream()
.min(Comparator.comparing(date -> Math.abs(tempDate.getTime() - date.getTime())))
.orElse(null);
}
Obviously this doesn't fit perfectly with your code, as I do not know the specific implementation of RequiredRecord. But I think something like this might work for you:
private static Date getNearestDate(List<RequiredRecord> dates, Date tempDate) {
return dates.stream()
.map(RequiredRecord :: getLogRecDateTime)
.min(Comparator.comparing(date -> Math.abs(tempDate.getTime() - date.getTime())))
.orElse(null);
}
If for some reason the RequiredRecords may be null, just add a filter before the map method, like you already do.
CodePudding user response:
You should refrain from using the Date class. It is obsolete and has been replaced by the much better java.time package.
- Duration - used to provide a value based amount of time.
- LocalDateTime - A date time without a time zone
You can do it as follows using the Duration.toMillis()
method from that package and return the millisecond difference of two dates.
- the first part of the comparator parses the date.
- the second part applies that to
Duration
along withtemp
value and converts to milliseconds. - then that is compared.
LocalDateTime temp =
LocalDateTime.parse("2021-03-07T07:37:20");
Optional<String> closest = Arrays.stream(dates)
.min(Comparator.comparing(LocalDateTime::parse,
Comparator.comparingLong(ldt -> Math.abs(Duration
.between(ldt, temp).toMillis()))));
if (closest.isPresent()) {
System.out.println(closest);
}
prints
2021-03-07T07:37:19.999