2

I am having troubles comparing dates as strings. I am required to iterate through a collection and compare the date value of each object against 2 dates passed as parameters. The dates are all stored as strings and am required to keep them that way.

It is known that the dates will all be formatted YYYY-MM-DD. Below is a quick example of what I mean. Thanks all!

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;
}
7
  • 1
    why would you want to compare dates as Strings? there are tons of tools to make comparisons of dates easy and precise, why not use those? Commented Sep 5, 2018 at 10:47
  • 1
    convert to a date object before compare is the only sane method Commented Sep 5, 2018 at 10:49
  • If you really want to stick to Strings, then split them by "-" and compare the separated values. You may have to cast them to int then... Commented Sep 5, 2018 at 10:49
  • 1
    Maybe you can use the SimpleDateFormat to make concrete Date objects out of your string and compare these. Commented Sep 5, 2018 at 10:49
  • The example above doesn't look complete, i.e. it doesn't contain the defintion of the objectCollection variable. Like @Stultuske said, why compare them as streings? You can parse them in to Calendars or Dates which are comparable. Commented Sep 5, 2018 at 10:49

4 Answers 4

3

Since your dates are in the YYYY-MM-DD format, a lexicographic comparison can be used to determine the ordering between two dates. Thus, you can just use the String.compareTo() method to compare the strings:

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

If it is guaranteed that dateOne < dateTwo, then you can just use (c1 >= 0 && c2 <= 0). To exclude the date bounds, use strict inequalities (> and <).

Sign up to request clarification or add additional context in comments.

2 Comments

Agreed with your answer. However, I guess what the author of the question has trouble doing is not so much comparing the strings, but rather, how to express/implement a "between" relationship in terms of String.compareTo(), which returns an int. Maybe you could expand your answer to address this part too. (@ernest_k's answer was just posted, adding such an explanation)
Thank you for this! Between yours and @ernest_k's answer it makes a lot of sense now!
0

As your dates are in the yyyy-MM-dd format, then String's compareTo should return consistent results:

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

This roughly checks (conceptually): objectDate >= dateOne && objectdate <= dateTwo

That's just if one must use string's methods. A better approache, though, would be to convert the strings to date objects and perform a date-based comparisons.

6 Comments

I don't think conversion to date is better. String comparison is fast, conversion is slow, and if the OP is supposed to keep the dates as they are, it means converting every time.
Maybe you could stress that your implementation works only when dateOne is before dateTwo.
@RealSkeptic Not really. This is easy because it's just local date values. What if time zones, offsets, daylight savings complexities are introduced? Date/time types would clearly be more appropriate.
Comparing strings is just going through them once. Converting them requires going through them once, and then also doing validity checks for the day and month.
@RealSkeptic Not arguing your point. You're talking performance, I'm talking accuracy. But you've got a valid point, not disputing that.
|
0

Here is the procedure you need to follow:

  1. Convert both String dateOne, String dateTwo into java.time.LocalDate
  2. Iterate over your ArrayList and convert the indexed string into java.time.LocalDate

    Note: You need to accept ArrayList<String> in order to parse the string to LocalDate, not ArrayList<Object>

  3. Do the comparison

Refer to the documentation to implement the comparison logic.

You may refer to this link for additional help.

Comments

0

If dateOne is before dateTwo you can use following comparison if you like have date inbetween.

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

5 Comments

Parsing start and end at each loop iteration may be quiete expensive...
Yes, but comparing date as strings seems for me a bit tricky.
You could parse them, as dates, once at the start of the method. Just a thought.
Does this increase performance, after all you have the same number of dates to parse?
If you have N items in the collection, with the current code, you call parseDate 3 times (1 for object.getDate, one for start, once for end) on each iterations, so 3*N times total. But only N+2 times are necessary (once and only once for start and end, and once for each of the N objects). That is a lot of unnecessary DateTimeFormatter instanciation and calls to parse if you happen to have a huge list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.