有没有更好的比较日期的方法

问题描述 投票:0回答:6

我正在尝试比较两个日期。 日期作为字符串从数据库导入,可能为空也可能不为空

这是我的代码

private String compareDates(String date1, String date2)
    {
        String earliestDate = null;
//        date2 is null and date1 is null
//            earliest = “not seen yet”
        if (date2 == null && date1 == null)
        {
            earliestDate = "not seen yet";
        }
//        date2 is null and date1 is not null
//            earliest = date1
        if (date2 == null && date1 != null)
        {
            earliestDate = date1;
        }
//        date2 is not null and date1 is null
//            earliest = date2
        if (date2 != null && date1 == null)
        {
            earliestDate = date2;
        }
//        date2 is not null and date1 is not null
//            compare dates
        if (date2 != null && date1 != null)
        {
            LocalDate LDdate1 = LocalDate.parse(date1);
            LocalDate LDdate2 = LocalDate.parse(date2);
            if (LDdate1.isBefore(LDdate2) || LDdate1.isEqual(LDdate2))
            {
                earliestDate = LDdate1.toString();
            }
            else
            {
                earliestDate = LDdate2.toString();
            }
        }
        return earliestDate;
    }

此代码为我提供了正确的输出,即最早的日期,或者如果两个日期都为空,则为“尚未看到”,但我想知道是否有更好/更有效的方法。

我想使用 switch 语句是一种选择,但这会更好还是只是采用不同的方法?

数据库中的数据仅包含大约 200 个日期,因此它不会处理大量数据,只是我有兴趣编写更好的代码

java algorithm date-comparison
6个回答
1
投票

如果日期采用标准本地格式并按 YYYY MM DD 排序

"2018-01-24"

为什么要费力去解析呢?只需进行字符串比较即可。速度快了大约 100 倍,也更简单。

    public static String compareDatesStr(String date1, String date2) {
        if (date1 == null)
            if (date2 == null)
                return "not seen yet";
            else
                return date2;
        else if (date2 == null)
            return date1;
        else
            return date1.compareTo(date2) > 0 ? date2 : date1;
    }

一些不科学的性能比较:

    private static String compareDatesParse(String date1, String date2) {
        String earliestDate;
        if (date1 == null) {
            if (date2 == null) {
                earliestDate = "not seen yet";
            }
            else {
                earliestDate = date2;
            }
        }
        else {
            if (date2 == null) {
                earliestDate = date1;
            }
            else {
                LocalDate LDdate1 = LocalDate.parse(date1);
                LocalDate LDdate2 = LocalDate.parse(date2);
                if (LDdate1.isAfter(LDdate2)) {
                    earliestDate = date2;
                }
                else {
                    earliestDate = date1;
                }
            }
        }
        return earliestDate;
    }

    public static void testDateComp(){
        String[] dates = {"2020-10-30", "2020-10-29", "1990-10-30", "2021-06-01", null};
        String result = null;
        int loops = 400000;
        long start, end = 0;
        // System.out.println("Runs: " + (dates.length*dates.length*loops));


        start = System.currentTimeMillis();
        for (int i = 0; i < loops; i++) {
            for (String date1:dates) {
                for (String date2:dates) {
                    result = compareDatesStr(date1, date2);
                }
            }
        }
        end = System.currentTimeMillis();
        System.out.println("Runtime String: " + (end - start)+ "ms");

        start = System.currentTimeMillis();
        for (int i = 0; i < loops; i++) {
            for (String date1:dates) {
                for (String date2:dates) {
                    result = compareDatesParse(date1, date2);
                }
            }
        }
        end = System.currentTimeMillis();
        System.out.println("Runtime Parsing: " + (end - start) + "ms");
    }

10MM 方法执行:

Runtime String: 61ms
Runtime Parsing: 7361ms

1
投票

您可以减少一个 if 条件,如下所示:

private String compareDates(String date1, String date2) {
    String earliestDate = "not seen yet";
    if (!StringUtils.isEmpty(date2) && !StringUtils.isEmpty(date1)) {
        LocalDate LDdate1 = LocalDate.parse(date1);
        LocalDate LDdate2 = LocalDate.parse(date2);
        if (LDdate1.isBefore(LDdate2) || LDdate1.isEqual(LDdate2)) {
            earliestDate = LDdate1.toString();
        }
        else {
            earliestDate = LDdate2.toString();
        }
    } else if (!StringUtils.isEmpty(date2) && StringUtils.isEmpty(date1)) {
        earliestDate = LDdate2;
    } else if (StringUtils.isEmpty(date2) && !StringUtils.isEmpty(date1)) {
        earliestDate = LDdate1;
    }
    return earliestDate;
} 

1
投票

您可以使用自定义

Comparator
,它允许以声明式方式指定比较逻辑:

private String compareDates(String date1, String date2) {

    Comparator<String> c = Comparator.nullsLast(
                           Comparator.comparing(LocalDate::parse));

    int result = c.compare(date1, date2);

    return result == 0 && date1 == null ?
           "not seen yet"               :
           result <= 0                  ?
           date1                        :
           date2;
}

1
投票

除了一堆类似的 if 语句之外,还有其他一些选择。

  1. Comparator

    if (date1 == null && date2 == null) {
        return "not seen yet";
    }
    Comparator<String> c = Comparator.nullsLast((String a, String b) -> LocalDate.parse(a).compareTo(LocalDate.parse(b)));
    return c.compare(date1, date2) <= 0 ? date1 : date2;
    
  2. Stream::reduce
    使用
    Comparator

    return Stream.of(date1, date2)
        .filter(Objects::nonNull)
        .reduce((a, b) -> LocalDate.parse(a).compareTo(LocalDate.parse(b)) <= 0 ? a : b)
        .orElse("not seen yet");
    

对我来说,这两个选项都比你现在所拥有的可读性更好,但我会选择选项 1。人们可能会发现使用流有点矫枉过正,这在某种程度上是正确的。


0
投票

以下怎么样?

private String compareDates(String date1, String date2) {
    String earliestDate;
    if (date1 == null) {
        if (date2 == null) {
            earliestDate = "not seen yet";
        }
        else {
            earliestDate = date2;
        }
    }
    else {
        if (date2 == null) {
            earliestDate = date1;
        }
        else {
            LocalDate LDdate1 = LocalDate.parse(date1);
            LocalDate LDdate2 = LocalDate.parse(date2);
            if (LDdate1.isAfter(LDdate2)) {
                earliestDate = date2;
            }
            else {
                earliestDate = date1;
            }
        }
    }
    return earliestDate;
}

0
投票

日期以字符串形式从数据库导入……

第一点:不要这样做。从数据库中以

LocalDate
对象的形式获取日期,并在程序中按此方式处理它们。有关如何从 SQL 数据库获取
LocalDate
,请参阅底部的链接。

接下来,我将使用流管道来查找较早的管道:

    // Some example dates
    LocalDate date1 = null;
    LocalDate date2 = LocalDate.of(2020, Month.OCTOBER, 24);
    
    String earlierDate = Stream.of(date1, date2)
            .filter(Objects::nonNull)
            .min(LocalDate::compareTo)
            .map(LocalDate::toString)
            .orElse("Not seen yet");
    System.out.println(earlierDate);

输出:

2020-10-24

链接:问题在 SQL 数据库(例如 H2)中插入和获取 java.time.LocalDate 对象

© www.soinside.com 2019 - 2024. All rights reserved.