【问题标题】:When using .compareTo to compare dates, why doesn't it take Months into account? [duplicate]使用 .compareTo 比较日期时,为什么不考虑月份? [复制]
【发布时间】:2019-12-23 11:16:18
【问题描述】:

我正在显示 ArrayList 中的某些日期,并使用格式化程序将日期缩短为“dd/MM”,但是当我比较日期时,它不适用于月份。例如17/08 IS 在 19/08 之前,21/08 IS 在 19/08 之后,但 17/09 IS 在 19/08 之前。我的程序实现的是显示未来 8 天内的任何日期。

我已尝试使用 .compareTo 来执行此操作,它在一个月内有效,但在几个月之间无效。我知道它在比较字符串,我认为这是问题所在,但我不知道如何解决它

SimpleDateFormat formatter = new SimpleDateFormat("dd/MM");
Calendar cal = Calendar.getInstance();
Date comDate = new Date();
cal.add(Calendar.DATE, 8);
//this adds days to the calender
comDate = cal.getTime();
String strDate = formatter.format(comDate);
//this applies the edited calender to the date I'm comparing to

ArrayList<String> arDat = new ArrayList<String>();
arDat.add("15/08");
arDat.add("15/09");
arDat.add("30/08");

Date recDate = new Date();

for (int i=0; i < arDat.size(); i++){
    recDate = formatter.parse(arDat(i));
    String strRecDate = formatter.format(recDate);
    if (strRecDate.compareTo(strDate) < 0 {
        showToast(recDate);
    }
}

我希望它只显示 15/08,但它显示 15/08 和 15/09

【问题讨论】:

标签: java date simpledateformat date-formatting compareto


【解决方案1】:

java.time.MonthDay

您可以使用现代的java.time 类,而不是使用过时的Calendar 类。如果您对日期和月份感兴趣,可以使用MonthDay 类,它是 compareTo 方法:

MonthDay monthDay = MonthDay.of(8, 15);
MonthDay monthDay1 = MonthDay.of(9, 15);
System.out.println(monthDay.compareTo(monthDay1));

给:

-1

您可能会发现MonthDay::isBeforeisAfterequals 方法更方便。

java.time 类内置于 Java 8 及更高版本中。对于 Java 6 和 Java 7,请将 ThreeTen-Backport 库添加到您的项目中。

【讨论】:

  • 我知道,但我目前仅限于使用非常旧的 java,因为我使用的是旧的工作笔记本电脑
  • @TomPallaghy 然后将ThreeTen-Backport 库添加到您的项目中,其中大部分 java.time 功能都向后移植到 Java 6 和 Java 7。非常值得麻烦,因为遗产真的是那么糟糕,糟糕,糟糕透顶。
【解决方案2】:

当您格式化时,它会转换为String。您正在格式化和比较。因此它正在进行String 比较。因此,结果。

如果你想要预期的结果,你必须比较Date对象。我已修改您的代码以比较 StringsDates

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

public class CompareDates {
    public static void main(String[] args) throws Exception {
        SimpleDateFormat formatter = new SimpleDateFormat("dd/MM");
        Calendar cal = Calendar.getInstance();
        Date comDate = new Date();
        cal.add(Calendar.DATE, 8);
        //this adds days to the calender
        comDate = cal.getTime();
        //this applies the edited calender to the date I'm comparing to

        ArrayList<String> arDat = new ArrayList<String>();
        arDat.add("15/08");
        arDat.add("15/09");
        arDat.add("30/08");

        Date redDate = new Date();
        for (int i = 0; i < arDat.size(); i++) {
            Date recDate = formatter.parse(arDat.get(i));
            if (formatter.format(recDate).compareTo(formatter.format(comDate)) < 0) {
                System.out.println("String comparison result: " + recDate);
            }
            if (recDate.compareTo(formatter.parse(formatter.format(comDate))) < 0) {
                System.out.println("Date comparison result: " + recDate);
            }
        }
    }
}

这是预期的输出(与日期比较时仅打印 8 月 15 日):

String comparison result: Sat Aug 15 00:00:00 UTC 1970
Date comparison result: Sat Aug 15 00:00:00 UTC 1970
String comparison result: Tue Sep 15 00:00:00 UTC 1970

注意: 我没有直接比较 recDatecompDate 因为 compDate 是当年 (2019) 而 recDate 是默认年份 (1970 )。因此,首先我将compDate 格式化为去掉年份、时间等,然后在比较之前再次解析为Date

【讨论】:

  • 在多年前采用 JSR 310 时,这里使用的糟糕的日期时间类已被 java.time 类所取代。在 the Answer by michalk 中找到现代解决方案.
  • 是的,强烈建议切换到 `java.time` 类。
【解决方案3】:

您正在比较日期的字符串。 Calendar 类实现了Comparable 接口。它会正确比较。

https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

所以你的代码在固定版本中:

for (int i=0; i < arDat.size(); i++){
    recDate = formatter.parse(arDat(i));
    if (recDate.compareTo(comDate) < 0 {
        showToast(recDate);
    }
}

【讨论】:

  • 为什么它是否适用于排除 30/08 以及如何实现与日历类的比较
猜你喜欢
  • 2014-06-30
  • 2019-12-06
  • 1970-01-01
  • 2013-09-01
  • 2020-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-24
  • 1970-01-01
相关资源
最近更新 更多