一个月有多少个星期日(包括周一等)?
给定一个(公历)月,我如何找出该月中有多少个星期二(或星期三,或……)?这个月要么有4个,要么有5个,但到底是哪个?
一种简单的解决办法是遍历从29日开始直到该月的天数。如果其中有哪一天是所请求的星期几,就返回5,否则返回4。但我确定并不需要通过遍历来计算这个……?
我们可以假设这个月是用它的第一天表示的,即2026-05-01表示2026年 5月。
我尝试了很多,但大多数解法都很复杂:要写大量代码/运算,或在算法上让人难以理解。
解决方案
其实,由于一个月只有28到 31天,这可以通过一个基础的分情况判断来解决,随后又可以简化为一个简洁的算术表达式。
让我们在isolation1中逐一查看每种情况:
- 28天:显然这个月恰好有四个完整的周,因此答案是4。
- 29天:无论月初是哪一天,都会在四周后再次出现。因此如果第一天就是我们关心的那一天,答案就是5,否则为4。
- 30天:在四周后,月的前两天也会再次出现。因此如果这前两天中有一天是我们关心的那一天,答案为5,否则为4。
- 31天:类似的,只不过前三天中必须有一天是我们关心的那一天。
因此,如果计算“我们关心的那一天”与月初第一天之间的距离:29天的月份距离必须为0;30天的月份最多为1;31天的月份最多为2。
因此,我们得到如下代码:
static int CountDayOfWeekInMonth(DateTime firstDayOfMonth, DayOfWeek day)
{
int daysInMonth = DateTime.DaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month);
if(daysInMonth == 28)
return 4;
// Wrap around if the distance is negative
int distance = (7 + (int)day - (int)firstDayOfMonth.DayOfWeek) % 7;
return distance <= daysInMonth - 29 ? 5 : 4;
/*
Equivalent to:
if(daysInMonth == 29 && distance == 0)
return 5;
if(daysInMonth == 30 && distance <= 1)
return 5;
if(daysInMonth == 31 && distance <= 2)
return 5;
return 4;
*/
}
1我认为这个规律可以通过查阅日历快速理解,例如这张2026年 5月的日历(31天):
+-----+-----+-----+-----+-----+-----+-----+
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
+-----+-----+-----+-----+-----+-----+-----+
| | | | | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
+-----+-----+-----+-----+-----+-----+-----+
周五、周六和周日是月初的三天,它们也是唯一会出现五次的日期。如果假设周日是我们关心的那一天,那么到第一天(周五)的距离是2。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。