某月的天数
计算某年某月份中的天数,对于多数人来说,都是很简单的事情。但能否把程序写得足够简洁,就是另外一回事了。
先给出最终的代码:
1 |
|
如果你已经知道上述代码是如何得来的,就不必再往下看了。
为什么可以这样写?
先来看一下这个表格:
month | 天数 |
---|---|
1 | 31 |
2 | 28或29 |
3 | 31 |
4 | 30 |
5 | 31 |
6 | 30 |
7 | 31 |
8 | 31 |
9 | 30 |
10 | 31 |
11 | 30 |
12 | 31 |
然后对这个表格中的数据进行调整:
month | 天数 |
---|---|
1 | 31 -> 31 |
2 | 28或29 -> 30 |
3 | 31 -> 31 |
4 | 30 -> 30 |
5 | 31 -> 31 |
6 | 30 -> 30 |
7 | 31 -> 31 |
8 | 31 -> 31 |
9 | 30 -> 30 |
10 | 31 -> 31 |
11 | 30 -> 30 |
12 | 31 -> 31 |
也就是将2月份的天数,调整为了30天。
再调整:
month | 天数 | month | 天数 |
---|---|---|---|
1 | 31 -> 31 | 8 | 31 -> 31 |
2 | 28或29 -> 30 | 9 | 30 -> 30 |
3 | 31 -> 31 | 10 | 31 -> 31 |
4 | 30 -> 30 | 11 | 30 -> 30 |
5 | 31 -> 31 | 12 | 31 -> 31 |
6 | 30 -> 30 | ||
7 | 31 -> 31 |
这样,是不是看出点儿规律了?
规律:天数31与30是交替出现的(1到7月,8到12月),也就是说,存在ABABAB这样的模式。此处,暂且认为2月份的天数就是30天,最后会对其进行特殊处理。
现在,对月份进行取模,也让其出现上述规律,这样,最后就可以简单地通过加减运算得到正确的结果。
由于是每隔7个数,就会重现规律,因此需要先对7进行取模:
month | month % 7 | month | month % 7 |
---|---|---|---|
1 | 1 | 8 | 1 |
2 | 2 | 9 | 2 |
3 | 3 | 10 | 3 |
4 | 4 | 11 | 4 |
5 | 5 | 12 | 5 |
6 | 6 | ||
7 | 0 |
到这里,会发现,对于6、7月,month % 7
的结果都是偶数,为了最终得到ABABAB这样的规律,取模的结果必须是奇数偶数交替出现才可以。
因此,需要调整一下,将month % 7
调整为(month - 1) % 7
:
month | (month - 1) % 7 | 天数 | month | (month - 1) % 7 | 天数 |
---|---|---|---|---|---|
1 | 0 | 31 | 8 | 0 | 31 |
2 | 1 | 30 | 9 | 1 | 30 |
3 | 2 | 31 | 10 | 2 | 31 |
4 | 3 | 30 | 11 | 3 | 30 |
5 | 4 | 31 | 12 | 4 | 31 |
6 | 5 | 30 | |||
7 | 6 | 31 |
再用(month - 1) % 7
的结果对2取模:
month | (month - 1) % 7 % 2 | 天数 | month | (month - 1) % 7 % 2 | 天数 |
---|---|---|---|---|---|
1 | 0 | 31 | 8 | 0 | 31 |
2 | 1 | 30 | 9 | 1 | 30 |
3 | 0 | 31 | 10 | 0 | 31 |
4 | 1 | 30 | 11 | 1 | 30 |
5 | 0 | 31 | 12 | 0 | 31 |
6 | 1 | 30 | |||
7 | 0 | 31 |
这样,就可以使用31 - (month - 1) % 7 % 2
计算出某月的天数。
对2月份进行处理后,最终就是(2 == month) ? (28 + isLeapYear(year)) : (31 - (month - 1) % 7 % 2)
。
某月的天数
https://daniate.github.io/2018/08/26/某月的天数/