【问题标题】:Java Closest LocalDateJava 最近的本地日期
【发布时间】:2021-08-18 09:31:21
【问题描述】:

我有一个 LocalDate 对象列表 (dates),我想在列表中找到最接近给定日期 (milestoneDate) 的条目。

最接近意味着日期可能在milestoneDate 之前或之后,但差异最小。例如,milestoneDate 前一天的某事会比milestoneDate 后 2 天的某事更接近。

到目前为止,我最好的想法是将dates 中的值转换为EpochSecond,然后获取该值与milestoneDatetoEpochSecond 之间的差的绝对值,然后选择最小值。

long milestoneSeconds = milestoneDate.atStartOfDay().toEpochSecond(ZoneOffset.UTC);

return dates.stream().sorted((x, y) -> {
            long xDiff = Math.abs(x.atStartOfDay().toEpochSecond(ZoneOffset.UTC) - milestoneSeconds);
            long yDiff = Math.abs(y.atStartOfDay().toEpochSecond(ZoneOffset.UTC) - milestoneSeconds);
            return (int) (xDiff - yDiff);
        }).findFirst();

虽然我怀疑这会起作用,但感觉有点沉重。有没有更优雅的方法来做到这一点?

【问题讨论】:

    标签: java localdate


    【解决方案1】:

    您可以直接找到里程碑日期与列表中每个日期之间的天数。无需转换为纪元秒。

    dates.stream().min(Comparator.comparingLong(
        x -> Math.abs(ChronoUnit.DAYS.between(x, milestoneDate))
    ));
    

    请注意,在某些情况下,可能有 2 个日期同样接近里程碑日期 - 一个在它之前,一个在它之后。如果您有偏好在这种情况下选择哪一个,您可以在比较器中添加thenComparing

    // gets the date before
    dates.stream().min(Comparator.<LocalDate>comparingLong(
        x -> Math.abs(ChronoUnit.DAYS.between(x, milestoneDate))
    ).thenComparing(Comparator.naturalOrder()));
    
    // gets the date after
    dates.stream().min(Comparator.<LocalDate>comparingLong(
        x -> Math.abs(ChronoUnit.DAYS.between(x, milestoneDate))
    ).thenComparing(
        Comparator.<LocalDate>naturalOrder().reversed()
    ));
    

    有点遗憾的是Java不能推断类型参数:(

    【讨论】:

    • 也可以有关系。 OP 应相应地解决或合并任何平局规则。
    • @Atmas 谢谢你的提醒!我通常会想很多关于日期和时间的边缘情况,但这次我出于某种原因没有考虑到这一点。
    • 很高兴能为您提供帮助!我相信你最终会来的。
    • 为什么要对整个流进行排序? Stream 有一个 min 方法,我认为它就可以达到目的。
    • @OleV.V.你是对的,这更简洁。虽然我确实想知道 sorted(...).findFirst() 是否会像 min 一样是 O(n),因为流是懒惰评估的......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 2021-01-01
    • 2012-03-01
    相关资源
    最近更新 更多