According to the documentation of Calendar
, the value of the month to be passed to the method set
is indexed at zero. That is, January is 0, February is 1, etc.
For this reason, 1 is subtracted from the reported value, because the correct value of the month is probably passed there (1 for January, 2 for February, etc.). But by passing this amount to Calendar
, have to subtract 1 so that it generates the correct date.
This is a little confusing, but that’s how the class Calendar
works. That’s one of the reasons (it’s not the main one, but it’s definitely one that contributes) why this API is so criticized.
java.time
If using Java >= 8 and your code does not depend on the use of Date
and Calendar
, an alternative is to use the API java.time
. This API solves many of the old API problems.
If you only want the date with day, month and year (and do not need the time nor the Timezone), can use a java.time.LocalDate
:
public class Produto {
private LocalDate dataValidade;
public Produto(String nome, double peso, int dia, int mes, int ano) {
this.dataValidade = LocalDate.of(ano, mes, dia);
...
}
}
This API has several improvements regarding Date
and Calendar
. The simplest - and at the same time one of the best - is that now the months are no longer indexed to zero and therefore have the correct values (January is 1, February is 2, etc). It is no longer necessary to subtract 1, as it was with Calendar
.
Already to format the date, use a java.time.format.DateTimeFormatter
. In your case, you were using DateFormat.getDateInstance()
, which uses the standard default locale of the JVM. To obtain the equivalent of java.time
, use a java.time.format.DateTimeFormatterBuilder
, along with a java.time.format.FormatStyle
:
public class Produto {
private LocalDate dataValidade;
private static final DateTimeFormatter FMT = new DateTimeFormatterBuilder()
.appendLocalized(FormatStyle.MEDIUM, null).toFormatter();
public String getFormattedDataValidade() {
return FMT.format(dataValidade);
}
}
If you don’t already use Java 8, you can use Threeten Backport, which has the same classes already mentioned (LocalDate
, DateTimeFormatter
, etc) and it basically works the same way. The difference is that they are in the package org.threeten.bp
(instead of java.time
). The backport is compatible with JDK 6 and 7.
In case you are still attached to Java 5 and want to use something better than Date
and Calendar
, an alternative is the Joda-Time (although this is a project considered "terminated", since on your site there’s a warning indicating this and recommending the use of java.time
)
Joda-Time has classes with names similar to java.time
, although it is not 100% equal. Classes are in the package org.joda.time
, follows a similar example to the previous code:
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
...
LocalDate date = new LocalDate(ano, mes, dia);
DateTimeFormatter fmt = DateTimeFormat.mediumDate();
System.out.println(fmt.print(date));
More about the java.time
can be seen in this question.
Hello. Actually, I just remembered that, excellent explanation, thank you!
– Diego