# How to parse time range input?

In a program I'm working on, i need the user to input time ranges, such as 2002-2003, or 1999- (implied present), or -2000 (before 2000).

I have an ArrayList of objects, and so the user might put it the title of books, including some information (one of these must be the date it was published). They can then search for a specific book, and time range is one of the ways to do it.

So i've taken in the date range they want as a String, and I have the date stored in my object as a integer. I know the cases, and I've tried to cover all the cases, but am having problems with the '-2010' and '2010-', and the '2010' cases.

The cases, as far as I can tell are: -2010 2010 2010-2011 2011-

could anyone suggest a basic algorithm, or perhaps outline some useful functions?

My idea was that by the end of the parsing, i should have a minimum and maximum date, such that i can look at a particular book, and ask, is the date it provided bigger than the minimum, and smaller than the maximum? But i still need to parse the ranges.

Thanks for the help everyone.

Check if the first character is a -. Then check if the last character is a -. If it is neither of those cases, split at the - (use the String class's split method).

As much as I usually abhor regular expressions this is a great place for using them. You get data validation as well as parsing all in one shot with the correct use of grouping.

^(\d{4})?(-)?(\d{4})?\$ will give you 3 output groups, you check each one to see if you got a value and make decisions based on that, and as a bonus you are guaranteed that they are 4 digit numbers. Look at the groups on the Rubular page I link to. If you have a value in group 1 then that is the start year, a "-" in group two then it is a range, a value in group 3 an end range. Makes the logic really simple and you don't have to do all that silly string manipulation and Integer testing that other solutions suggest.

Since this is homework, here is something to kick start your thinking, how to use the Pattern and Matcher, I am not going to do the entire thing for you.

```import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main
{
public static void main(String[] args)
{
final List<String> inputs = Arrays.asList("1999-", "-2010", "1990-2000", "1967");

final Pattern p = Pattern.compile("^(\\d{4})?(-?)(\\d{4})?\$");
int count = 0;
for (final String input : inputs)
{
final Matcher m1 = p.matcher(input);
m1.find();
System.out.format("Input: %d\n", count++);
for (int i=1; i <= m1.groupCount(); i++)
{
System.out.format("\tGroup %d = %s\n", i, m1.group(i));
}
}
}
}
```

Here is the expected output:

```Input: 0
Group 1 = 1999
Group 2 = -
Group 3 = null
Input: 1
Group 1 = null
Group 2 = -
Group 3 = 2010
Input: 2
Group 1 = 1990
Group 2 = -
Group 3 = 2000
Input: 3
Group 1 = 1967
Group 2 =
Group 3 = null
```

How it works:

^ - start at the beginning of the line (\d{4})? - this looks for exactly 4 digits \d and the () says group what you find, ? means this group is optional for a match, group will == null (-)? - this looks for the dash, ? makes it optional, () groups the results at above (\d{4})? - this looks for exactly 4 digits \d and the () says group what you find, ? means this group is optional for a match, group will == null \$ - matches the end of the line

Exercise left for the reader: The two cases it doesn't "validate" for is an empty string and "-", both of which should be considered "special" cases depending on what you want your business logic to be.