【问题标题】:Comparing dates as strings in Java在 Java 中将日期与字符串进行比较
【发布时间】:2018-09-05 10:43:11
【问题描述】:

我无法将日期作为字符串进行比较。我需要遍历一个集合并将每个对象的日期值与作为参数传递的 2 个日期进行比较。日期都存储为字符串,并且需要以这种方式保存。

众所周知,日期将全部格式化为YYYY-MM-DD。下面是我的意思的一个简单例子。谢谢大家!

public ArrayList<Object> compareDates(String dateOne, String dateTwo) {
    for(Object object : objectCollection) {
        String objectDate = object.getDate();
        if(objectDate.equals(dateOne) || objectDate.equals(dateTwo)) { // Unsure of how to determine if the objects date is inbetween the two given dates
            //add object to collection
        }
    }
return  collection;
}

【问题讨论】:

  • 为什么要将日期作为字符串进行比较?有很多工具可以轻松准确地比较日期,为什么不使用这些工具呢?
  • 在比较之前转换为日期对象是唯一合理的方法
  • 如果你真的想坚持Strings,那么用"-"分割它们并比较分离的值。您可能必须将它们转换为 int 然后...
  • 也许您可以使用SimpleDateFormat 从您的字符串中制作具体的Date 对象并进行比较。
  • 上面的例子看起来并不完整,即它不包含objectCollection 变量的定义。就像@Stultuske 说的那样,为什么将它们作为字符串进行比较?您可以将它们解析为可比较的 Calendars 或 Dates。

标签: java string string-comparison


【解决方案1】:

由于您的日期采用YYYY-MM-DD 格式,因此可以使用字典比较来确定两个日期之间的顺序。因此,您可以只使用String.compareTo() 方法来比较字符串:

int c1 = objectDate.compareTo(dateOne);
int c2 = objectDate.compareTo(dateTwo);
if ((c1 >= 0 && c2 <= 0) || (c1 <= 0 && c2 >= 0)) {
    // objectDate between dateOne and dateTwo (inclusive)
}

如果保证dateOne &lt; dateTwo,那么你可以直接使用(c1 &gt;= 0 &amp;&amp; c2 &lt;= 0)。要排除日期范围,请使用严格的不等式(&gt;&lt;)。

【讨论】:

  • 同意你的回答。但是,我问题的作者做的不是比较字符串,而是如何根据 String.compareTo() 表达/实现“之间”关系,它返回一个 int。也许您也可以扩展您的答案以解决这部分问题。 (@ernest_k的回答刚刚贴出来,加了这么一个解释)
  • 谢谢你!在你和@ernest_k 的回答之间,现在很有意义!
【解决方案2】:

由于您的日期采用 yyyy-MM-dd 格式,因此 String 的 compareTo 应该返回一致的结果:

if(objectDate.compareTo(dateOne) >= 0 && objectDate.compareTo(dateTwo) <= 0)

这大致检查(概念上):objectDate &gt;= dateOne &amp;&amp; objectdate &lt;= dateTwo

这只是如果必须使用字符串的方法。不过,更好的方法是将字符串转换为日期对象并执行基于日期的比较。

【讨论】:

  • 我不认为转换到日期更好。字符串比较快,转换慢,如果OP要保持日期不变,那就意味着每次都要转换。
  • 也许你可以强调你的实现只有在dateOnedateTwo之前才有效。
  • @RealSkeptic 不是真的。这很容易,因为它只是本地日期值。如果引入时区、偏移、夏令时复杂性怎么办?日期/时间类型显然更合适。
  • 比较字符串只是通过它们一次。转换它们需要通过它们一次,然后还要对日期和月份进行有效性检查。
  • @RealSkeptic 不争论你的观点。你说的是性能,我说的是准确性。但你有一个正确的观点,没有争议。
【解决方案3】:

这是您需要遵循的程序:

  1. 将 String dateOne、String dateTwo 都转换为 java.time.LocalDate
  2. 遍历您的 ArrayList 并将索引字符串转换为 java.time.LocalDate

    注意:您需要接受ArrayList&lt;String&gt; 才能将字符串解析为LocalDate,而不是ArrayList&lt;Object&gt;

  3. 进行比较

Refer to the documentation实现比较逻辑。

您可以参考this link for additional help

【讨论】:

    【解决方案4】:

    如果 dateOne 在 dateTwo 之前,如果您喜欢在两者之间有日期,则可以使用以下比较。

        public ArrayList<Object> compareDates(List<Object> objectCollection, String start, String end) {
            ArrayList<Object> dateBetween = new ArrayList<>();
            for(Object object : objectCollection) {
                LocalDate objectDate = parseDate(object.getDate());
                if( !objectDate.isBefore(parseDate(start)) && !objectDate.isAfter(parseDate(end))) {
                    dateBetween.add(object);
                }
            }
            return dateBetween;
        }
    
        private LocalDate parseDate(String date) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-DD");
            return LocalDate.parse(date, formatter);
        }
    

    【讨论】:

    • 在每次循环迭代时解析 startend 可能会很昂贵...
    • 是的,但是将日期作为字符串比较对我来说有点棘手。
    • 您可以在方法开始时将它们解析为日期一次。只是一个想法。
    • 这是否会提高性能,毕竟您需要解析相同数量的日期?
    • 如果集合中有 N 个项目,使用当前代码,您调用 parseDate 3 次(object.getDate 1 次,start 1 次,end 一次)迭代,所以总共有3*N 次。但只需要N+2 次(startend 一次且仅一次,N 个对象中的每一个都需要一次)。这是很多不必要的DateTimeFormatter 实例化和调用parse 如果您碰巧有一个庞大的列表。
    猜你喜欢
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多