Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if month or day or year is in range of two dates in string format

I originally asked this question here with a different use case but now I realize I could have more cases for this problem.

I have a filter that is a String and can only accept 3 date-formats - YYYY, YYYY-MM, YYYY-MM-DD.

I want to check if the requested String is in the range of two string-valued dates.

Let's say, I have two dates strings which can be in any of the above 3 date-formats


Use case 1

Start date: 2010-05-15 & end date: 2020-05.

All the below requested String are In range results:

2010, 2020, 2010-05, 2020-05, 2020-05-22, 2010-05-15, 2010-05-22, 2015-02-25

All the requested String below are NOT in range

2009, 2021, 2010-04, 2020-06, 2010-05-14, 2020-06-01


Use case 2

Start date: 2010 & end date: 2020-05-15

All the below values are In range results:

2010, 2020, 2010-05, 2020-05, 2010-05-22, 2010-01-01, 2020-05-15, 2015-02-25

All the values below are NOT in range

2009, 2021, 2020-06, 2020-05-16, 2020-06-01


Use case 3

Start date: NULL & end date: 2020-05

All the requested dates which are before 2020-05-31 are In range results:

All the values after 2020-05-31 are NOT in range.


Use case 4

Start date: 2010-05-15 & end date: NULL

All the requested dates which are after 2010-05-15 are In range results:

All the values before 2010-05-15 are NOT in range.


I am using Java time to check if a date is before or after the given dates, but in my case, I have a string as a request date, start date, and end date that could be in any of the 3 date-formats.

I am not sure if this is a valid solution but this is what I am thinking

Simply break all the dates (requested, start, & end) into numbers and compare requested year with years in start & end, if months in requested date is available and also available in the start and end then compare if the month is in range, and same for the dates.

Can someone please help to solve this problem?

like image 748
AMagic Avatar asked Dec 19 '25 21:12

AMagic


2 Answers

Convert all string inputs to LocalDate objects

Stop thinking in strings. The strings are merely for user-interface and for serializing values to storage. When your app is running, you should be performing your logic using objects, java.time objects, LocalDate ultimately.

Convert all inputs to LocalDate.

Check for the length of the input.

if( input.length() = 4 ) {…}

If the input in 4 characters long, parse as a Year. Trap for exception thrown in case faulty input gets past your filter. From the year, get a LocalDate by calling atDay.

try{
    Year year = Year.parse( "2020" ) ; 
     LocalDate ld = year.atDay( 1 ) ;
} catch ( DateTimeParseException e ) {
    …
}

If input is seven characters, parse as a YearMonth. Form that get a LocalDate via the atDay method.

try{
    YearMonth YearMonth = YearMonth.parse( "2020-05" ) ; 
     LocalDate ld = yearMonth.atDay( 1 ) ;
} catch ( DateTimeParseException e ) {
    …
}

If input is 10 characters, parse as a LocalDate.

try{
    LocalDate localDate = LocalDate.parse( "2020-05-23" ) ; 
} catch ( DateTimeParseException e ) {
    …
}

Once you have all your LocalDate objects in place, compare. Use Half-Open approach consistently when defining your spans of time. The beginning is inclusive while the ending is exclusive.

Tip: “not before” is a shorter way of asking “is equal to or later”.

( ! target.isBefore( start ) ) && target.isBefore( stop ) 
like image 99
Basil Bourque Avatar answered Dec 21 '25 09:12

Basil Bourque


As your dates are in the yyyy-MM-dd format, you should be able to perform string comparison, making sure that you only compare strings of the same length (to take care of your rules about comparing dates of different lengths):

private static boolean isDateInRange(String startDate, String endDate, String date) {
    return (null == startDate || compareDateString(startDate, date) <= 0)
            && (null == endDate || compareDateString(date, endDate) <= 0);
}

private static int compareDateString(String date1, String date2) {
    if (date1.length() == date2.length())
        return date1.compareTo(date2);

    int length = Math.min(date1.length(), date2.length());
    return date1.substring(0, length).compareTo(date2.substring(0, length));
}

And you can check in the following way:

String startDate = "2010-05-15";
String endDate = "2020-05";
String date = "2020-06";

boolean inRange = isDateInRange(startDate, endDate, date);
like image 42
ernest_k Avatar answered Dec 21 '25 09:12

ernest_k