0%

日期问题

LC1118 一月有多少天
LC1154 一年中的第几天
LC1360 日期之间间隔几天
LC1185 一周中的第几天

闰年

  • 四年一闰,百年不闰,四百年再闰: (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
  • 从公元1年开始的闰年个数:year / 4 - year / 100 + year / 400
  • 闰年的二月有29天,平年的二月有28天。

LC1118 一月有多少天

计算y-m-d自1-1-1的天数

不考虑历史因素(儒略历到格里高利历的更改)。认为1-1-1是第0天。

设该日期为:y-m-d

  • 1-1-1y-1-1的左闭右开区间内的天数:
    • 不考虑平年闰年,则自1-1-1起,到今年初y-1-1的左闭右开区间内共有365 * (y - 1)$天。
    • 1-1-1到去年(y - 1年)共有leap = (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400个闰年。则应补上leap天。
  • y-1-1y-m-1的左闭右开区间内的天数:
    • 将平年每月的天数记录到数组中,为方便计算,前方留0:mdays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    • 则经过的天数为accumulate(mdays.begin(), mdays.begin() + m)天。
    • 如果今年是闰年,并且m > 2,则应该补上1天。
  • y-m-1y-m-d的左闭右开区间的天数为d - 1天。

总计:

1
2
3
4
5
6
7
8
mkdays(int y, int m, int d)
{
return (365 * (y - 1))
+ (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400
+ accumulate(mdays.begin(), mdays.begin() + m, 0)
+ (((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) && m > 2)
+ d - 1;
}


LC1154 一年中的第几天

即计算y-1-1y-m-d经过的天数:

  • y-1-1y-m-1的左闭右开区间内的天数:
    • 将平年每月的天数记录到数组中,为方便计算,前方留0:mdays = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    • 则经过的天数为accumulate(mdays.begin(), mdays.begin() + m)天。
    • 如果今年是闰年,并且m > 2,则应该补上1天。
  • y-m-1y-m-d的左闭右开区间的天数为d天。
  • 加上1天,因为y-1-1是第1天,不是第0天。

LC1360 日期之间间隔几天

计算两个日期的间隔,就是计算两个日期到1-1-1的天数差。

y-m-d是星期几

不考虑历史因素,只按照现行历法回推,1-1-1天是星期一。

因此日期y-m-d是星期几可以按下面的程序计算:

1
int day_of_the_week = mkdays(y, m, d) % 7 + 1;

LC1185 一周中的第几天