Codename One:PickerComponent日期年龄验证的跨Locale适配问题
Hey there, I see the issue you're facing—your current validator relies on a fixed date format (dd/mm/yy) which breaks when the device's locale changes, plus the two-digit year parsing is ambiguous and there's a subtle format bug. Let's fix this with a validator that adapts to the device's locale while ensuring accurate age calculation.
The Problem with Your Current Code
- You’re hardcoding a date format that doesn’t match the locale-specific formatting the PickerComponent uses, so parsing fails when the locale changes.
- The
mmin your format is for minutes, not months—you should useMMfor months! This would already throw off your validation even if the locale matched. - Two-digit year parsing can lead to incorrect dates (e.g., "03" might be interpreted as 1903 instead of 2003).
Fixed Locale-Adaptive Validator
Here’s a revised version that handles locale-specific date strings correctly, fixes the month/minute mix-up, and ensures proper two-digit year handling:
PickerComponent datePicker = PickerComponent.createDate(new Date()) .label("Data di nascita") .errorMessage("Hai almeno 13 anni?"); Validator validator = new Validator(); validator.addConstraint(datePicker, new Constraint() { @Override public boolean isValid(Object value) { if (!(value instanceof String)) { Log.p("Invalid input type: expected String"); return false; } String inputDateStr = (String) value; Log.p("-----------------"); Log.p("Inserted birthday date: " + inputDateStr); Log.p("-----------------"); // Use the locale-specific short date formatter that matches the Picker's output DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); // Set a clear range for two-digit year parsing to avoid century confusion if (dateFormat instanceof SimpleDateFormat) { SimpleDateFormat sdf = (SimpleDateFormat) dateFormat; // Assume two-digit years refer to 1950-2049 (adjust this range if needed) sdf.set2DigitYearStart(new GregorianCalendar(1950, Calendar.JANUARY, 1).getTime()); } try { Date birthdayDate = dateFormat.parse(inputDateStr); Calendar birthday = Calendar.getInstance(); birthday.setTime(birthdayDate); Calendar nowMinus13 = Calendar.getInstance(); nowMinus13.add(Calendar.YEAR, -13); // Check if the birthday is on or before the date 13 years ago return birthday.before(nowMinus13) || birthday.equals(nowMinus13); } catch (ParseException ex) { Log.p("Cannot parse the date: " + ex.getMessage()); return false; } } @Override public String getDefaultFailMessage() { return "You must be at least 13 years old"; } });
Key Improvements
- Locale Adaptability: Uses
DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault())which automatically matches the short date format the PickerComponent uses for the current locale—no more hardcoding formats! - Fixed Month Format: Eliminated the
mm/MMmix-up that would have broken date parsing even in matching locales. - Two-Digit Year Clarity: Sets an explicit range for two-digit year parsing to avoid incorrect century assumptions.
- Robust Input Checks: Added a check for non-string input to handle edge cases gracefully.
Bonus: Even Better Approach (If Possible)
If you can configure the PickerComponent to return a Date object directly instead of a String, that would eliminate parsing issues entirely. Check the component’s documentation to see if there’s a setting for this—it’s the most reliable long-term solution.
内容的提问来源于stack exchange,提问作者Francesco Galgani

