2

I'm displaying certain dates from an ArrayList and using a formatter to shorten the date to "dd/MM" but when I compare the dates it doesn't work for the months. e.g. 17/08 IS before 19/08, 21/08 IS after 19/08 but 17/09 IS before 19/08. What my program achieves is showing any of the dates within the next 8 days.

I've tried using .compareTo to do this and it works within a month but not going between months. I know it's comparing strings and I think that's the problem but I don't know how to get around it

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);
    }
}

I want it to just show 15/08 but it shows 15/08 and 15/09

  • you used new library in java 8 date time api – Ng Sharma Aug 17 '19 at 12:53
  • https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html – Ng Sharma Aug 17 '19 at 12:54
  • 1
    related Answer : https://stackoverflow.com/questions/2592501/how-to-compare-dates-in-java – Ng Sharma Aug 17 '19 at 12:57
  • 1
    FYI, the troublesome date-time classes such as `java.util.Date`, `java.util.Calendar`, & `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) classes. Most *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android (<26) in [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP). See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Aug 17 '19 at 15:35
  • I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `MonthDay` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Aug 20 '19 at 19:07

3 Answers3

3

java.time.MonthDay

Instead of using outdated Calendar class you can use modern java.time classes. If you are interested in days and months you can use MonthDay class and it's compareTo method :

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

gives :

-1

You might find more convenient the methods MonthDay::isBefore, isAfter, and equals.

The java.time classes are built into Java 8 and later. For Java 6 and Java 7, add the ThreeTen-Backport library to your project.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Michał Krzywański
  • 15,659
  • 4
  • 36
  • 63
  • I know but I'm limited to a very old java at the moment because I'm using an old work laptop – Tom Pallaghy Aug 17 '19 at 13:02
  • @TomPallaghy Then add the [*ThreeTen-Backport*](https://www.threeten.org/threetenbp/) library to your project, where most of the *java.time* functionality is back-ported to Java 6 and Java 7. Well worth the bother, as the legacy really are that bad, terrible, bloody awful bad. – Basil Bourque Aug 17 '19 at 15:34
0

You are comparing the strings of the date. The Calendar class implements the Comparable interface. It will compare correctly.

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

So your code in the fixed version:

for (int i=0; i < arDat.size(); i++){
    recDate = formatter.parse(arDat(i));
    if (recDate.compareTo(comDate) < 0 {
        showToast(recDate);
    }
}
Michiel Leegwater
  • 1,172
  • 4
  • 11
  • 27
0

When you format it converts to String. You are formatting and comparing. Hence it is doing String comparison. Hence, the result.

If you want the expected result, you must compare Date objects. I have modified your code to compare both Strings and Dates.

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);
            }
        }
    }
}

And here is the output as expected (only Aug 15 is printed when compared as Date):

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

Note: I did not directly compare recDate with compDate as compDate is of the current year (2019) and recDate is of default year (1970). Hence, first I formatted compDate to strip off the year, time, etc. and then again parsed to Date before comparison.

fiveelements
  • 3,649
  • 1
  • 17
  • 16
  • The terrible date-time classes used here were supplanted years ago by the *java.time* classes as of the adoption of JSR 310. Find the modern solution in the [the Answer by michalk](https://stackoverflow.com/a/57536487/642706). – Basil Bourque Aug 17 '19 at 15:35
  • Yes, switching to ` java.time` classes is highly recommended. – fiveelements Aug 17 '19 at 15:37