为什么java.util.Calendar在2021年2月返回31?
以下代码段返回:
28
31
我想不通,为什么。我尝试通过两种方式将日历对象设置为 2021 年 2 月,我做错了什么?月份是从零开始的,所以二月是“1”。
import java.util.Calendar;
import java.util.GregorianCalendar;
public class HelloWorld{
public static void main(String []args){
Calendar g = new GregorianCalendar(2021, 1, 28);
System.out.println(g.getActualMaximum(Calendar.DAY_OF_MONTH));
int year = 2021;
int month = 1;
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
System.out.println(c.getActualMaximum(Calendar.DAY_OF_MONTH));
}
}
或者这只会发生,因为我在 3 月 29、30 或 31 日调用 Calendar.getInstance() 而我没有调用
c.set(Calendar.DAY_OF_MONTH, {any day below 29});
回答
java.util日期时间 API 及其格式化 APISimpleDateFormat已过时且容易出错。建议完全停止使用它们并切换到现代日期时间 API *。
使用现代日期时间 API:
import java.time.Month;
import java.time.Year;
public class Main {
public static void main(String[] args) {
System.out.println(YearMonth.of(2021, Month.FEBRUARY).lengthOfMonth());
}
}
输出:
28
28
从Trail: Date Time 中了解有关现代日期时间 API 的更多信息。
使用旧版 API:
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
// 1st Feb 2021
Calendar cal = new GregorianCalendar(2021, Calendar.FEBRUARY, 1);
System.out.println(cal.getActualMaximum(Calendar.DAY_OF_MONTH));
}
}
输出:
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和您的 Android API 工作级别仍然不符合 Java-8,请检查通过 desugaring和How to use ThreeTenABP in Android Project可用的 Java 8+ APIs。
- Wouldn't [`YearMonth.of(2021, Month.FEBRUARY)`](https://docs.oracle.com/javase/8/docs/api/java/time/YearMonth.html#of-int-java.time.Month-) be simpler than `Year.of(2021).atMonth(Month.FEBRUARY)`? --- It for sure skips the wasted creation of a `Year` object.