日期之间隔几天

标签: 数学 字符串

难度: Easy

请你编写一个程序来计算两个日期之间隔了多少天。

日期以字符串形式给出,格式为 YYYY-MM-DD,如示例所示。

示例 1:

输入:date1 = "2019-06-29", date2 = "2019-06-30"
输出:1

示例 2:

输入:date1 = "2020-01-15", date2 = "2019-12-31"
输出:15

提示:

  • 给定的日期是 1971 年到 2100 年之间的有效日期。

Submission

运行时间: 23 ms

内存: 16.0 MB

class Solution:
    def daysBetweenDates(self, date1: str, date2: str) -> int:
        # 1971 1 1
        month_sum = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]
        def days(date: str):
            year, month, day = int(date[:4]), int(date[5:7]), int(date[8:10])
            days = (year-1971)*365 + month_sum[month-1] + day
            days += (year-1968) // 4
            if year == 2100 or (year % 4 == 0 and month <= 2):
                days -= 1
            return days
        return abs(days(date1) - days(date2))

Explain

该题解使用了一种数学计算的方法来计算两个日期之间的天数差。首先,为了方便计算,题解选择了一个基准日期(1971年1月1日)并计算从这个日期到给定日期的天数。这是通过以下步骤实现的:1. 计算从基准年到给定年份之前的完整年份中的天数,假设每年有365天。2. 使用一个预先计算好的数组 month_sum,该数组存储了在非闰年中,从年初到每个月第一天前的累积天数,使用这个数组可以快速得到从年初到指定月份的天数。3. 加上月内的天数。4. 考虑闰年对结果的影响,每四年有一个闰年(2月29日),因此需要添加相应的天数。然而,由于范围到2100年,需要特别处理2100年,因为它虽然能被4整除,但不是闰年。5. 最后,计算两个日期的天数差,将两个日期分别转换为从基准日期到它们的天数,然后取绝对值。

时间复杂度: O(1)

空间复杂度: O(1)

# 定义 Solution 类

class Solution:
    def daysBetweenDates(self, date1: str, date2: str) -> int:
        # 预存每年每月1号之前的天数累计,不考虑闰年
        month_sum = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]

        # 定义一个计算从1971年1月1日到给定日期天数的内部函数
        def days(date: str):
            # 解析日期
            year, month, day = int(date[:4]), int(date[5:7]), int(date[8:10])
            # 计算天数:年份差 * 365 + 月份天数累计 + 日
            days = (year-1971)*365 + month_sum[month-1] + day
            # 添加每四年的闰年天数
            days += (year-1968) // 4
            # 特殊处理闰年和2100年情况
            if year % 4 == 0 and (month <= 2) or year == 2100:
                days -= 1
            return days
        # 计算两个日期的天数差并取绝对值
        return abs(days(date1) - days(date2))

Explore

使用`(year-1971)*365`来计算基础天数是为了简化计算过程。首先,这一步计算假定了除了闰年外的所有年份都是365天,这使得年份的天数计算变得非常直接和快速。接着,通过另外计算闰年带来的额外天数,并进行相应的调整,可以有效地处理闰年。这种分步计算的方法,既简化了计算流程,也保证了计算的准确性。

数组`month_sum`是根据非闰年中每个月之前的天数累加构建的。它的设计是为了快速从年初到给定月份的天数进行查找,而不需要对每个月份逐个累加天数。对于闰年的特殊处理(2月29天),在计算总天数时通过检查年份和月份来进行调整。如果是闰年且日期在2月29日之后,需要在结果中额外加一天。这样,`month_sum`虽然基于非闰年构建,但通过条件判断正确处理了闰年2月的情况。

使用`(year-1968) // 4`是为了计算从1968年开始到指定年份之前的闰年数量。这是因为1971年是计算的基准年,而闰年的周期是每4年一次。通过从1968年开始计算,可以确保这一周期的正确对齐(1968年是闰年)。这样,确保了从1971年到给定年份的计算中闰年被正确计算。

对2100年的特殊处理是在计算过程中进行的。虽然2100年能被4整除,按常规判断应是闰年,但按照格里高利历规则,因为它不能被100整除却不能被400整除,所以它不是闰年。在代码中,特别检查了这一年份,如果计算的年份是2100且计算的日期位于3月1日或之后,由于2100年2月没有29日,所以需要从总天数中减去1天,以反映这一非闰年状态。