Mig*_*gol 124 python datetime timedelta
我需要检查自某个日期以来是否有多少年.目前我timedelta已从datetime模块中获取,我不知道如何将其转换为多年.
Ric*_*and 146
你需要的不仅仅是timedelta告诉已经过了多少年; 你还需要知道开始(或结束)日期.(这是闰年的事情.)
您最好的选择是使用该dateutil.relativedelta 对象,但这是第三方模块.如果您想知道从某个日期开始的datetime那n几年(默认为现在),您可以执行以下操作::
from dateutil.relativedelta import relativedelta
def yearsago(years, from_date=None):
if from_date is None:
from_date = datetime.now()
return from_date - relativedelta(years=years)
Run Code Online (Sandbox Code Playgroud)
如果您更愿意使用标准库,答案会更复杂一些::
from datetime import datetime
def yearsago(years, from_date=None):
if from_date is None:
from_date = datetime.now()
try:
return from_date.replace(year=from_date.year - years)
except ValueError:
# Must be 2/29!
assert from_date.month == 2 and from_date.day == 29 # can be removed
return from_date.replace(month=2, day=28,
year=from_date.year-years)
Run Code Online (Sandbox Code Playgroud)
如果它是2/29,而18年前没有2/29,这个功能将返回2/28.如果您宁愿返回3/1,只需将最后一个return语句更改为:
return from_date.replace(month=3, day=1,
year=from_date.year-years)
Run Code Online (Sandbox Code Playgroud)
你的问题最初说你想知道自某个约会以来已经过了多少年.假设您需要整数年,您可以根据每年365.25天进行猜测,然后使用yearsago上面定义的任一函数进行检查::
def num_years(begin, end=None):
if end is None:
end = datetime.now()
num_years = int((end - begin).days / 365.25)
if begin > yearsago(num_years, end):
return num_years - 1
else:
return num_years
Run Code Online (Sandbox Code Playgroud)
Ada*_*eld 46
如果您正在尝试检查某人是否年满18岁,timedelta由于闰年,使用将无法在某些边缘情况下正常工作.例如,2000年1月1日出生的人,将于2018年1月1日(包括5个闰年)完全在6575天后满18岁,但2001年1月1日出生的人将在1月1日的6574天之后满18岁, 2019年(包括4个闰年).因此,如果有人正好6574天,你无法确定他们是17岁还是18岁而不知道他们的出生日期的更多信息.
这样做的正确方法是直接从日期计算年龄,减去两年,然后如果当前月/日在出生月/日之前减去一年.
首先,在最详细的层面上,问题无法准确解决.年份长短不一,并且年份长度没有明确的"正确选择".
也就是说,获得任何单位"自然"(可能是秒)的差异,并除以它与年份之间的比率.例如
delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)
Run Code Online (Sandbox Code Playgroud)
...管他呢.远离几个月,因为它们的定义甚至不如几年.
小智 7
` 简单的解决方案!
import datetime as dt
from dateutil.relativedelta import relativedelta
dt1 = dt.datetime(1990,2,1)
dt2 = dt.datetime(2021,5,16)
out = relativedelta(dt2, dt1)
print(f'Complete: {out}')
print(f'years:{out.years}, months:{out.months}, days:{out.days}') `
Run Code Online (Sandbox Code Playgroud)
完成:relativedelta(年=+31,月=+3,天=+15)
年:31,月:3,天:15
这是一个更新的DOB功能,它以与人类相同的方式计算生日:
import datetime
import locale
# Source: https://en.wikipedia.org/wiki/February_29
PRE = [
'US',
'TW',
]
POST = [
'GB',
'HK',
]
def get_country():
code, _ = locale.getlocale()
try:
return code.split('_')[1]
except IndexError:
raise Exception('Country cannot be ascertained from locale.')
def get_leap_birthday(year):
country = get_country()
if country in PRE:
return datetime.date(year, 2, 28)
elif country in POST:
return datetime.date(year, 3, 1)
else:
raise Exception('It is unknown whether your country treats leap year '
+ 'birthdays as being on the 28th of February or '
+ 'the 1st of March. Please consult your country\'s '
+ 'legal code for in order to ascertain an answer.')
def age(dob):
today = datetime.date.today()
years = today.year - dob.year
try:
birthday = datetime.date(today.year, dob.month, dob.day)
except ValueError as e:
if dob.month == 2 and dob.day == 29:
birthday = get_leap_birthday(today.year)
else:
raise e
if today < birthday:
years -= 1
return years
print(age(datetime.date(1988, 2, 29)))
Run Code Online (Sandbox Code Playgroud)
def age(dob):
import datetime
today = datetime.date.today()
if today.month < dob.month or \
(today.month == dob.month and today.day < dob.day):
return today.year - dob.year - 1
else:
return today.year - dob.year
>>> import datetime
>>> datetime.date.today()
datetime.date(2009, 12, 1)
>>> age(datetime.date(2008, 11, 30))
1
>>> age(datetime.date(2008, 12, 1))
1
>>> age(datetime.date(2008, 12, 2))
0
Run Code Online (Sandbox Code Playgroud)