简体   繁体   English

为什么 java.util.Calendar 在 2021 年 2 月返回 31?

[英]Why is java.util.Calendar returning 31 for Feb 2021?

The following snippet returns:以下代码段返回:

28
31

I can't figure out, why.我想不通,为什么。 I tried so set the calendar object to Feb 2021 in two ways, what am I doing wrong?我尝试通过两种方式将日历 object 设置为 2021 年 2 月,我做错了什么? Month is zero-based, so Feb is "1".月份是从零开始的,所以二月是“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));
     }
}

Or does this only happen, because I call Calendar.getInstance() on March 29, 30 or 31 and I don't call或者这只会发生,因为我在 3 月 29 日、30 或 31 日调用 Calendar.getInstance() 并且我没有调用

c.set(Calendar.DAY_OF_MONTH, {any day below 29});

java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. java.util date-time API 及其格式 API、 SimpleDateFormat已过时且容易出错。 It is recommended to stop using them completely and switch to the modern date-time API * .建议完全停止使用它们并切换到现代日期时间 API *

Using modern date-time 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());
    }
}

Output: Output:

28

Learn more about the modern date-time API from Trail: Date Time .Trail: Date Time了解有关现代日期时间 API 的更多信息。

Using legacy 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));
    }
}

Output: Output:

28

* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project . * For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API级别仍然不符合 Java-8,检查Java 8+ API 可通过脱糖如何在 Android 项目中使用 ThreeTenABP

You call Calendar.getInstance() , which returns a Calendar object initialized to the current time, which today means Mar 31, 2021.您调用Calendar.getInstance() ,它返回一个Calendar object 初始化为当前时间,今天意味着 2021 年 3 月 31 日。

You then set YEAR to 2021 and MONTH to 1 (Feb), leaving DAY_OF_MONTH at 31. If you asked the Calendar object for the date, it would resolve the fields and return a date value that explains the issue:然后将YEAR设置为 2021 并将MONTH设置为 1(2 月),将DAY_OF_MONTH设置为 31。如果您向Calendar object 询问日期,它将解析字段并返回解释问题的日期值:

System.out.println(c.getTime()); // prints: Wed Mar 03 11:51:55 EST 2021

See how it says Mar 3 , 2021?看看 2021 年3 月 3日是怎么写的? That is because Feb 31 rolls over after Feb 28 and becomes Mar 3.那是因为 2 月 31 日在 2 月 28 日之后翻转并变为 3 月 3 日。

Since the Calendar object is now in March, the c.getActualMaximum(Calendar.DAY_OF_MONTH) correctly returns 31.由于Calendar object 现在是 3 月,因此c.getActualMaximum(Calendar.DAY_OF_MONTH)正确返回 31。

To do it right, call clear() and set DAY_OF_MONTH to 1, which is much easier when you use the nice set(year, month, date) helper method.要正确执行此操作,请调用clear()并将DAY_OF_MONTH设置为 1,当您使用 nice set(year, month, date)辅助方法时,这会容易得多。

int year = 2021;
int month = Calendar.FEBRUARY/*1*/;
Calendar c = Calendar.getInstance();
c.clear();
c.set(year, month, 1);
System.out.println(c.getTime()); // prints: Mon Feb 01 00:00:00 EST 2021
System.out.println(c.getActualMaximum(Calendar.DAY_OF_MONTH)); // prints: 28

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM