Java 日历跳过第一个月

Java calender skipping first month

我目前正在尝试制作一个 Java 程序,它只打印一年中每一天的日期。除一月份外,它适用于一年中的每个月。谁能建议我可能做错了什么?请在下面找到代码。

String date;

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.MONTH, 0);
    cal.set(Calendar.DAY_OF_MONTH, 0);
        int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        int maxMon = cal.getActualMaximum(Calendar.MONTH);
        SimpleDateFormat df = new SimpleDateFormat("dd_MM_yy");
        for (int j = 0; j < maxMon; j++){
            for (int i = 0; i < maxDay; i++) {
                    cal.set(Calendar.DAY_OF_MONTH , i);
                    date = df.format(cal.getTime());
                    System.out.println(date);
            }
        } 

首先,您需要在月循环中获取 int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);

接下来,请记住 MONTHDAY_OF_MONTH 有不同的基础: MONTH 从 0 开始,因此 maxMon 将是 11。DAY_OF_MONTH 从 1 开始,因此 maxDay 将在 28-31 范围内。

因此,如果您相应地更改循环(从 j = 0i = 1 开始并使用 j <= maxMoni <= maxDay),您的结果应该没问题。

日历的索引是...特别的。

DAY_OF_MONTH 从 1 开始,MONTH 从 0 开始。 getActualMaximum returns 实际最大值,也需要包含在循环中。除此之外,您在遍历日历实例时没有更改月份字段。

我冒昧地使您的循环代码更易于理解。

String date;

Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 0);

SimpleDateFormat df = new SimpleDateFormat("dd_MM_yy");
for (int i = 0; i <= cal.getActualMaximum(Calendar.MONTH); i++) {
    cal.set(Calendar.MONTH, i);
    for (int j = 1; j <= cal.getActualMaximum(Calendar.DAY_OF_MONTH); j++) {
        cal.set(Calendar.DAY_OF_MONTH , j);
        date = df.format(cal.getTime());
        System.out.println(date);
    }
}

java.time

现代方法是使用 java.time classes。旧的日期时间 classes 是一团糟、设计不佳、令人困惑和麻烦。

LocalDate

LocalDate class 表示没有时间和时区的仅日期值。

时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因地区而异。例如,Paris France is a new day while still “yesterday” in Montréal Québec.

午夜后几分钟
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

TemporalAdjuster

TemporalAdjuster 接口提供了 classes 来操作日期时间值。 TemporalAdjusters class(注意复数 s)提供了一些方便的实现。

LocalDate firstOfMonth = today.with( TemporalAdjusters.firstDayOfMonth() );

现在循环整个月。获取下个月的第一天作为循环的限制。生成自动本地化为魁北克省的缩写格式的字符串。

LocalDate firstOfNextMonth = today.with( TemporalAdjusters.firstDayOfNextMonth() );
LocalDate ld = firstOfMonth;
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
System.out.println( ld.getMonth().getDisplayName( TextStyle.FULL , locale ) );  // Print localized name of the month being reported.
do {
    System.out.println( ld.format( f ) );  // Create String representing this date.
} while ( ld.isBefore( firstOfNextMonth ) );

octobre

16-10-01

16-10-02

参见 code in action