ฉันต้องตรวจสอบว่ามีบางปีที่ผ่านมานับตั้งแต่บางวัน ขณะนี้ฉันได้รับtimedelta
จากdatetime
โมดูลและไม่รู้วิธีแปลงเป็นปี
ฉันต้องตรวจสอบว่ามีบางปีที่ผ่านมานับตั้งแต่บางวัน ขณะนี้ฉันได้รับtimedelta
จากdatetime
โมดูลและไม่รู้วิธีแปลงเป็นปี
คำตอบ:
คุณต้องการมากกว่า a 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)
หากคุณต้องการที่จะใช้ไลบรารี่มาตรฐานคำตอบนั้นซับซ้อนกว่าเล็กน้อย ::
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)
หากเป็น 2/29 และ 18 ปีที่ผ่านมาไม่มี 2/29 ฟังก์ชันนี้จะส่งคืน 2/28 หากคุณต้องการส่งคืน 3/1 เพียงแค่เปลี่ยนreturn
คำสั่งสุดท้ายเพื่ออ่าน ::
return from_date.replace(month=3, day=1,
year=from_date.year-years)
ตอนแรกคำถามของคุณบอกว่าคุณต้องการที่จะรู้ว่ามันเป็นไปได้กี่ปีแล้ว สมมติว่าคุณต้องการจำนวนเต็มเป็นปีคุณสามารถเดาได้ตาม 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
datetime.now()
) มากกว่าความแตกต่างระหว่างค่าเฉลี่ย Julian ( 365.25
) และ Gregorian ( 365.2425
) ปี . แนะนำวิธีการที่ถูกต้องในคำตอบของ @Adam Rosenfield
หากคุณกำลังพยายามที่จะตรวจสอบว่ามีใครอายุ 18 ปีการใช้timedelta
จะไม่ทำงานอย่างถูกต้องในบางกรณีขอบเพราะปีอธิกสุรทิน ตัวอย่างเช่นคนที่เกิดในวันที่ 1 มกราคม 2000 จะมีอายุ 18 ปี 6575 วันต่อมาในวันที่ 1 มกราคม 2018 (รวม 5 ปีอธิกสุรทิน 5 ปี) แต่มีคนที่เกิดในวันที่ 1 มกราคม 2001 จะมีอายุ 18 ปี 6574 ในวันที่ 1 มกราคม 2019 (รวมการก้าวกระโดด 4 ปี) ดังนั้นหากคุณมีอายุ 6574 วันคุณไม่สามารถระบุได้ว่าพวกเขาอายุ 17 หรือ 18 ปีโดยไม่ทราบข้อมูลเพิ่มเติมเกี่ยวกับวันเกิดของพวกเขาหรือไม่
วิธีที่ถูกต้องในการทำเช่นนี้คือการคำนวณอายุโดยตรงจากวันที่โดยการลบสองปีแล้วลบหนึ่งถ้าเดือน / วันปัจจุบันนำหน้าเดือนเกิด / วัน
ก่อนอื่นในระดับรายละเอียดสูงสุดปัญหาจะไม่สามารถแก้ไขได้อย่างแน่นอน ปีมีความยาวแตกต่างกันและไม่มี "ทางเลือกที่ถูกต้อง" สำหรับความยาวปี
ที่กล่าวว่าได้รับความแตกต่างในสิ่งที่หน่วยเป็น "ธรรมชาติ" (อาจวินาที) และหารด้วยอัตราส่วนระหว่างที่และปี เช่น
delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)
... หรืออะไรก็ตาม อยู่ห่างจากเดือนเนื่องจากพวกเขายังนิยามน้อยกว่าปี
นี่คือฟังก์ชั่น 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)))
รับจำนวนวันแล้วหารด้วย 365.2425 (ค่าเฉลี่ยเกรกอเรียนปี) เป็นเวลาหลายปี หารด้วย 30.436875 (เดือน Gregorian เฉลี่ย) สำหรับเดือน
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
คุณต้องการให้มันแม่นยำแค่ไหน? td.days / 365.25
จะทำให้คุณเข้ามาใกล้ถ้าคุณกังวลเกี่ยวกับการก้าวกระโดดปี
อีกหนึ่งบุคคลที่สามที่ไม่ได้กล่าวถึงในที่นี้คือ mxDateTime lib (ผู้บุกเบิกของ python datetime
และบุคคลที่สามtimeutil
) สามารถใช้งานนี้ได้
ดังกล่าวข้างต้นyearsago
จะเป็น:
from mx.DateTime import now, RelativeDateTime
def years_ago(years, from_date=None):
if from_date == None:
from_date = now()
return from_date-RelativeDateTime(years=years)
พารามิเตอร์แรกคาดว่าจะเป็น DateTime
อินสแตนซ์
หากต้องการแปลงสามัญdatetime
เป็นDateTime
คุณสามารถใช้วิธีนี้เพื่อความแม่นยำ 1 วินาที):
def DT_from_dt_s(t):
return DT.DateTimeFromTicks(time.mktime(t.timetuple()))
หรือนี่เพื่อความแม่นยำ 1 ไมโครวินาที:
def DT_from_dt_u(t):
return DT.DateTime(t.year, t.month, t.day, t.hour,
t.minute, t.second + t.microsecond * 1e-6)
และใช่การเพิ่มการพึ่งพาสำหรับงานเดี่ยวที่เป็นปัญหานี้จะเป็นการ overkill เปรียบเทียบกับการใช้ timeutil (แนะนำโดย Rick Copeland)
ในที่สุดสิ่งที่คุณมีคือปัญหาคณิตศาสตร์ หากทุก ๆ 4 ปีเรามีวันพิเศษให้ดำดิ่ง timedelta เป็นวันไม่ใช่ 365 แต่ 365 * 4 + 1 ซึ่งจะให้จำนวน 4 ปี จากนั้นหารอีกครั้งโดย 4 timedelta / ((365 * 4) +1) / 4 = timedelta * 4 / (365 * 4 +1)
นี่คือทางออกที่ฉันได้ผลฉันหวังว่าจะช่วยได้ ;-)
def menor_edad_legal(birthday):
""" returns true if aged<18 in days """
try:
today = time.localtime()
fa_divuit_anys=date(year=today.tm_year-18, month=today.tm_mon, day=today.tm_mday)
if birthday>fa_divuit_anys:
return True
else:
return False
except Exception, ex_edad:
logging.error('Error menor de edad: %s' % ex_edad)
return True
แม้ว่าเธรดนี้จะตายไปแล้ว แต่ฉันขอแนะนำวิธีแก้ปัญหาการทำงานสำหรับปัญหาเดียวกันนี้ที่ฉันพบเจอ นี่คือ (วันที่เป็นสตริงในรูปแบบ dd-mm-yyyy):
def validatedate(date):
parts = date.strip().split('-')
if len(parts) == 3 and False not in [x.isdigit() for x in parts]:
birth = datetime.date(int(parts[2]), int(parts[1]), int(parts[0]))
today = datetime.date.today()
b = (birth.year * 10000) + (birth.month * 100) + (birth.day)
t = (today.year * 10000) + (today.month * 100) + (today.day)
if (t - 18 * 10000) >= b:
return True
return False
ฟังก์ชั่นนี้จะคืนความแตกต่างในปีระหว่างวันที่สองวัน (นำมาเป็นสตริงในรูปแบบ ISO แต่สามารถแก้ไขได้อย่างง่ายดายเพื่อใช้ในรูปแบบใด ๆ )
import time
def years(earlydateiso, laterdateiso):
"""difference in years between two dates in ISO format"""
ed = time.strptime(earlydateiso, "%Y-%m-%d")
ld = time.strptime(laterdateiso, "%Y-%m-%d")
#switch dates if needed
if ld < ed:
ld, ed = ed, ld
res = ld[0] - ed [0]
if res > 0:
if ld[1]< ed[1]:
res -= 1
elif ld[1] == ed[1]:
if ld[2]< ed[2]:
res -= 1
return res
ฉันจะแนะนำPyfdate
pyfdate คืออะไร
เป้าหมายของไพ ธ อนนั้นเป็นภาษาสคริปต์ที่ทรงพลังและง่ายต่อการใช้งานคุณสมบัติในการทำงานกับวันที่และเวลาไม่เป็นมิตรกับผู้ใช้เท่าที่ควร วัตถุประสงค์ของ pyfdate คือการแก้ไขสถานการณ์นั้นโดยการให้คุณสมบัติสำหรับการทำงานกับวันที่และเวลาที่มีประสิทธิภาพและใช้งานง่ายเหมือนกับ Python ที่เหลือ
import datetime
def check_if_old_enough(years_needed, old_date):
limit_date = datetime.date(old_date.year + years_needed, old_date.month, old_date.day)
today = datetime.datetime.now().date()
old_enough = False
if limit_date <= today:
old_enough = True
return old_enough
def test_ages():
years_needed = 30
born_date_Logan = datetime.datetime(1988, 3, 5)
if check_if_old_enough(years_needed, born_date_Logan):
print("Logan is old enough")
else:
print("Logan is not old enough")
born_date_Jessica = datetime.datetime(1997, 3, 6)
if check_if_old_enough(years_needed, born_date_Jessica):
print("Jessica is old enough")
else:
print("Jessica is not old enough")
test_ages()
นี่คือรหัสที่ผู้ประกอบการ Carrousel กำลังทำงานในภาพยนตร์ Run ของ Logan;)
ฉันเจอคำถามนี้และพบว่าอดัมส์ตอบคำถามที่เป็นประโยชน์ที่สุด https://stackoverflow.com/a/765862/2964689
แต่ไม่มีตัวอย่างไพ ธ อนเกี่ยวกับวิธีการของเขา แต่นี่คือสิ่งที่ฉันใช้
input: วัตถุวันที่และเวลา
เอาท์พุท: อายุจำนวนเต็มทั้งปี
def age(birthday):
birthday = birthday.date()
today = date.today()
years = today.year - birthday.year
if (today.month < birthday.month or
(today.month == birthday.month and today.day < birthday.day)):
years = years - 1
return years
ฉันชอบวิธีการแก้ปัญหาของ John Mee สำหรับความเรียบง่ายและฉันไม่กังวลเกี่ยวกับวิธีการในวันที่ 28 กุมภาพันธ์หรือ 1 มีนาคมเมื่อไม่ใช่ปีอธิกสุรทินเพื่อกำหนดอายุของคนที่เกิดในวันที่ 29 กุมภาพันธ์ แต่นี่เป็นรหัสบิดของเขา ซึ่งฉันคิดว่าอยู่ที่การร้องเรียน:
def age(dob):
import datetime
today = datetime.date.today()
age = today.year - dob.year
if ( today.month == dob.month == 2 and
today.day == 28 and dob.day == 29 ):
pass
elif today.month < dob.month or \
(today.month == dob.month and today.day < dob.day):
age -= 1
return age