Java 当一个月的第一周定义为出现 1 的周时,日历显示错误的周数

Java Calendar shows wrong amount of weeks when first week of month is defined as week in which 1 occurs

我创建了一个函数,该函数应该获取给定月份的周数。对于一月、五月、七月和十月,应该 return 5 周。 然而,它 returns 5 表示三月、六月、九月。和十一月。令人惊讶的是,总周数是正确的 (52)。

public static int getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(Calendar calendar) {

    while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
        calendar.roll(Calendar.DATE, true);
    }
    int currentMonth = calendar.get(Calendar.MONTH);
    int nextMonth = (currentMonth + 1) % 12;
    int prePreviousMonth = (currentMonth + 12 - 2) % 12;
    int nofWeeks = 0;
    do {
        int month = calendar.get(Calendar.MONTH);
        if (month == nextMonth) {
            nofWeeks++;
        }
        if (month == prePreviousMonth) {
            break;
        }
        calendar.roll(Calendar.WEEK_OF_YEAR, true);
    } while (true);
    return nofWeeks;
}

public static void main(String[] args) {

    int numWeeks;
    int totalWeeks=0;
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, 2016);
    calendar.set(Calendar.DAY_OF_MONTH, 1);

    calendar.set(Calendar.MONTH, Calendar.MAY);
    numWeeks=getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(calendar);
    System.out.println("no of weeks " + numWeeks);
}

输出: 第 4 周

月份的开始是在有第一天的那一周。例如:

25 - 5 月 1 日
5 月 2 日至 8 日
5 月 9 - 15 日
5 月 16 日至 22 日
5 月 23 日至 29 日

5 月的第 5 周:

从评论中我推断出您想从每月 1 号开始计算一个月中的周数。

您需要:

  • 将月中的第几天设置为 1

  • 向前添加,不向后滚动

  • 周日而不是周一开始

代码应该是这样的:

public static int getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(Calendar calendar) {
    while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
        calendar.roll(Calendar.DATE, true);
    }
    int currentMonth = calendar.get(Calendar.MONTH);
    int nextMonth = (currentMonth + 1) % 12;
    int prePreviousMonth = (currentMonth + 12 - 2) % 12;
    int nofWeeks = 0;
    do {
        int month = calendar.get(Calendar.MONTH);
        if (month == currentMonth) {
            nofWeeks++;
        } else {
            break;
        }
        calendar.add(Calendar.WEEK_OF_YEAR, 1);
    } while (true);
    return nofWeeks;
}


public static void main(String[] args) {

    int numWeeks;
    int totalWeeks=0;
    for (int i = 0; i < 12; i++) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, 2016);
    calendar.set(Calendar.DAY_OF_MONTH, 1);

    calendar.set(Calendar.MONTH, i);
    numWeeks=getNofWeeksWithFirstWeekStartingWhenFirstDayOfMonthOccurs(calendar);
    System.out.println("no of weeks " + numWeeks);
    }
}

输出:

no of weeks 5
no of weeks 4
no of weeks 4
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 4
no of weeks 5
no of weeks 4
no of weeks 4

我觉得你应该:

  • 算出一个月的第一天
  • 从中确定与上个月相比 "borrowed" 有多少 "extra" 天(例如,如果第 1 天是星期一,则为 0;如果第 1 天是星期二,则为 1,等等)
  • 将其添加到常规月份的天数中
  • 除以 7(隐式截断为 0)

无需完成您当前正在做的一半工作。

使用java.util.Calendar,它会是这样的:

// Note: day-of-week runs from Sunday (1) to Saturday (7).
// Entry 0 here is not used. We could do this without an array lookup
// if desired, but it's whatever code you think is clearest.
private static final int[] EXTRA_DAYS = { 0, 6, 0, 1, 2, 3, 4, 5 };

// Note: 0-based month as per the rest of java.util.Calendar
public static int getWeekCount(int year, int month) {
    Calendar calendar = new GregorianCalendar(year, month, 1);
    int dayOfWeekOfStartOfMonth = calendar.get(Calendar.DAY_OF_WEEK);
    int extraDays = EXTRA_DAYS[dayOfWeekOfStartOfMonth];
    int regularDaysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    int effectiveDaysInMonth = regularDaysInMonth + extraDays;
    return effectiveDaysInMonth / 7;
}

不过,如果可能的话,我建议改用 Joda Time 或 java.time

使用该代码,2016 年的结果是:

  • 1 月:5
  • 二月:4
  • 三月:4
  • 4 月:4
  • 五月:5
  • 6 月:4
  • 7 月:5
  • 八月:4
  • 9 月:4
  • 十月:5
  • 11 月:4
  • 12 月:4