日历.月份输出错误

3

我一直使用 java.util 来表示所有日期和日历。但是我在这里遇到了一个奇怪的问题。 Calendar.MONTHCalendar.DAY_OF_MONTH等都给出了错误的输出。但是当我使用 Calendar.getTime() 时,我得到了正确的输出。可能的问题是什么?

public class TestClass {

    public static void main(String[] args) {
        Calendar rightNow = Calendar.getInstance();
        System.out.println(rightNow.MONTH);
        System.out.println(rightNow.DAY_OF_MONTH);
        System.out.println(rightNow.YEAR);
        System.out.println(rightNow.getTime());
    }
}

同样的操作会得到以下输出结果:
2
5
1
Tue Jan 22 10:31:44 GMT+05:30 2013

在使用Java日历时,要注意一些你直觉上认为应该从1开始的事物,例如月份,实际上是从0开始计数的。http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#MONTH - Patashu
3
我完全不懂Java,但那些看起来像是位置常量... - leppie
Calendar类存在许多设计问题,你只是碰巧遇到了其中之一。虽然在2013年使用它是合理的,但在接下来的一年中,它被ZonedDateTime和其他来自java.time,现代Java日期和时间API的类所取代。因此,现在永远不要再使用Calendar了。 - Ole V.V.
1
请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque
4个回答

8
    System.out.println(rightNow.MONTH);
    System.out.println(rightNow.DAY_OF_MONTH);
    System.out.println(rightNow.YEAR);
    System.out.println(rightNow.getTime());

您正在打印日历常量值。

如果想要值,需要使用 get...方法。

示例:

    System.out.println(rightNow.get(Calendar.MONTH));

阅读Calendar javadoc以获取更多信息。


我正在使用mCalendar.setDate(java.util.Date)方法,但仍然给出错误的月份值。 - AZ_
实际上这是与Java Calendar API有关的问题,第一个月是0而不是1 :-) - AZ_
如果您打印出第一个月份1月,它将打印0而不是1。 - AZ_

6

Calendar.MONTH不会返回当前月份。它是一个常量,其值为2。

来自源代码:

public final static int MONTH = 2;

它用作Calendar的get方法中的参数。
public int get(int field) {...}

日历的设计源自Java早期,当时许多现今的约定、不存在或正在发展中。Oracle(以及早期的Sun)今天绝不会让像java.util.Calendar API这样的API成为标准API的一部分。
并且,为了完整起见,应该使用Joda Time而不是Java的Date和Calendar API。

3

java.time

    ZonedDateTime rightNow = ZonedDateTime.now(ZoneId.of("Africa/Cairo"));
    System.out.println(rightNow.getMonth());
    System.out.println(rightNow.getMonthValue());
    System.out.println(rightNow.getDayOfMonth());
    System.out.println(rightNow.getYear());
    System.out.println(rightNow);

刚刚运行时的输出是:

FEBRUARY
2
15
2019
2019-02-15T21:15:06.313809+02:00[Africa/Cairo]

不要使用Calendar

Calendar类很容易让人感到困惑,因为它的设计很糟糕。所以不奇怪你会有这个疑问。幸运的是,在你提出这个问题的一年后,它被java.time中的ZonedDateTime和其他类所取代,它们是现代Java日期和时间API。所以现在永远不要再使用Calendar了。

Calendar类试图变得非常通用,所以它没有像getMonth方法等那样,而是有了可以读取和设置的字段的概念。由于它是在Java拥有enum之前设计的,每个字段都有一个数字和一个命名常量。所以YEAR(纪元)是1,MONTH是2等等。要获取Calendar对象的字段值,你应该调用get方法并传递适当的命名常量,例如rightNow.get(Calendar.MONTH)。只使用rightNow.MONTH是一个经常犯的错误。它只会给你常量的值,即2。

链接

Oracle教程:日期和时间,解释如何使用java.time。


0
    Calendar now = Calendar.getInstance();
    out.println("month now= " + (now.get(Calendar.MONTH)+1));

或者使用 GregorianCalender:

    GregorianCalendar nu  = new GregorianCalendar();
    int day = nu.get(Calendar.DAY_OF_MONTH);
    int month = (nu.get(Calendar.MONTH)+1);  //month +1 because january`==0
    int year= nu.get(Calendar.YEAR);
    int hour= nu.get(Calendar.HOUR_OF_DAY);
    int minutes= nu.get(Calendar.MINUTE);

这里


1
请将您的所有代码都放在代码块中。欢迎来到SO。 - Kars
感谢您想要做出贡献。正如所说,我们不应再使用CalendarGregorianCalendar,因此坦率地说,我认为帮助用户如何做到这一点就是在帮助他们做不应该做的事情。相反,我鼓励您学习Java时间和日期API(java.time) - Ole V.V.
1
谢谢你给了我这个选项。我刚学会了Calendar类以及如何使用它。我一定会去查看java.time。 - Linda Minne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接