Java 比较日期列表,找出最接近该分钟的日期,然后选择该日期并将其四舍五入到最接近的分钟

Java 比较日期列表,找出最接近该分钟的日期,然后选择该日期并将其四舍五入到最接近的分钟,java,json,datetime,functional-programming,java-stream,Java,Json,Datetime,Functional Programming,Java Stream,我有一个对象类型的列表-TrackingMessage,其中包含一个日期。该列表可以包含5-数千个条目 我需要通过比较每个日期的列表来找出哪一个日期最接近这一分钟。列表在一分钟内可能包含3或4个条目,因此它需要找到最接近该分钟的条目,然后再将其四舍五入到最接近的分钟 i、 e 12:45:22,12:45:35,12:45:15 从上面的小例子中,它将选择12:45:15作为最接近分钟的时间,然后将其四舍五入到最接近的分钟-12:45:00 我目前拥有的代码如下: { "status":

我有一个对象类型的列表-TrackingMessage,其中包含一个日期。该列表可以包含5-数千个条目

我需要通过比较每个日期的列表来找出哪一个日期最接近这一分钟。列表在一分钟内可能包含3或4个条目,因此它需要找到最接近该分钟的条目,然后再将其四舍五入到最接近的分钟

i、 e 12:45:22,12:45:35,12:45:15

从上面的小例子中,它将选择12:45:15作为最接近分钟的时间,然后将其四舍五入到最接近的分钟-12:45:00

我目前拥有的代码如下:

{
    "status": "success",
    "serviceId": "d8f2092b-01de-424f-9068-32c4efdcfd45",
    "driverId": "e1275ef6-f885-4724-9255-2e03868df5ee",
    "eventList": [
        {
            "eventTime": "2019-07-18T13:09:01",
            "eventId": 15,
            "lat": 50.4130166,
            "lon": -5.0739198
        },
        {
            "eventTime": "2019-07-18T13:10:04",
            "eventId": 21,
            "lat": 50.412991299999995,
            "lon": -5.073924
        },
        {
            "eventTime": "2019-07-18T13:11:04",
            "eventId": 21,
            "lat": 50.413074599999995,
            "lon": -5.074010299999999
        },
        {
            "eventTime": "2019-07-18T13:12:04",
            "eventId": 21,
            "lat": 50.4131295,
            "lon": -5.0739676
        },
        {
            "eventTime": "2019-07-18T13:13:04",
            "eventId": 21,
            "lat": 50.4133475,
            "lon": -5.073917499999999
        },
        {
            "eventTime": "2019-07-18T13:14:04",
            "eventId": 21,
            "lat": 50.4133618,
            "lon": -5.0739218
        },
        {
            "eventTime": "2019-07-18T13:15:04",
            "eventId": 21,
            "lat": 50.4133333,
            "lon": -5.073961
        },
        {
            "eventTime": "2019-07-18T13:16:04",
            "eventId": 21,
            "lat": 50.4132803,
            "lon": -5.0739765
        },
        {
            "eventTime": "2019-07-18T13:17:04",
            "eventId": 21,
            "lat": 50.4133433,
            "lon": -5.0739588
        },
        {
            "eventTime": "2019-07-18T13:18:04",
            "eventId": 21,
            "lat": 50.413306999999996,
            "lon": -5.0739355999999995
        },
        {
            "eventTime": "2019-07-18T13:19:04",
            "eventId": 21,
            "lat": 50.4133013,
            "lon": -5.073953599999999
        },
        {
            "eventTime": "2019-07-18T13:20:04",
            "eventId": 21,
            "lat": 50.413309299999995,
            "lon": -5.073988099999999
        },
        {
            "eventTime": "2019-07-18T13:21:04",
            "eventId": 21,
            "lat": 50.4133146,
            "lon": -5.0739618
        },
        {
            "eventTime": "2019-07-18T13:22:04",
            "eventId": 21,
            "lat": 50.413287999999994,
            "lon": -5.0739141
        },
        {
            "eventTime": "2019-07-18T13:23:04",
            "eventId": 21,
            "lat": 50.4132981,
            "lon": -5.0739008
        },
        {
            "eventTime": "2019-07-18T13:24:04",
            "eventId": 21,
            "lat": 50.413283,
            "lon": -5.07386
        },
        {
            "eventTime": "2019-07-18T13:25:03",
            "eventId": 52,
            "lat": 50.413303,
            "lon": -5.0738673
        },
        {
            "eventTime": "2019-07-18T13:26:01",
            "eventId": 60,
            "lat": 50.4135111,
            "lon": -5.0737745
        },
        {
            "eventTime": "2019-07-18T13:27:02",
            "eventId": 130,
            "lat": 50.415140099999995,
            "lon": -5.073355299999999
        },
        {
            "eventTime": "2019-07-18T13:28:00",
            "eventId": 125,
            "lat": 50.4139743,
            "lon": -5.0697981
        },
        {
            "eventTime": "2019-07-18T13:29:01",
            "eventId": 21,
            "lat": 50.4186421,
            "lon": -5.0698473
        },
        {
            "eventTime": "2019-07-18T13:30:09",
            "eventId": 153,
            "lat": 50.418105999999995,
            "lon": -5.0624391
        },
        {
            "eventTime": "2019-07-18T13:30:50",
            "eventId": 21,
            "lat": 50.4185011,
            "lon": -5.0581641
        },
        {
            "eventTime": "2019-07-18T13:31:59",
            "eventId": 21,
            "lat": 50.417915099999995,
            "lon": -5.0517363
        },
        {
            "eventTime": "2019-07-18T13:33:02",
            "eventId": 131,
            "lat": 50.4194111,
            "lon": -5.0496058
        },
        {
            "eventTime": "2019-07-18T13:35:34",
            "eventId": 51,
            "lat": 50.4194153,
            "lon": -5.049543
        }
    ]
}
方法,该方法返回基于时间的已排序和舍入消息列表

private List<TrackingMessage> findTrackingMessageDatesToNearestMinute(List<TrackingMessage> filteredTrackingMessages) {
    return filteredTrackingMessages.stream()
            .sorted(orderByClosestToMinute)
            .filter(JourneyServiceUtil.distinctByKey(x -> roundToClosestMinute(x)))
            .sorted(comparing(TrackingMessage::getEventTime))
            .collect(Collectors.toList());
  }
  private LocalDateTime roundToClosestMinute(TrackingMessage trackingMessage) {
    return DateTimeUtils.toLocalDateTime(DateUtils.round(trackingMessage.getEventTime(), Calendar.MINUTE));
  }
删除重复项的功能

  public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return t -> seen.add(keyExtractor.apply(t));
  }
如您所见(底部),我们在13:30内有两次{2019-07-18T13:30:502019-07-18T13:30:09}

从技术上讲,我希望选择2019-07-18T13:30:09,因为它最接近一分钟(9秒后,另一个是10秒)

此外,如果您查看响应中的时间,则时间为秒,不向下舍入


如果还不清楚,请不要犹豫,继续提问。

我认为问题之一可能是这一行:

.filter(JourneyServiceUtil.distinctByKey(x -> roundToClosestMinute(x)))
通过四舍五入到最接近的分钟来设置关键点。日期时间,
2019-07-18T13:30:09
2019-07-18T13:30:50
将四舍五入到不同的分钟,
13:30:00
13:31:00
。因此,它们将具有不同的键,您将在结果中同时获得这两个键。你们可能想在这里使用地板


还有,你说结果不是四舍五入的。过滤器将键设置为向下取整对象的
eventTime
值;但是,它使对象保持不变。

您似乎想要的是计算从一分钟开始经过的秒数。在你的例子中,13:30:09是分钟后9秒,13:30:50是分钟后50秒

要计算您是否可以使用此方法,请执行以下操作:

public static int distanceToMinute(LocalDateTime t) {
  LocalDateTime minute = t.truncatedTo(ChronoUnit.MINUTES);
  return (int) ChronoUnit.SECONDS.between(minute, t);
}
对于您所给出的两个示例,它将按预期返回9和50

下一步是按分钟对时间进行分组,如:

List<LocalDateTime> times = ...
Map<LocalDateTime, List<LocalDateTime>> timesByMinute = times.stream()
                    .collect(Collectors.groupingBy(t -> t.truncatedTo(ChronoUnit.MINUTES)));
列表时间=。。。
Map timesByMinute=times.stream()
.collect(收集器.groupingBy(t->t.truncatedTo(ChronoUnit.MINUTES));
然后将每个列表缩减为最接近一分钟的元素:

public static LocalDateTime bestTime(List<LocalDateTime> times) {
  return times.stream()
           .sorted((t1, t2) -> Integer.compare(distanceToMinute(t1), distanceToMinute(t2)))
           .findFirst().get();
}    
public静态LocalDateTime最佳时间(列表时间){
返回时间。stream()
.sorted((t1,t2)->Integer.compare(distanceToMinute(t1),distanceToMinute(t2)))
.findFirst().get();
}    

谢谢,你能举个例子说明你在代码中的意思吗?什么是
DateTimeUtils.toLocalDateTime
DateUtils.round
?DateTimeUtils.toLocalDateTime将日期转换为LocalDateTime。DateUtils是apache库,它将时间舍入到最接近的分钟、小时或您指定的任何时间
public static LocalDateTime bestTime(List<LocalDateTime> times) {
  return times.stream()
           .sorted((t1, t2) -> Integer.compare(distanceToMinute(t1), distanceToMinute(t2)))
           .findFirst().get();
}