Java Data Type How to - Create date field which tolerates different locales/mistakes/formats








Question

We would like to know how to create date field which tolerates different locales/mistakes/formats.

Answer

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//  w w  w .  j  a va  2 s .c o m
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatter;

public class Main {
  public static void main(String[] args) {
    DateFormatter[] formatters = new DateFormatter[] {
        new DateFormatter(new SimpleDateFormat("dd.MM.yyyy")),
        new DateFormatter(new SimpleDateFormat("ddMMyyyy")),
        new DateFormatter(new SimpleDateFormat("yyyy.MM.dd.")),
        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();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(ftf);
    frame.add(new JButton("OK"));
    frame.pack();
    frame.setVisible(true);
  }
}

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

  private List<F> formatters;

  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) {
        System.out.println("Could not find valid parser for " + value);
      }
    }
    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) {
        System.out.println("Could not find valid parser for " + value);
      }
    }
    return value;
  }
}