简体   繁体   中英

Java date field tolerating different locales/mistakes

I am working on a Java project where as you can see from the code below I have a JFormattedTextfield. What I would like to do is to introduce some tolerance in the date field. Like if the user inputs 02.02.2010 or 02.FEB.2010 or 02/02/2010, it shouldn't give an error. I am trying to search for something similar, but all I can find is examples of Simpledateformat telling to use predefined format. Kindly let me know or give some pointers. Thank you.

DateFormat format = new SimpleDateFormat("dd/M/yyyy"); DateFormatter df = new DateFormatter(format); JFormattedTextField dateField = new JFormattedTextField(df);

This is a seed of an idea, basically what this is a "multi formatter". What that means is, you can supply any number of AbstractFormatter s to it and when requested, it will scan through the list until it finds one capable of parsing/formatting the requested value.

It has limitations...obviously, you can no longer use a mask of any kind, as the MultiFormatter allows for any number of different, incompatible (as far as the mask is concerned) formats...

During testing, I did not that when the field was validated, it would always default to the first formatter (to format the given value). You might be able to fix this, by keeping a reference of the last successful parser used to parse the text to it's Object equivalent. Of course, then you would also need to be ready to discard this formatter if it was not able to format the given Object again and try the other formatters...

The long and short basically is, the resulting "value" was correct for what the user put in. The way that the MultiFormatter is setup right now, the first formatter will become the "default" formatter for new values...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatter;

public class Test100 {

    public static void main(String[] args) {
        new Test100();
    }

    public Test100() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DateFormatter[] formatters = new DateFormatter[]{
                    new DateFormatter(new SimpleDateFormat("dd.MM.yyyy")),
                    new DateFormatter(new SimpleDateFormat("dd.MMM.yyyy")),
                    new DateFormatter(new SimpleDateFormat("dd/MM/yyyy"))
                };
                MultiFormatter<DateFormatter> multiFormatter = new MultiFormatter<>(formatters);

                JFormattedTextField ftf = new JFormattedTextField(multiFormatter);
                ftf.setColumns(10);


                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                frame.add(ftf, gbc);
                frame.add(new JButton("Test Focus Lost"), gbc);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MultiFormatter<F extends JFormattedTextField.AbstractFormatter> extends DefaultFormatter {

        private List<F> formatters;

        public MultiFormatter() {
        }

        public MultiFormatter(F... formatters) {
            addFormatters(formatters);
        }

        public List<F> getFormatters() {
            if (formatters == null) {
                formatters = new ArrayList<>(25);
            }
            return formatters;
        }

        public void addFormatters(F... formatters) {
            getFormatters().addAll(Arrays.asList(formatters));
        }

        @Override
        public String valueToString(Object value) throws ParseException {

            String text = null;
            for (F formatter : getFormatters()) {
                try {
                    text = formatter.valueToString(value);
                    break;
                } catch (ParseException exp) {
                }
            }

            if (text == null) {
                throw new ParseException("Could not find valid parser for " + value, 0);
            }

            return text;

        }

        @Override
        public Object stringToValue(String text) throws ParseException {

            Object value = null;
            for (F formatter : getFormatters()) {
                try {
                    value = formatter.stringToValue(text);
                    break;
                } catch (ParseException exp) {
                }
            }

            if (text == null) {
                throw new ParseException("Could not find valid parser for " + value, 0);
            }

            return value;
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM