Search code examples
javaswinglocaldatejformattedtextfield

Error from JFormattedTextField to LocalDate - java.time.format.DateTimeParseException


I have a JFormattedTextField in which the format is dd/MM/yyyy

I want to extract the day, month and year of a date, in dd/MM/yyyy format, time date "ES" (Spain).

I run the JFrame, and if I press button, having the JFormattedTextField empty, why do I have the following error? The error (see image):

enter image description here

How can I resolve it? I'll show my code...

Code:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.MaskFormatter;

public class Ventana extends JFrame implements ActionListener {
    public JLabel label_date, label_calculo;
    public JFormattedTextField date; 
    public JButton button; 

    public Ventana() throws ParseException{
        super();
        configurarVentana();
        inicializarComponentes();
    }

    private void configurarVentana() {
        this.setTitle("Example");
        this.setSize(600, 480);
        this.setLocationRelativeTo(null);
        this.setLayout(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void inicializarComponentes() throws ParseException{
        label_date = new JLabel();
        label_calculo = new JLabel();
        date = new JFormattedTextField();
        button = new JButton();
        
        label_date.setText("Add date:");
        label_date.setBounds(50, 50, 100, 25);
        date.setBounds(150, 50, 160, 25);
        label_calculo.setText("Age: ");
        label_calculo.setBounds(50, 90, 300, 25);
        button.setBounds(320, 50, 130, 25);
        button.setText("Calculate age");
        
        this.add(label_date);
        this.add(date);
        this.add(button);
        this.add(label_calculo);
        
        button.addActionListener(this);
        
        //Format: JFormattedTextField dd-MM-yyyy
        date.setFormatterFactory(new DefaultFormatterFactory(new MaskFormatter("##/##/####")));
    }

    public void actionPerformed(ActionEvent e) {
        //JAVA 8.
        LocalDate ahora = LocalDate.now();
        int dia_hoy = ahora.getDayOfMonth();
        int mes_hoy = ahora.getMonthValue();
        int ano_hoy = ahora.getYear();
        System.out.println(dia_hoy+"   "+mes_hoy+"   "+ano_hoy); 

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        LocalDate fechaNac = LocalDate.parse(date.getText(), fmt);
        int dia_nac = fechaNac.getDayOfMonth();
        int mes_nac = fechaNac.getMonthValue();
        int ano_nac = fechaNac.getYear();
        Period periodo = Period.between(fechaNac, ahora);

        if(date.getText().trim().isEmpty()){
            JOptionPane.showMessageDialog(null, "Date empty", "Administrador", JOptionPane.WARNING_MESSAGE);
        }else if(dia_nac<1 || dia_nac>31){
            JOptionPane.showMessageDialog(null, "Day incorrect", "Administrador", JOptionPane.WARNING_MESSAGE);
        }else if(mes_nac<1 || mes_nac>12){
            JOptionPane.showMessageDialog(null, "Month incorrect.", "Administrador", JOptionPane.WARNING_MESSAGE);
        }else if(ano_nac<1900 || ano_nac>ano_hoy){
            JOptionPane.showMessageDialog(null, "Year incorrect.", "Administrador", JOptionPane.WARNING_MESSAGE);
        }else{
            label_calculo.setText("You're "+String.valueOf(periodo.getYears())+" years old.");
        }
    }
    
    public static void main(String[] args) throws ParseException {
        Ventana V = new Ventana();
        V.setVisible(true);
    }

}

Solution

  • You still haven't posted proper MRE, because you still don't understand what problem you are attempting to fix.

    Forget about your application and concentrate on the problem.

    Here is a proper MRE:

    import java.time.*;
    import java.time.format.*;
    
    
    public class Main2
    {
        public static void main(String[] args) throws Exception
        {
                String textFromTextField = "  /  /    "; // cause exception
    //          String textFromTextField = "18/05/2021"; // works as expected
    
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
                LocalDate fechaNac = LocalDate.parse(textFromTextField, fmt);
                int dia_nac = fechaNac.getDayOfMonth();
                int mes_nac = fechaNac.getMonthValue();
                int ano_nac = fechaNac.getYear();
    
                System.out.println(dia_nac + " : " + mes_nac + " : " + ano_nac);
        }
    }
    

    All it does is attempt to parse a String. There is no need for a GUI to parse a String.

    1. The first string value attempts to parse an empty string which is what you get when you don't type any data into your formatted text field. It will generate your Exception.
    2. The second string attempts to demonstrate what happens when a valid data is entered. You get the expected output.

    Below is the solution. You use a try/catch block to handle the Exception and then do whatever processing is relevant in your case:

    import java.time.*;
    import java.time.format.*;
    
    
    public class Main2
    {
        public static void main(String[] args) throws Exception
        {
            String textFromTextField = "  /  /    "; // cause exception
    //      String textFromTextField = "18/05/2021"; // works as expected
    
            try
            {
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
                LocalDate fechaNac = LocalDate.parse(textFromTextField, fmt);
                int dia_nac = fechaNac.getDayOfMonth();
                int mes_nac = fechaNac.getMonthValue();
                int ano_nac = fechaNac.getYear();
    
                System.out.println(dia_nac + " : " + mes_nac + " : " + ano_nac);
            }
            catch (Exception e)
            {
                System.out.println("Invalid date format entered");
            };
        }
    }
    

    So the first step in solving a problem is knowing what problem you are attempting to solve.

    By simplifying the problem, the MRE is simpler and the posting in the forum is simpler and the solution is simpler.