Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

Sometimes, we need to parse date strings that could be provided in a number of different formats, like  ‘yyyy/MM/dd’, ‘yyyy-MM-dd’, or ‘dd-MM-yyyy’. In this tutorial, we’ll demonstrate some options that we have for parsing different patterns of dates. First, we’ll try to solve parsing problems using standard Java libraries: SimpleDateFormat and DateTimeFormatterBuilder. Then, we’ll examine third-party libraries Apache Commons DateUtils and Joda Time.

2. Using SimpleDateFormat

First, let’s use Java’s SimpleDateFormat to parse dates with multiple formats. In the beginning, we define a list of possible date formats and loop through them all until a format matches our String. When one matches, we return a java.util.Date. Otherwise, we return null:

public static Date parseDate(String dateString, List<String> formatStrings) {
    for (String formatString : formatStrings) {
        try {
            return new SimpleDateFormat(formatString).parse(dateString);
        } catch (ParseException e) {
        }
    }
    return null;
}

This method has its own pros and cons. On the plus side, no external libraries are necessary and the implementation is simple and straightforward.

However, we need to know all the potential matching date formats in advance. Also, there’s no date validation. We could parse dates that are formatted according to a matching pattern but are still invalid. For example, if we parse ‘2022-40-40’, SimpleDateFormater will return ‘2025-05-10’.

Let’s see an example showing that parsing this invalid date returns something unexpected:

@Test
public void whenInvalidInput_thenGettingUnexpectedResult() {
    SimpleParseDate simpleParseDate = new SimpleParseDate();
    String date = "2022-40-40";
    assertEquals(
        "Sat May 10 00:00:00 EEST 2025",
        simpleParseDate.parseDate(date, Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd"))
    );
}

3. Using DateTimeFormatterBuilder

SimpleDateFormat is the original implementation in Java, and java.util.Date has many deprecated methods, so the better option is to use DateTimeFormatterBuilder. Unlike SimpleDateFormatter, DateTimeFormatterBuilder can receive multiple date patterns and use them all to try to parse a given date. If there’s a pattern that matches, it’ll return the parsed date, otherwise, it’ll throw a DateTimeParseException:

public static LocalDate parseDate(String date) {
    DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ofPattern("[MM/dd/yyyy]" + "[dd-MM-yyyy]" + "[yyyy-MM-dd]"));
    DateTimeFormatter dateTimeFormatter = dateTimeFormatterBuilder.toFormatter();
    return LocalDate.parse(date, dateTimeFormatter);
}

Let’s use this formatter to parse some dates:

@Test
public void whenInvalidDate_thenAssertThrows() {
    assertEquals(
        java.time.LocalDate.parse("2022-12-04"),
        simpleDateTimeFormater.parseDate("2022-12-04")
    );
    assertThrows(DateTimeParseException.class, () -> simpleDateTimeFormater.parseDate("2022-13-04"));
}

4. Apache Commons DateUtils

Another option is to use the Apache Commons library, which provides a DateUtils helper. First, we need to include the Apache Commons Lang dependency:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

DateUtils works similar to DateTimeFormatterBuilder. We can feed it several date formats, and it’ll parse the date if one of the formats matches the string to be parsed:

DateUtils.parseDateStrictly("2022-12-29",new String[]{"yyyy/MM/dd", "dd/MM/yyyy", "yyyy-MM-dd"});

Let’s use DateUtils to parse invalid and valid dates:

@Test
public void whenDateIsCorrect_thenParseCorrect() {
    SimpleDateUtils simpleDateUtils = new SimpleDateUtils();
    assertNull(simpleDateUtils.parseDate("53/10/2014"));
    assertEquals("Wed Sep 10 00:00:00 UTC 2014", simpleDateUtils.parseDate("10/09/2014").toString());
}

5. Joda Time

Another third-party option is to use the Joda Time library. It’s worth knowing that Joda Time is the de facto standard date and time library for Java prior to Java SE 8. First, we need to include its dependency:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.12.5</version>
</dependency>

Let’s define the available patterns for DateTimeFormat:

public static LocalDate parseDate(String date) {
    List<String> patternList = Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd");
    for (String pattern : patternList) {
        try {
            return DateTimeFormat.forPattern(pattern).parseLocalDate(date);
        } catch (IllegalFieldValueException e) {
        }
    }
     return null;
}

Let’s write a test using Joda Time to parse some dates:

@Test
public void whenDateIsCorrect_thenResultCorrect() {
    SimpleDateTimeFormat simpleDateUtils = new SimpleDateTimeFormat();
    assertNull(simpleDateUtils.parseDate("53/10/2014"));
    assertEquals(LocalDate.parse("2014-10-10"), simpleDateUtils.parseDate("2014-10-10"));
}

6. Conclusion

In this article, we learned about our options for parsing dates with multiple formats using standard Java libraries. Additionally, we solved date parsing problems with third-party libraries: Apache Commons Lang and Joda Time.

As always, you can find these examples over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!