【问题标题】:Is there a simple way to get the number of years and days between 2 dates?有没有一种简单的方法来获取两个日期之间的年数和天数?
【发布时间】:2020-01-21 14:20:34
【问题描述】:

我有一个代表出生日期的字符串,我想知道这个人的年龄和天数。

例如: 出生 = 07/04/1994(月/日/年)

所以这个人是 25 岁 78 岁

但到目前为止,当我在日期之间进行减法时,使用datetime 得到的结果是天数。而且由于闰年,我永远无法确定确切的天数。


In [1]:
from datetime import date, datetime
today = date.today()

birth = '10/21/1996'
birth_date = datetime.strptime(datetime.strptime(birth, '%m/%d/%Y').strftime('%Y-%m-%d'),'%Y-%m-%d').date()
delta = today - birth_date
print(delta.days)

Out [1]:
8369

【问题讨论】:

  • 没有。一年不是一个明确定义的时间段。
  • 我认为,也许pendulum 能够做到这一点。不太确定
  • 你的已经很简单了!
  • @schwobaseggl,一年的定义非常非常(至少在公历上)。将一天计数转换为精确的y/d 集可能并不容易,但这只是因为您不知道开始(或结束)日期。一旦你知道了,你就可以得到准确的y/d 值。
  • @paxdiablo 一年的定义可能很好,但它的一般长度不是。在您的解决方案中计算的那 54 年中,有些比其他的要长。 timedelta 不接受关键字monthsyears 是有原因的。 “我正好 54 岁”这句话的第二个确切含义取决于说话的时间。

标签: python python-datetime


【解决方案1】:

不像内置 Python函数那么简单,但使用以下逻辑肯定是可行的:

  1. 构造一个基于当前年份减去一但出生月份和日期的日期。打电话给lastYearBirthday。还根据当前年份但出生月份和日期构建日期。打电话给currYearBirthday

  2. 如果currYearBirthdaytoday之后(今年还没有生日),则可以通过从year(lastYearBirthday)中减去year(birthdate)得到完整年数。使用(today - lastYearBirthday).days 获得的天数(自上次生日以来的天数)。

  3. 否则今年的生日已经发生(或今天发生),因此可以通过从 year(currYearBirthday) 中减去 year(birthdate) 来获得完整的年数 - 使用 @987654330 获得的天数@.

将其转换为您可以轻松使用的 Python 函数,我们得到:

from datetime import date

# Functions to return tuple of (fullYears, extraDays) for
# a given birth date.

def ageInYearsAndDays(birthDate):
    # Create relevant dates to ease task.

    today = date.today()
    lastYearBirthday = date(today.year - 1, birthDate.month, birthDate.day)
    currYearBirthday = date(today.year, birthDate.month, birthDate.day)

    # Work out years and days based on whether this years
    # birthday has happened. Basic idea is that years can
    # be calculated as difference between birth year and
    # year of most recent birthday. Days is the number of
    # days between most recent birthday and today.

    if currYearBirthday > today:
        years = lastYearBirthday.year - birthDate.year
        days = (today - lastYearBirthday).days
    else:
        years = currYearBirthday.year - birthDate.year
        days = (today - currYearBirthday).days

    return (years, days)

一些测试代码显示了我在这个凡人线圈上的自己不稳定的位置:

(years, days) = ageInYearsAndDays(date(1965, 2, 2))
print(years, "years and", days, "days")

输出结果(在发布此答案的当天)相当令人沮丧:

54 years and 230 days

:-)

请注意,我只是直接根据年、月和日构建了我的生日。由于您已经知道如何将字符串转换为其中之一(根据您的问题),因此我没有费心使用该方法。

