I am trying to parse some dates that are coming out of a document. It would appear users have entered these dates in a similar but not exact format.
here are the formats:
9/09
9/2009
09/2009
9/1/2009
9-1-2009
What is the best way to go about trying to parse all of these? These seem to be the most common, but I guess what is hanging me up is that if i have a pattern of "M/yyyy" wont that always catch before "MM/yyyy" Do I have to set up my try/catch blocks nested in a least restrictive to most restrictive way? it seems like it sure is going to take a lot of code duplication to get this right.
Here is the complete example (with main method) which can be added as a utility class in your project. All the format mentioned in SimpleDateFormate API is supported in the below method.
This solution checks all the possible formats before throwing an exception. This solution is more convenient if you are trying to test for multiple date formats.
If working in Java 1.8 you can leverage the DateTimeFormatterBuilder
See post: Java 8 Date equivalent to Joda's DateTimeFormatterBuilder with multiple parser formats?
What about just defining multiple patterns? They might come from a config file containing known patterns, hard coded it reads like:
For the modern answer I am ignoring the requirement to use
SimpleDateFormat
. While using this class for parsing was a good idea in 2010 when this question was asked, it is now long outdated. The replacement,DateTimeFormatter
, came out in 2014. The idea in the following is pretty much the same as in the accepted answer.This parses each of the input strings from the question into a year-month of
2009-09
. It’s important to try the two-digit year first since"M/y"
could also parse9/09
, but into0009-09
instead.A limitation of the above code is it ignores the day-of-month from the strings that have one, like
9/1/2009
. Maybe it’s OK as long as most formats have only month and year. To pick it up, we’d have to tryLocalDate.parse()
rather thenYearMonth.parse()
for the formats that included
in the pattern string. Surely it can be done.Matt's approach above is fine, but please be aware that you will run into problems if you use it to differentiate between dates of the format
y/M/d
andd/M/y
. For instance, a formatter initialised withy/M/d
will accept a date like01/01/2009
and give you back a date which is clearly not what you wanted. I fixed the issue as follows, but I have limited time and I'm not happy with the solution for 2 main reasons:getDateFormat()
method becoming a bit of a nightmare if you needed it to handle lots of other date formats.If I had to make something that could handle lots and lots of different date formats and needed to be highly performant, then I think I would use the approach of creating an enum which linked each different date regex to its format. Then use
MyEnum.values()
to loop through the enum and test withif(myEnum.getPattern().matches(date))
rather than catching a dateformatexception.Anway, that being said, the following can handle dates of the formats
'y/M/d' 'y-M-d' 'y M d' 'd/M/y' 'd-M-y' 'd M y'
and all other variations of those which include time formats as well: