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
我创建了一个函数,该函数应该获取给定月份的周数。对于一月、五月、七月和十月,应该 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