【讨论】:

    【解决方案2】:

    用户在堆栈上为捕获闰年逻辑的另一个答案构建了以下代码。话虽如此,您将需要重构以满足您的需求...

    #Calculate the Days between Two Date
    
    daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    
    def isLeapYear(year):
    
        # Pseudo code for this algorithm is found at
        # http://en.wikipedia.org/wiki/Leap_year#Algorithm
        ## if (year is not divisible by 4) then (it is a common Year)
        #else if (year is not divisable by 100) then (ut us a leap year)
        #else if (year is not disible by 400) then (it is a common year)
        #else(it is aleap year)
        return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
    
    def Count_Days(year1, month1, day1):
        if month1 ==2:
            if isLeapYear(year1):
                if day1 < daysOfMonths[month1-1]+1:
                    return year1, month1, day1+1
                else:
                    if month1 ==12:
                        return year1+1,1,1
                    else:
                        return year1, month1 +1 , 1
            else: 
                if day1 < daysOfMonths[month1-1]:
                    return year1, month1, day1+1
                else:
                    if month1 ==12:
                        return year1+1,1,1
                    else:
                        return year1, month1 +1 , 1
        else:
            if day1 < daysOfMonths[month1-1]:
                 return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                        return year1, month1 +1 , 1
    
    
    def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):
    
        if y1 > y2:
            m1,m2 = m2,m1
            y1,y2 = y2,y1
            d1,d2 = d2,d1
        days=0
        while(not(m1==m2 and y1==y2 and d1==d2)):
            y1,m1,d1 = Count_Days(y1,m1,d1)
            days+=1
        if end_day:
            days+=1
        return days
    
    
    # Test Case
    
    def test():
        test_cases = [((2012,1,1,2012,2,28,False), 58), 
                      ((2012,1,1,2012,3,1,False), 60),
                      ((2011,6,30,2012,6,30,False), 366),
                      ((2011,1,1,2012,8,8,False), 585 ),
                      ((1994,5,15,2019,8,31,False), 9239),
                      ((1999,3,24,2018,2,4,False), 6892),
                      ((1999,6,24,2018,8,4,False),6981),
                      ((1995,5,24,2018,12,15,False),8606),
                      ((1994,8,24,2019,12,15,True),9245),
                      ((2019,12,15,1994,8,24,True),9245),
                      ((2019,5,15,1994,10,24,True),8970),
                      ((1994,11,24,2019,8,15,True),9031)]
    
        for (args, answer) in test_cases:
            result = daysBetweenDates(*args)
            if result != answer:
                print "Test with data:", args, "failed"
            else:
                print "Test case passed!"
    
    test()
    

    How to calculate number of days between two given dates?

    【讨论】:

    • 根据 OP 的问题,这不是简单地提供您从 (date - date).days 获得的信息吗?我认为他们想要一种准确的方法将其转化为年复一年。
    【解决方案3】:

    9 月堆栈溢出的好日子里的很多练习。这应该向您说明逻辑。请注意,只有当年份被完全除以 4、100 或 400 时才是闰年。然后您可以利用 datetime 属性获得乐趣。

    from datetime import date, datetime
    today = date.today()
    
    birth = '10/21/1996'
    birth_date = datetime.strptime(datetime.strptime(
        birth, '%m/%d/%Y').strftime('%Y-%m-%d'), '%Y-%m-%d').date()
    delta = today - birth_date
    
    days = delta.days
    year_counter = 0
    if today.day >= birth_date.day and today.month >= birth_date.month:
        full_years = today.year
    else:
        full_years = today.year - 1
    
    for year in range(1996, full_years):
        if (year % 4) == 0 or (year % 100) == 0 or (year % 400) == 0:
            days -= 366
            year_counter += 1
        else:
            days -= 365
            year_counter += 1
    
    print("years: " + str(year_counter) + "\ndays: " + str(days))
    

    显然有更多的 Pythonic 方式来编写它,但我想你想要一些可读性。

    【讨论】:

    • 感谢您的回答,但这并不是您想的大学逻辑测试。只是一个我不想“浪费时间”的个人项目。我正在寻找具有内置功能的软件包。我认为Pendulum 可能是个好人
    • 我的错。那时dateutil 可能更有用。查看relative delta
    猜你喜欢
    • 2018-04-29
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多