I have the following (somewhat abbreviated) code to parse String
input into a Joda Time DateTime
object. I need to properly handle multiple formats, including four & two digit years.
setupValidDateFormats();
DateTime date = convertToDateTime(thisField.getText());
if (date != null) {
thisField.setText(date.toString("MM/dd/yyyy"));
} else {
System.out.println("Invalid date");
}
private void setupValidDateFormats() {
DateTimeParser[] formats = {
DateTimeFormat.forPattern("MM/dd/yyyy").getParser(),
DateTimeFormat.forPattern("MM/dd/yy").getParser(),
DateTimeFormat.forPattern("MM-dd-yyyy").getParser(),
DateTimeFormat.forPattern("MM-dd-yy").getParser(),
DateTimeFormat.forPattern("MMddyyyy").getParser(),
DateTimeFormat.forPattern("MMddyy").getParser()
};
formatter = new DateTimeFormatterBuilder().append(null, formats).appendTwoDigitYear(1950, true).toFormatter()
.withLocale(Locale.US);
}
private DateTime convertToDateTime(String input) {
if (isNullOrEmpty(input)) {
return null;
}
DateTime date;
try {
// When you parse a date, it'll throw an exception for not only invalid formats,
// but for invalid values such as 09/31/2013 or 02/30/2013. Leap year is included as well.
date = formatter.parseDateTime(input);
} catch (Exception e) {
// User input a date in the incorrect format, or an invalid value.
// Example: 02/30/2013 is invalid.
date = null;
}
return date;
}
The issue I'm having is that when the user enters 120100
, I expect it to be able to parse correctly and ultimately output at 12/01/1900. However, formatter.parseDateTime(input);
in convertToDateTime
throws an IllegalArgumentException
instead, and the method returns null
.
Probably worth noting that if I remove the appendTwoDigitYear
from the DateTimeFormatterBuilder
chain, the input does parse successfully, but 120100
becomes 12/01/0000
, but that's not what I need.
Am I misunderstanding the Joda Time API? Shouldn't appendTwoDigitYear
with the 1950 pivot handle the 00 two year digit as 1900?
When you use a pattern like
DateTimeFormat.forPattern("MMddyyyy")
it can read a date like "120100"
. What it does is read the 12
for MM
, the 01
for dd
, and 00
as a literal value for yyyy
, ie. 0
starting at year 0
, so 0000
.
Because that pattern appears before the MMddyy
in your parsers
array, it will be used to parse your date string.
What you'll want to do, along with reordering or removing that format, is use a pivot year.
public static void main(String[] args) throws Exception {
String str = "120100";
DateTimeParser[] formats = {
DateTimeFormat.forPattern("MM/dd/yyyy").getParser(),
DateTimeFormat.forPattern("MM/dd/yy").getParser(),
DateTimeFormat.forPattern("MM-dd-yyyy").getParser(),
DateTimeFormat.forPattern("MM-dd-yy").getParser(),
DateTimeFormat.forPattern("MMddyy").getParser()
};
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(null, formats).toFormatter()
.withPivotYear(1950).withLocale(Locale.US);
DateTime dateTime = formatter.parseDateTime(str);
System.out.println(dateTime);
}
prints
1900-12-01T00:00:00.000-05:00
I'm still trying to figure out how appendTwoDigitYear
works.