I have what is essentially a JFormattedTextField which uses a DateFormatter, which gets its format from a user-controlled locale setting. The code below is an attempt to reproduce this without a ton of proprietary code. (I apologize for my ham-fisted attempts at top-level Swing stuff...)
My issue is, that if the user has chosen a locale with two-digit years, it becomes impossible to enter dates in the "wrong" century. For example, if I run the program below and edit the year to 2047 and click Ok, the program prints a date in 1947.
The reason seems to be that JFormattedTextField likes to "normalize" its data by round-tripping it through the text representation. One workaround is to override commitEdit() with a method that tests the roundtrip and, if it turns out to clobber the year, replaces the format with a hard-coded YYYY-MM-DD. This seems a bit heavy-handed, though. Is there a better way, except asking the users to choose a sane locale or hard-wiring the format for this particular field? (I know there are ways to chose which 100-year window is the right one, but that still limits me to a 100-year window).
import javax.swing.*;
import javax.swing.text.DateFormatter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
public class Main {
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
var gbl = new GridBagLayout();
frame.setLayout(gbl);
final Container contentPane = frame.getContentPane();
Date date = new Date();
JFormattedTextField dateField = new JFormattedTextField(date);
dateField.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
@Override
public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
return new DateFormatter(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.GERMANY));
}
});
contentPane.add(dateField);
JButton button = new JButton("Ok");
contentPane.add(button);
button.addActionListener((ActionEvent e) -> {
try {
dateField.commitEdit();
} catch (ParseException ex) {
ex.printStackTrace();
}
System.out.println(dateField.getValue());
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(Main::createAndShowGUI);
}
}