Home > Mobile >  get the nearest date closest to target date if found on same second else return the closest date to
get the nearest date closest to target date if found on same second else return the closest date to

Time:03-16

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 with temp 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

  • Related