arabiata
arabiata

Reputation: 3

Java 8 formatted date input

I use this code to format a formatted text field to enter month & day:

SimpleDateFormat sdf = new SimpleDateFormat("MM.dd");
DateFormatter df = new DateFormatter(sdf);
DefaultFormatterFactory ddf = new DefaultFormatterFactory(df, df, df, df);
datumTextField.setValue(new Date(System.currentTimeMillis()));
datumTextField.setFormatterFactory(ddf);

When an invalid date is entered, eg. 13.10, a magican changes it to 1.10 after this line:

DateOfAdding = datumTextField.getText();

so the DateOfAddig value is 1.10.

How to turm the magican off?

Upvotes: 0

Views: 89

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 339043

tl;dr

MonthDay.parse( 
    "12.31" , 
     DateTimeFormatter.ofPattern( "MM.dd" ) 
)

Catch DateTimeParseException for invalid input.

java.time.MonthDay

The modern approach uses the java.time classes rather than the troublesome legacy classes seen in the Question.

Among the java.time classes is MonthDay, just what you need.

I suggest collecting input as two different numbers.

MonthDay md = MonthDay.of( x , y ) ;

If you insist, you can collect input as a combined string and parse. If so I suggest you and your user use standard ISO 8601 format: --MM-DD.

MonthDay md = MonthDay.parse( "--12-31" ) ;

Or define a pattern using DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM.dd" ) ;
MonthDay md = MonthDay.parse( input , f ) ;

Trap for DateTimeParseException to detect invalid inputs.

String input = "13.10" ;  // Invalid input. Month must be 1-12.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM.dd" ) ;
MonthDay md = null ;
try 
{
    md = MonthDay.parse( input , f ) ;
} catch ( DateTimeParseException e ) { 
    // … handle error …
    System.out.println( "Invalid input: " + input ) ;
} 

See this code run live at IdeOne.com.

Invalid input: 13.10

e: java.time.format.DateTimeParseException: Text '13.10' could not be parsed: Unable to obtain MonthDay from TemporalAccessor: {MonthOfYear=13, DayOfMonth=10},ISO of type java.time.format.Parsed

md.toString(): null

Upvotes: 1

Aaron
Aaron

Reputation: 24802

You will want to call the SimpleDateFormat's setLenient method with false as a parameter so that the underlying Calendar used for parsing is set to non-lenient.

A non-lenient calendar will refuse field values that aren't in the expected range for this field, rather than accepting them and modifying other fields to make sense of them : in your case the month was rolled-over 12 and reached 1, while the year was increased by 1 and probably reached 1971 rather than the default-when-unspecified 1970.

From the Calendar's javadoc :

Leniency

Calendar has two modes for interpreting the calendar fields, lenient and non-lenient. When a Calendar is in lenient mode, it accepts a wider range of calendar field values than it produces. When a Calendar recomputes calendar field values for return by get(), all of the calendar fields are normalized. For example, a lenient GregorianCalendar interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.

When a Calendar is in non-lenient mode, it throws an exception if there is any inconsistency in its calendar fields. For example, a GregorianCalendar always produces DAY_OF_MONTH values between 1 and the length of the month. A non-lenient GregorianCalendar throws an exception upon calculating its time or calendar field values if any out-of-range field value has been set.

Upvotes: 0

Related Questions