Python 年内两个日期之间的肾盂差异?

Python 年内两个日期之间的肾盂差异?,python,datetime,Python,Datetime,下面有没有更有效的方法?我想把两个日期之间的年差作为一个标量。欢迎提出任何建议 from datetime import datetime start_date = datetime(2010,4,28,12,33) end_date = datetime(2010,5,5,23,14) difference = end_date - start_date difference_in_years = (difference.days + difference.seconds/86400)/36

下面有没有更有效的方法?我想把两个日期之间的年差作为一个标量。欢迎提出任何建议

from datetime import datetime
start_date = datetime(2010,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
difference  = end_date - start_date
difference_in_years = (difference.days + difference.seconds/86400)/365.2425

如果您的意思是在代码空间方面高效,那么不,这是最有效的方法。

更高效?不,但可能更正确。但这取决于你想要的正确程度。日期不是小事

年不是一个固定的长度。您想要闰年或正常年份的差异吗?:-)当你计算时,你总是会得到一个稍微不正确的答案。一天多少年?你说1/365.2425。嗯,是的,平均一千年,是的。但除此之外,情况并非如此

所以这个问题没有多大意义

要正确,您必须执行以下操作:

from datetime import datetime
from calendar import isleap
start_date = datetime(2005,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
diffyears = end_date.year - start_date.year
difference  = end_date - start_date.replace(end_date.year)
days_in_year = isleap(end_date.year) and 366 or 365
difference_in_years = diffyears + (difference.days + difference.seconds/86400.0)/days_in_year
在这种情况下,这是0.0012322917425568528年或0.662天的差异,考虑到这不是闰年


(然后我们忽略微秒。嘿。)

为了理解闰年,你几乎被迫将其分为两部分:整数年和小数年。两者都需要处理闰年,但方式不同——积分需要处理起始日期2月29日,分数必须处理一年中不同的天数。您希望分数部分以相等的数量递增,直到下一个周年日等于1.0,因此它应该基于结束日期后一年中的天数

您希望您的日期范围包括1900还是2100?如果你不这样做,事情会变得容易一些。
编辑:我花了很长时间来解释这一点。基本问题是日历年不是一个恒定的大小,但是您通过将其设置为1.0来强制它们保持恒定。因此,您提出的任何解决方案都会出现异常,您必须选择可以接受的异常。约翰·梅辛是对的

2008-02-28和2009-02-28有什么区别?大多数人都会同意,应该正好是1.0年。2008-03-01和2009-03-01的区别是什么?同样,大多数人都会同意应该正好是1.0年。如果您选择将日期表示为一年加上以日期为基础的零头一年,则不可能使这两种说法都成立。您的原始代码假设一天为一年的1/365.2425,或者任何代码假设每天有一年的固定分数,即使一天的大小代表闰年

我的主张是,你们需要把它分解成整数年和小数年,这是为了回避这个问题。如果你把之前的每一个条件都看作是一个完整的年份,你所要做的就是决定将哪个分数分配给剩余的天数。这个方案的问题是,您仍然无法理解(date2-date1)+date3,因为分数不能以任何一致性返回到一天

因此,我建议另一种编码,基于每年包含366天的数据,无论是闰年还是非闰年。首先,不正常的情况是,从2月29日起不能有一年(或2或3)的日期——“对不起,约翰尼,你今年没有生日,没有2月29日”并不总是可以接受的。第二个问题是,如果你试图强迫这样一个数字回到某个日期,你必须考虑非闰年,检查2月29日的特殊情况,并将其转换为3月1日

from datetime import datetime
from datetime import timedelta
from calendar import isleap

size_of_day = 1. / 366.
size_of_second = size_of_day / (24. * 60. * 60.)

def date_as_float(dt):
    days_from_jan1 = dt - datetime(dt.year, 1, 1)
    if not isleap(dt.year) and days_from_jan1.days >= 31+28:
        days_from_jan1 += timedelta(1)
    return dt.year + days_from_jan1.days * size_of_day + days_from_jan1.seconds * size_of_second

start_date = datetime(2010,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
difference_in_years = date_as_float(end_time) - date_as_float(start_time)
我并不是说这就是解决方案,因为我认为完美的解决方案是不可能的。但它有一些可取的特性:

  • 同一个月、同一天和同一时间的任何日期之间的差值将是一个精确的年数
  • 将差异添加到另一个日期将产生一个可以转换回有用日期的值

如果您想要精确的结果,我建议您使用该库


这是指完整的年份(例如,一个人的年龄)。如果你想要分数年,那么加上月、日、小时。。。达到所需的精度。

我使用其中一个来计算人的年龄:

import datetime
dob = datetime.date(1980, 10, 10)

def age():
    today = datetime.date.today()
    years = today.year - dob.year
    if today.month < dob.month or (today.month == dob.month and today.day < dob.day):
        years -= 1
    return years

def age2():
    today = datetime.date.today()
    this_year_birthday = datetime.date(today.year, dob.month, dob.day)
    if this_year_birthday < today:
        years = today.year - dob.year
    else:
        years = today.year - dob.year - 1
    return years
导入日期时间
dob=日期时间日期(1980年10月10日)
定义年龄():
今天=datetime.date.today()
年=今天。年-月。年
如果今天.month
只需执行以下操作:

from dateutil.relativedelta import relativedelta

myBirthday = datetime.datetime(1983,5,20,0,0,0,0)
now = datetime.datetime.now()



difference = relativedelta(now, myBirthday)
print("My years: "+str(difference.years))

以下是克斯特安廷在其“age2”功能中发布的内容的衍生产品。它略短/更干净,并使用了“年龄”或年差的传统/口语含义:

def ageInYears( d ):
    today = datetime.date.today()
    currentYrAnniversary = datetime.date( today.year, d.month, d.day )
    return (today.year - d.year) - (1 if today < currentYrAnniversary else 0)
def年限(d):
今天=datetime.date.today()
currentyr周年=datetime.date(今天.年,d.月,d.日)
返回(今天.year-d.year)-(如果今天<当前年份,则返回1,否则返回0)

以下是我在不使用外部依赖关系的情况下想到的:

def year_diff(d1, d2):
    """Returns the number of years between the dates as a positive integer."""
    later = max(d1, d2)
    earlier = min(d1, d2)

    result = later.year - earlier.year
    if later.month < earlier.month or (later.month == earlier.month and later.day < earlier.day):
        result -= 1

    return result
def年份差异(d1、d2):
“”“以正整数形式返回两个日期之间的年数。”“”
之后=最大值(d1,d2)
早期=最小值(d1,d2)
结果=后一年-前一年
如果later.month
更稳健的函数-计算年(年龄)和日的差异:

def get_diff_in_years_and_days(from_date, to_date):
    try:
        from_in_this_year = date(to_date.year, from_date.month, from_date.day)
    except:
        from_in_this_year = date(to_date.year, from_date.month, from_date.day-1) # today is feb in leap year

    if from_in_this_year <= to_date:
        years = to_date.year - from_date.year
        days = (to_date - from_in_this_year).days
    else:
        years = to_date.year - from_date.year - 1
        try:
            from_in_prev_year = date(to_date.year-1, from_date.month, from_date.day)
        except:
            from_in_prev_year = date(to_date.year-1, from_date.month, from_date.day-1) # today is feb in leap year
        days = (to_date - from_in_prev_year).days

    assert days>=0 and days<=365, days
    assert years>=0, years

    return years, days

因为我们即将结束

输出

Tim Bergling              8 Sep 1989     20 Apr 2018     died at 28
Stephen Hillenburg       21 Aug 1961     26 Nov 2018     died at 57
Stephen Hawking           8 Jan 1942     14 Mar 2018     died at 76
Stan Lee                 28 Dec 1922     12 Nov 2018     died at 95
Stefán Karl Stefánsson   10 Jul 1975     21 Aug 2018     died at 43

安装库之前:

choco upgrade Python -y
python pip install python-dateutil
在Cmder(windows)中Python的一行中:

批内转义百分比,含%%:

python -c "import datetime; from dateutil.relativedelta import relativedelta; myBirthday = datetime.datetime(2019,2,6,11,0,0,0); now = datetime.datetime.utcnow(); diff = relativedelta(now, myBirthday); print ("'My'+'" "'+'year'+'" "'+':'+'" "'+'%%d''" "''and''" "''%%d''" "''microseconds'" %% (diff.years, diff.microseconds))"

我想你要找的是:

difference_in_years = difference.dt.days / 365.25

BuvinJ解决方案的更新,该解决方案是美国
choco upgrade Python -y
python pip install python-dateutil
python -c "import datetime; from dateutil.relativedelta import relativedelta; myBirthday = datetime.datetime(2019,2,6,11,0,0,0); now = datetime.datetime.utcnow(); diff = relativedelta(now, myBirthday); print ("'My'+'" "'+'year'+'" "'+':'+'" "'+'%d''" "''and''" "''%d''" "''microseconds'" % (diff.years, diff.microseconds))"
python -c "import datetime; from dateutil.relativedelta import relativedelta; myBirthday = datetime.datetime(2019,2,6,11,0,0,0); now = datetime.datetime.utcnow(); diff = relativedelta(now, myBirthday); print ("'My'+'" "'+'year'+'" "'+':'+'" "'+'%%d''" "''and''" "''%%d''" "''microseconds'" %% (diff.years, diff.microseconds))"
difference_in_years = difference.dt.days / 365.25
from datetime import date

def ageInYears( d ):
    today = datetime.date.today()

    notQuiteYourBirthday = (today.month, today.day) < (born.month, born.day)
    return (today.year - d.year) - notQuiteYourBirthday
from datetime import datetime as dt

def get_age(dob_str):
    now_str = dt.strftime(dt.utcnow(), '%Y-%m-%d')
    return int(now_str[:4]) - int(dob_str[:4]) - int(dob_str[5:] > now_str[5:])
from datetime import datetime as dt

def get_age(dob_str, now_str=dt.strftime(dt.utcnow(), '%Y-%m-%d')):
    return int(now_str[:4]) - int(dob_str[:4]) - int(dob_str[5:] > now_str[5:])
from datetime import datetime

my_birthday = datetime(2000, 1, 1, 0, 0, 0, 0 )

now = datetime.now()

age = now.year - my_birthday.year

print(age)