Search code examples
javajava-11simpledateformatdate-formatdatetimeformatter

How to convert different date formats in JDK11 to dd-mm-yyyy format?


I have a use case where I have date in the following formats,

  1. 2023-05-09T05:55:07Z
  2. 2023-04-30
  3. 08-05-2023
  4. 2023-05-09 00:00:00
  5. 31-Dec-2021

Irrespective of the input format I have a requirement to convert it to dd-mm-yyyy format. How can I convert it in JDK11? I tried different libraries but got no luck.


Solution

  • You can iterate over known formats and skip ones that throw a DateTimeParseException.

    Note: If you are parsing just a date string into a LocalDateTime, you will need to build the formatter and specify that the time portion is optional.

    import java.time.LocalDateTime;
    import java.time.format.*;
    import java.time.temporal.ChronoField;
    import java.util.*;
    
    public class DateParser {
        public static void main(String[] args) {
            System.out.println(normalizeDate("2023-05-09T05:55:07Z")); // 2023-05-09
            System.out.println(normalizeDate("2023-04-30")); // 2023-04-30
            System.out.println(normalizeDate("08-05-2023")); // 2023-08-05
            System.out.println(normalizeDate("2023-05-09 00:00:00")); // 2023-05-09
            System.out.println(normalizeDate("31-Dec-2021")); // 2021-12-31
            System.out.println(normalizeDate("")); // null
        }
    
        public static String normalizeDate(String rawDateTimeString) {
            return Optional.ofNullable(parseDateString(rawDateTimeString))
                    .map(displayFormat::format)
                    .orElse(null);
        }
    
        private static LocalDateTime parseDateString(String dateString) {
            for (DateTimeFormatter formatter : knownFormats) {
                try {
                    return LocalDateTime.parse(dateString, formatter);
                } catch (DateTimeParseException e) {
                    continue;
                }
            }
            return null;
        }
    
        private static final List<DateTimeFormatter> knownFormats = Arrays.asList(
                DateTimeFormatter.ISO_DATE_TIME,
                dateOnlyFormatter("yyyy-MM-dd"),
                dateOnlyFormatter("MM-dd-yyyy"),
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
                dateOnlyFormatter("dd-MMM-yyyy").withLocale(Locale.ENGLISH));
    
        private static DateTimeFormatter dateOnlyFormatter(String datePattern) {
            // Credit: https://stackoverflow.com/a/40175568/1762224
            return new DateTimeFormatterBuilder()
                    .appendPattern(datePattern)
                    .optionalStart()
                    .appendPattern(" HH:mm")
                    .optionalEnd()
                    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                    .toFormatter();
        }
    
        private static final DateTimeFormatter displayFormat = DateTimeFormatter.ISO_DATE;
    }
    

    Here is a modified version that is simpler as Devin suggested. It ignores the concept of time entirely, and only focuses on date when parsing. It removes the need for the dateOnlyFormatter method (as seen above).

    import java.time.LocalDate;
    import java.time.format.*;
    import java.util.*;
    
    public class DateParser {
        public static void main(String[] args) {
            System.out.println(normalizeDate("2023-05-09T05:55:07Z")); // 2023-05-09
            System.out.println(normalizeDate("2023-04-30")); // 2023-04-30
            System.out.println(normalizeDate("08-05-2023")); // 2023-08-05
            System.out.println(normalizeDate("2023-05-09 00:00:00")); // 2023-05-09
            System.out.println(normalizeDate("31-Dec-2021")); // 2021-12-31
            System.out.println(normalizeDate("")); // null
        }
    
        public static String normalizeDate(String rawDateTimeString) {
            return Optional.ofNullable(parseDateString(rawDateTimeString))
                    .map(displayFormat::format)
                    .orElse(null);
        }
    
        private static LocalDate parseDateString(String dateString) {
            for (DateTimeFormatter formatter : knownFormats) {
                try {
                    return LocalDate.parse(dateString, formatter);
                } catch (DateTimeParseException e) {
                    continue;
                }
            }
            return null;
        }
    
        private static final List<DateTimeFormatter> knownFormats = Arrays.asList(
                DateTimeFormatter.ISO_DATE_TIME,
                DateTimeFormatter.ofPattern("yyyy-MM-dd"),
                DateTimeFormatter.ofPattern("MM-dd-yyyy"),
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
                DateTimeFormatter.ofPattern("dd-MMM-yyyy").withLocale(Locale.ENGLISH));
    
        private static final DateTimeFormatter displayFormat = DateTimeFormatter.ISO_DATE;
    }