Problem Handling LocalDate Dates

2

I'm making an application for work calculations. I need to receive two dates and know the amount of days / months / years. Ex: 08/03/2017 to 07/03/2018 is for 12 months accurate, in my code of 11 months and 27 days someone knows how to fix it.

String dataEntrada, dataSaida;
        dataEntrada = JOptionPane.showInputDialog(null, "Digite a data de entrada");
        dataSaida = JOptionPane.showInputDialog(null, "Digite a data de saida");
        String entrada[] = dataEntrada.split("/");
        String saida[] = dataSaida.split("/");

        LocalDate admissao = LocalDate.of(Integer.parseInt(entrada[2]), Integer.parseInt(entrada[1]),
                Integer.parseInt(entrada[0]));
        LocalDate demissao = LocalDate.of(Integer.parseInt(saida[2]), Integer.parseInt(saida[1]),
                Integer.parseInt(saida[0]));
        Period periodo = Period.between(admissao, demissao);
        System.out
                .println(periodo.getYears() + " Anos " + periodo.getMonths() + " Meses " + periodo.getDays() + " Dias");
    
asked by anonymous 07.03.2018 / 23:40

2 answers

1

What happens is that Period , in a sense, "rounds down". For an exact month to be considered, the day of the month must be greater than or equal to the beginning of the month.

Example: If you start on 3/8/2017 and end on 04/17/2017:

LocalDate admissao = LocalDate.of(2017, 3, 8);
LocalDate demissao = LocalDate.of(2017, 4, 7);
Period periodo = Period.between(admissao, demissao);
System.out.println(periodo.getYears() + " Anos " + periodo.getMonths() + " Meses " + periodo.getDays() + " Dias");

The output will be:

  

0 Years 0 Months 30 Days

As I started on March 8th, the API only considers a full month from April 8th. So if I change the dates to:

LocalDate admissao = LocalDate.of(2017, 3, 8);
LocalDate demissao = LocalDate.of(2017, 4, 8);

The output will be:

  

0 Years 1 Months 0 Days

In your example, the period starts on 3/8/2017 and ends on 3/7/2018, so the twelfth month was not completed (it would only be completed as of 08/03/2018).

This is how the API does the calculations and there is no way to change. If your rule to consider a whole month is different, some adaptations should be made.

One solution would be to add one day to the date of resignation (as suggested in the prmottajr response), and then subtract this day to more than periodo.getDays() .

I do not know exactly what your rule is. Is it from the 03/03/2018 that you consider 12 months? Or as of 01/03/2018 should already return 12 months?

If it is the second case (as of 01/03/2018 already considers 12 months), you can simply ignore the day (transforming LocalDate to YearMonth ) and calculate the number of months between them:

long meses = ChronoUnit.MONTHS.between(YearMonth.from(admissao), YearMonth.from(demissao));

With this, meses will equal 12. Then you can adjust for the amount of years, if meses is greater than 12, for example:

long anos = meses / 12;
meses = meses - (anos * 12);
    
03.05.2018 / 15:22
0

The method between no includes the end date. Try it:

LocalDate demissao = LocalDate.of(Integer.parseInt(saida[2]), Integer.parseInt(saida[1]),
                Integer.parseInt(saida[0])+1);
    
07.03.2018 / 23:50