Reputation: 146
I have been trying to create DateUtil for parsing a string to LocalDateTime. There is no problems if a year has pattern "yyyy" but I get Exception if year represents like "yy".
Exception in thread "main" java.time.format.DateTimeParseException: Text '06-mar-17 11:52' could not be parsed at index 3
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
at rinex.service.impl.utils.date.Test.parseToLocalDateTime(Test.java:43)
at rinex.service.impl.utils.date.Test.main(Test.java:53)
Test class
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.LinkedHashMap;
import java.util.Map;
public class Test {
private static final Map<String, String> DATE_FORMAT_REGEXPS = new LinkedHashMap<String, String>() {{
put("^\\d{4}\\d{1,2}\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyyMMdd HH:mm:ss");
put("^\\d{1,2}-[a-z]{3}-\\d{2}\\s\\d{1,2}:\\d{2}$", "dd-MMM-yy HH:mm");
}};
private static final Map<String, DateTimeFormatter> DATE_SHORT_FORMAT_REGEXPS = new LinkedHashMap<String, DateTimeFormatter>() {{
put("dd-MMM-yy HH:mm", new DateTimeFormatterBuilder().
appendPattern("dd-MMM-").
appendValueReduced(ChronoField.YEAR, 2, 2, 2000).
appendPattern(" HH:mm").toFormatter());
}};
public static String determineDateFormat(String dateString) {
for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
if (dateString.toLowerCase().matches(regexp)) {
return DATE_FORMAT_REGEXPS.get(regexp);
}
}
return null; // Unknown format.
}
public static LocalDateTime parseToLocalDateTime(String date) {
date = date.trim().toLowerCase().replaceAll("utc","");
String format = determineDateFormat(date);
LocalDateTime local;
try {
local = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(format));
} catch (DateTimeParseException e) {
DateTimeFormatter formatter = DATE_SHORT_FORMAT_REGEXPS.get(format);
local = LocalDateTime.parse(date, formatter);
}
return local;
}
public static void main(String[] args) {
String date = "20170506 11:52:00UTC";
LocalDateTime dateTime = Test.parseToLocalDateTime(date);
date = "06-MAR-17 11:52";
dateTime = Test.parseToLocalDateTime(date);
}
}
Debug for "20170506 11:52:00UTC" date - "yyyyMMdd HH:mm:ss"
Debug for "06-MAR-17 11:52" date - "dd-MMM-yy HH:mm"
So, what is wrong in DateTimeFormatterBuilder to parse "06-MAR-17 11:52" date?
Upvotes: 2
Views: 3368
Reputation: 14415
It's not the year, but the string representation of the month, where the parsing is case sensitive by default.
You can either use the proper (title) case:
// works
LocalDateTime.parse("06-Mar-17 11:52",
DateTimeFormatter.ofPattern("dd-MMM-yy HH:mm", Locale.ENGLISH));
Or you can build a DateTimeFormatter
that parses case insensitive:
// works
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive().appendPattern("dd-MMM-yy HH:mm")
.toFormatter(Locale.ENGLISH);
formatter.parse("06-mar-17 11:52");
(The explicit locale is not required if your default locale is already English.)
Upvotes: 4