I have a use case where I have date in the following formats,
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.
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;
}