[LeetCode] 1360. Number of Days Between Two Dates 日期之间隔几天

发布时间 2023-11-12 12:24:47作者: Grandyang

Write a program to count the number of days between two dates.

The two dates are given as strings, their format is YYYY-MM-DD as shown in the examples.

Example 1:

Input: date1 = "2019-06-29", date2 = "2019-06-30"
Output: 1

Example 2:

Input: date1 = "2020-01-15", date2 = "2019-12-31"
Output: 15

Constraints:

  • The given dates are valid dates between the years 1971 and 2100.

这道题给了两个 YYYY-MM-DD 格式的日期,让返回两个日期之间的天数,题目中限定了年份的范围是 1971 年到 2100 年之间。根据题目中的两个例子可以发现,两个给定的日期之间的早晚关系是不确定的,为了使的 date1 的时间早于 date2,在最开始时做个小判断,即当 date1 晚于 date2 时,返回调用原函数,并且调换 date1 和 date2 之间的顺序。然后就是要分别提取出 date1 和 date2 中的年月日,由于给定的日期的格式是固定的,所以年月日所在的位置和长度也是固定的,可以用取子串的函数 substr 来取出年月日,并且调用字符串转整型的函数 stoi 来得到整型数格式的年月日。

接下来就要考虑如何实现计算两个日期之间的天数了,虽然现在知道 date1 是早于 date2 的,但由于不知道年份是否相等,所以 date1 的月份跟 date2 的月份的大小关系是不确定的,不太好直接计算之间的天数。所以此时需要找一个基准点,这里比较方便的就是用其当年的1月1号,即计算出离当年一月一号之间的天数。这个可以用一个子函数 daysFromTheYear 来得到。为了方便整月天数的计算,可以将每个月的天数放到一个数组中,方便使用。还有就是要考虑闰年的问题,闰年的2月是有29天的,判断闰年可以放到一个子函数中。想必大家对判断闰年的方法都很熟悉了吧,若某个年份能被 100 整除,则其必须能被 400 整除的是闰年,还有就是不能被 100 整除,但能被4整除的年份也是闰年。

有了统计天数的函数之外,还需要一个统计给定两个年份之间的天数的子函数,因为 date1 和 date2 可能不是同一年,可能相差好几年。这个整年之间的天数很好统计,除了闰年之外都是 365 天,对每个年份判断一下,若是闰年,就多加1天。有了这两个子函数,就可以求 date1 和 date2 之间的天数了,这里分两种情况来讨论:假如 date1 和 date2 是同一年的话,则分别计算其距离1月1号的天数,然后相减就是 date1 和 date2 之间的天数。若不在同一年,则计算 date1 的年份到 date2 的年份减1的整年之间的天数,然后要减去 date1 距其当年1月1号之间的天数,因为计算的是整年的天数,要减去这些多算的天数。然后还要加上 date2 具体其当前1月1号的天数,因为整年天数没有算这一年,要把这些天数加上才行,参见代码如下:


解法一:

class Solution {
public:
    int daysBetweenDates(string date1, string date2) {
        if (date1 > date2) return daysBetweenDates(date2, date1);
        int y1 = stoi(date1.substr(0, 4)), m1 = stoi(date1.substr(5, 2)), d1 = stoi(date1.substr(8, 2));
        int y2 = stoi(date2.substr(0, 4)), m2 = stoi(date2.substr(5, 2)), d2 = stoi(date2.substr(8, 2));
        return y1 == y2 ? daysFromTheYear(y2, m2, d2) - daysFromTheYear(y1, m1, d1) : daysBetweenTwoYears(y1, y2 - 1) - daysFromTheYear(y1, m1, d1) + daysFromTheYear(y2, m2, d2);
    }
    int daysFromTheYear(int y, int m, int d) {
        int res = 0;
        vector<int> monthDays{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31};
        for (int i = 1; i < m; ++i) {
            res += monthDays[i - 1];
        }
        if (m > 2 && isLeapYear(y)) ++res;
        return res + d;
    }
    int daysBetweenTwoYears(int y1, int y2) {
        if (y1 > y2) return daysBetweenTwoYears(y2, y1);
        int res = 0;
        for (int i = y1; i <= y2; ++i) {
            res += 365;
            if (isLeapYear(i)) res += 1;
        }
        return res;
    }
    bool isLeapYear(int year) {
        return (year % 100 == 0) ? (year % 400 == 0) : (year % 4 == 0);
    }
};

来看一种稍微简单一点的解法,由于年份的范围最早是 1971 年,那么可以将 1971 年1月1日当作基准点,分别计算 date1 和 date2 到 1971 年1月1日之间的天数,然后相减就可以得到 date1 和 date2 之间的天数了。计算到 1971 年1月1日的天数放到一个子函数中,先计算整年的天数,再计算整月的天数,再加上日的天数即可,注意还是要考虑闰年的情况,参见代码如下:


解法二:

class Solution {
public:
    int daysBetweenDates(string date1, string date2) {
        if (date1 > date2) return daysBetweenDates(date2, date1);
        int y1 = stoi(date1.substr(0, 4)), m1 = stoi(date1.substr(5, 2)), d1 = stoi(date1.substr(8, 2));
        int y2 = stoi(date2.substr(0, 4)), m2 = stoi(date2.substr(5, 2)), d2 = stoi(date2.substr(8, 2));
        return daysFrom1971(y2, m2, d2) - daysFrom1971(y1, m1, d1);
    }
    int daysFrom1971(int y, int m, int d) {
        int res = 0;
        vector<int> monthDays{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31};
        for (int i = 1971; i < y; ++i) {
            res += 365;
            if (isLeapYear(i)) ++res;
        }
        for (int i = 1; i < m; ++i) {
            res += monthDays[i - 1];
        }
        if (m > 2 && isLeapYear(y)) ++res;
        return res + d;
    }
    bool isLeapYear(int year) {
        return (year % 100 == 0) ? (year % 400 == 0) : (year % 4 == 0);
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1360


类似题目:

Count Days Spent Together


参考资料:

https://leetcode.com/problems/number-of-days-between-two-dates

https://leetcode.com/problems/number-of-days-between-two-dates/solutions/517605/similar-to-day-of-the-year/

https://leetcode.com/problems/number-of-days-between-two-dates/solutions/621582/c-short-simple-modular-solution/


LeetCode All in One 题目讲解汇总(持续更新中...)