Bagaimana saya bisa menemukan umur dalam python dari tanggal hari ini dan tanggal lahir seseorang? Tanggal lahir adalah dari DateField dalam model Django.
a nitpick: date.today()mengembalikan tanggal di zona waktu lokal yang mungkin berbeda dari tempat lahir. Anda mungkin perlu menggunakan zona waktu secara eksplisit
jfs
10
Itu mungkin tergantung pada definisi Anda tentang "usia". Untuk semua tujuan praktis, ulang tahun biasanya diberikan sebagai tanggal, bukan waktu-sadar zona waktu (yaitu, "lahir" tidak ada detailnya). Kebanyakan orang tidak dilahirkan pada tengah malam tajam (jadi biasanya mengamati sebelum waktunya :-)), dan ketika di zona waktu yang berbeda, saya akan berasumsi bahwa sebagian besar orang merayakan ulang tahun mereka di waktu setempat (itulah yang saya lakukan, saya hidup 10-12 jam ke depan waktu kelahiran saya). Jika "lahir" adalah waktu-sadar zona waktu, Anda bisa menggunakan aritmatika dan menormalkan pytz () - mungkin menarik untuk perangkat lunak astrologi?
Danny W. Adair
2
Saya setuju sepenuhnya dalam konteks usia manusia tetapi formula Anda dapat digunakan dalam konteks yang lebih luas. Meskipun saya pribadi tidak pernah merayakan ulang tahun saya bahkan satu jam sebelumnya karena tradisi keluarga dan menjadi seorang programmer, itu sepele untuk menghitung waktu di mana pun saya berada.
jfs
@ pyd: born adalah tanggal / datetime
kjagiello
68
from datetime import datedef calculate_age(born):
today = date.today()try:
birthday = born.replace(year=today.year)exceptValueError:# raised when birth date is February 29 and the current year is not a leap year
birthday = born.replace(year=today.year, month=born.month+1, day=1)if birthday > today:return today.year - born.year -1else:return today.year - born.year
Sama seperti prinsipnya, exceptblok Anda harus menangkap hanya satu pengecualian khusus yang dapat dinaikkan.
Daenyth
1
@ Ketidaksamaan: Panggilan bagus ... Saya pikir ini adalah ValueError. Diperbarui.
mpen
Saya bahkan melangkah lebih jauh dengan menguji pesan pengecualian untuk memastikan apa yang saya harapkan. Bahkan dengan kode di atas, ada kemungkinan ValueError dilemparkan, tetapi bukan ValueError yang Anda harapkan.
Randy Syring
+ untuk pengecualian tetapi, Apakah ada masalah di saya ? Saya pikir ini cukup sederhana. def calculate_age(dob)
Grijesh Chauhan
1
@GrijeshChauhan: Ya, milik Anda tidak berfungsi. datetime.date(2014, 1, 1)memberi -1, itu harus memberi 0. Anda today > dobsedang memeriksa apakah DOB di masa lalu, bukan awal tahun yang sama ini. datetime.date.today()termasuk informasi tahun, itulah sebabnya saya menggantinya dengan tahun berjalan dalam solusi saya.
mpen
18
from datetime import date
days_in_year =365.2425
age = int((date.today()- birth_date).days / days_in_year)
Di Python 3, Anda bisa melakukan pembagian pada datetime.timedelta:
from datetime import date, timedelta
age =(date.today()- birth_date)// timedelta(days=365.2425)
setiap tahun keempat adalah tahun kabisat kecuali setiap tahun keseratus bukan tahun kabisat kecuali setiap tahun keempat ratus adalah tahun kabisat. coba days_in_year = 365.2425
Dan
3
@Dan: perbedaan antara 365.25tahun kalender Julian ( ) dan Gregorian ( 365.2425) kurang dari sehari jika Anda hidup kurang dari 130 tahun.
jfs
4
Ini tidak berfungsi untuk beberapa tanggal: (date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)harus kembali 13, tetapi kembali 12. Unfloored, hasilnya adalah 12.999582469181433.
href_
13
Seperti yang disarankan oleh @ [Tomasz Zielinski] dan @Williams python-dateutil dapat melakukannya hanya 5 baris.
from dateutil.relativedelta import*from datetime import date
today = date.today()
dob = date(1982,7,5)
age = relativedelta(today, dob)>>relativedelta(years=+33, months=+11, days=+16)`
Cara paling sederhana adalah menggunakan python-dateutil
import datetimeimport dateutildef birthday(date):# Get the current date
now = datetime.datetime.utcnow()
now = now.date()# Get the difference between the current date and the birthday
age = dateutil.relativedelta.relativedelta(now, date)
age = age.yearsreturn age
Ini tidak berfungsi dengan benar ketika ulang tahun pada 29 Februari dan tanggal hari ini adalah 28 Februari (akan bertindak seolah-olah hari ini adalah 29 Februari).
Trey Hunner
6
from datetime import datedef age(birth_date):
today = date.today()
y = today.year - birth_date.yearif today.month < birth_date.month or today.month == birth_date.month and today.day < birth_date.day:
y -=1return y
tanggal instance atau beberapa keberatan seperti itu, docs.python.org/3/library/datetime.html#datetime.date, kesalahan ketik diperbaiki.
gzerone
5
Sayangnya, Anda tidak bisa hanya menggunakan timedelata karena unit terbesar yang digunakannya adalah hari dan tahun kabisat akan membuat perhitungan Anda tidak valid. Karena itu, mari kita cari jumlah tahun kemudian sesuaikan satu jika tahun lalu tidak penuh:
from datetime import date
birth_date = date(1980,5,26)
years = date.today().year - birth_date.year
if(datetime.now()- birth_date.replace(year=datetime.now().year)).days >=0:
age = years
else:
age = years -1
Pembaruan:
Solusi ini benar-benar menyebabkan pengecualian ketika Feb, 29 berperan. Ini cek yang benar:
from datetime import date
birth_date = date(1980,5,26)
today = date.today()
years = today.year - birth_date.year
if all((x >= y)for x,y in zip(today.timetuple(), birth_date.timetuple()):
age = years
else:
age = years -1
Upd2:
Memanggil beberapa panggilan ke now()hit kinerja adalah konyol, itu tidak masalah dalam semua kasus tetapi sangat istimewa. Alasan sebenarnya untuk menggunakan variabel adalah risiko inkosistensi data.
Terima kasih, saya mengetahuinya dengan melakukan beberapa tes - dan akhirnya menemukan kode serupa yang ditemukan dari tautan AndiDog.
tkalve
3
Strike 1: Anda menggunakan datetime.datetime alih-alih datetime.date. Strike 2: Kode Anda jelek dan tidak efisien. Memanggil datetime.now () TIGA kali ?? Mogok 3: Tanggal Lahir 29 Feb 2004 dan tanggal hari ini 28 Feb 2010 harus mengembalikan usia 6, tidak berteriak "ValueError: hari di luar jangkauan untuk bulan". Kamu keluar!
John Machin
Maaf, kode "Pembaruan" Anda bahkan lebih barok dan rusak daripada upaya pertama - tidak ada hubungannya dengan 29 Februari; gagal dalam BANYAK kasus sederhana seperti 2009-06-15 hingga 2010-07-02 ... orang tersebut jelas berusia di atas 1 tahun tetapi Anda mengurangi setahun karena pengujian pada hari-hari (2> = 15) gagal. Dan jelas Anda belum mengujinya - ini berisi kesalahan sintaksis.
John Machin
4
Gotcha klasik dalam skenario ini adalah apa yang harus dilakukan dengan orang yang lahir pada tanggal 29 Februari. Contoh: Anda harus berusia 18 tahun untuk memilih, mengendarai mobil, membeli alkohol, dll ... jika Anda dilahirkan pada 2004-02-29, apa hari pertama Anda diizinkan melakukan hal-hal seperti itu: 2022-02 -28, atau 2022-03-01? AFAICT, kebanyakan yang pertama, tetapi beberapa killjoys mungkin mengatakan yang terakhir.
Berikut kode yang sesuai untuk 0,068% (kurang-lebih) dari populasi yang lahir pada hari itu:
Jangan gunakan Django |timesinceuntuk menghitung timedelta selama beberapa tahun karena itu tidak memperhitungkan tahun kabisat dan karenanya menghasilkan hasil yang tidak akurat. Lihat tiket Django # 19210 untuk info lebih lanjut tentang ini.
jnns
Tidak tahu itu. Terima kasih.
Anoyz
2
Berikut adalah solusi untuk menemukan usia seseorang sebagai tahun atau bulan atau hari.
Katakanlah tanggal lahir seseorang adalah 2012-01-17T00: 00: 00
Karena itu, usianya pada 2013-01-16T00: 00: 00 adalah 11 bulan
atau jika ia dilahirkan pada 2012-12-17T00: 00: 00 , usianya pada 2013-01-12T00: 00: 00 akan menjadi 26 hari
atau jika dia dilahirkan pada 2000-02-29T00: 00: 00 , usianya pada 2012-02-29T00: 00: 00 akan menjadi 12 tahun
Anda perlu mengimpor datetime .
Ini kodenya:
def get_person_age(date_birth, date_today):"""
At top level there are three possibilities : Age can be in days or months or years.
For age to be in years there are two cases: Year difference is one or Year difference is more than 1
For age to be in months there are two cases: Year difference is 0 or 1
For age to be in days there are 4 possibilities: Year difference is 1(20-dec-2012 - 2-jan-2013),
Year difference is 0, Months difference is 0 or 1
"""
years_diff = date_today.year - date_birth.year
months_diff = date_today.month - date_birth.month
days_diff = date_today.day - date_birth.day
age_in_days =(date_today - date_birth).days
age = years_diff
age_string = str(age)+" years"# age can be in months or days.if years_diff ==0:if months_diff ==0:
age = age_in_days
age_string = str(age)+" days"elif months_diff ==1:if days_diff <0:
age = age_in_days
age_string = str(age)+" days"else:
age = months_diff
age_string = str(age)+" months"else:if days_diff <0:
age = months_diff -1else:
age = months_diff
age_string = str(age)+" months"# age can be in years, months or days.elif years_diff ==1:if months_diff <0:
age = months_diff +12
age_string = str(age)+" months"if age ==1:if days_diff <0:
age = age_in_days
age_string = str(age)+" days"elif days_diff <0:
age = age-1
age_string = str(age)+" months"elif months_diff ==0:if days_diff <0:
age =11
age_string = str(age)+" months"else:
age =1
age_string = str(age)+" years"else:
age =1
age_string = str(age)+" years"# The age is guaranteed to be in years.else:if months_diff <0:
age = years_diff -1elif months_diff ==0:if days_diff <0:
age = years_diff -1else:
age = years_diff
else:
age = years_diff
age_string = str(age)+" years"if age ==1:
age_string = age_string.replace("years","year").replace("months","month").replace("days","day")return age_string
Beberapa fungsi tambahan yang digunakan dalam kode di atas adalah:
def get_todays_date():"""
This function returns todays date in proper date object format
"""return datetime.now()
Dan
def get_date_format(str_date):"""
This function converts string into date type object
"""
str_date = str_date.split("T")[0]return datetime.strptime(str_date,"%Y-%m-%d")
Sekarang, kita harus memberi makan get_date_format () dengan string seperti 2000-02-29T00: 00: 00
Ini akan mengubahnya menjadi objek tipe tanggal yang akan diumpankan ke get_person_age (date_birth, date_today) .
Fungsi get_person_age (date_birth, date_today) akan mengembalikan umur dalam format string.
Memperluas Solusi Danny , tetapi dengan segala macam cara untuk melaporkan usia bagi kaum muda (catatan, hari ini datetime.date(2015,7,17)):
def calculate_age(born):'''
Converts a date of birth (dob) datetime object to years, always rounding down.
When the age is 80 years or more, just report that the age is 80 years or more.
When the age is less than 12 years, rounds down to the nearest half year.
When the age is less than 2 years, reports age in months, rounded down.
When the age is less than 6 months, reports the age in weeks, rounded down.
When the age is less than 2 weeks, reports the age in days.
'''
today = datetime.date.today()
age_in_years = today.year - born.year -((today.month, today.day)<(born.month, born.day))
months =(today.month - born.month -(today.day < born.day))%12
age = today - born
age_in_days = age.days
if age_in_years >=80:return80,'years or older'if age_in_years >=12:return age_in_years,'years'elif age_in_years >=2:
half ='and a half 'if months >6else''return age_in_years,'%syears'%half
elif months >=6:return months,'months'elif age_in_days >=14:return age_in_days/7,'weeks'else:return age_in_days,'days'
Kode sampel:
print'%d %s'%calculate_age(datetime.date(1933,6,12))# >=80 yearsprint'%d %s'%calculate_age(datetime.date(1963,6,12))# >=12 yearsprint'%d %s'%calculate_age(datetime.date(2010,6,19))# >=2 yearsprint'%d %s'%calculate_age(datetime.date(2010,11,19))# >=2 years with halfprint'%d %s'%calculate_age(datetime.date(2014,11,19))# >=6 monthsprint'%d %s'%calculate_age(datetime.date(2015,6,4))# >=2 weeksprint'%d %s'%calculate_age(datetime.date(2015,7,11))# days old80 years or older
52 years
5 years
4and a half years
7 months
6 weeks
7 days
Karena saya tidak melihat implementasi yang benar, saya recoded saya dengan cara ini ...
def age_in_years(from_date, to_date=datetime.date.today()):if(DEBUG):
logger.debug("def age_in_years(from_date='%s', to_date='%s')"%(from_date, to_date))if(from_date>to_date):# swap when the lower bound is not the lower bound
logger.debug('Swapping dates ...')
tmp = from_date
from_date = to_date
to_date = tmp
age_delta = to_date.year - from_date.year
month_delta = to_date.month - from_date.month
day_delta = to_date.day - from_date.day
if(DEBUG):
logger.debug("Delta's are : %i / %i / %i "%(age_delta, month_delta, day_delta))if(month_delta>0or(month_delta==0and day_delta>=0)):return age_delta
return(age_delta-1)
Anggapan sebagai "18" pada tanggal 28 Februari ketika lahir pada tanggal 29 adalah salah. Menukar batas dapat diabaikan ... itu hanya kenyamanan pribadi untuk kode saya :)
Sedikit modifikasi solusi Danny untuk memudahkan membaca dan memahami
from datetime import date
def calculate_age(birth_date):
today = date.today()
age = today.year - birth_date.year
full_year_passed =(today.month, today.day)<(birth_date.month, birth_date.day)ifnot full_year_passed:
age -=1return age
datetime
modul standar tidak cukup, Anda dapat mencoba: labix.org/python-dateutildateutil.relativedelta.relativedelta
Jawaban:
Itu bisa dilakukan lebih sederhana mengingat bahwa int (Benar) adalah 1 dan int (Salah) adalah 0:
sumber
date.today()
mengembalikan tanggal di zona waktu lokal yang mungkin berbeda dari tempat lahir. Anda mungkin perlu menggunakan zona waktu secara eksplisitPembaruan: Gunakan solusi Danny , lebih baik
sumber
except
blok Anda harus menangkap hanya satu pengecualian khusus yang dapat dinaikkan.ValueError
. Diperbarui.def calculate_age(dob)
datetime.date(2014, 1, 1)
memberi -1, itu harus memberi 0. Andatoday > dob
sedang memeriksa apakah DOB di masa lalu, bukan awal tahun yang sama ini.datetime.date.today()
termasuk informasi tahun, itulah sebabnya saya menggantinya dengan tahun berjalan dalam solusi saya.Di Python 3, Anda bisa melakukan pembagian pada
datetime.timedelta
:sumber
365.25
tahun kalender Julian ( ) dan Gregorian (365.2425
) kurang dari sehari jika Anda hidup kurang dari 130 tahun.(date(2017, 3, 1) - date(2004, 3, 1)) / timedelta(days=365.2425)
harus kembali13
, tetapi kembali12
. Unfloored, hasilnya adalah12.999582469181433
.Seperti yang disarankan oleh @ [Tomasz Zielinski] dan @Williams python-dateutil dapat melakukannya hanya 5 baris.
sumber
Cara paling sederhana adalah menggunakan
python-dateutil
sumber
sumber
Sayangnya, Anda tidak bisa hanya menggunakan timedelata karena unit terbesar yang digunakannya adalah hari dan tahun kabisat akan membuat perhitungan Anda tidak valid. Karena itu, mari kita cari jumlah tahun kemudian sesuaikan satu jika tahun lalu tidak penuh:
Pembaruan:
Solusi ini benar-benar menyebabkan pengecualian ketika Feb, 29 berperan. Ini cek yang benar:
Upd2:
Memanggil beberapa panggilan ke
now()
hit kinerja adalah konyol, itu tidak masalah dalam semua kasus tetapi sangat istimewa. Alasan sebenarnya untuk menggunakan variabel adalah risiko inkosistensi data.sumber
Gotcha klasik dalam skenario ini adalah apa yang harus dilakukan dengan orang yang lahir pada tanggal 29 Februari. Contoh: Anda harus berusia 18 tahun untuk memilih, mengendarai mobil, membeli alkohol, dll ... jika Anda dilahirkan pada 2004-02-29, apa hari pertama Anda diizinkan melakukan hal-hal seperti itu: 2022-02 -28, atau 2022-03-01? AFAICT, kebanyakan yang pertama, tetapi beberapa killjoys mungkin mengatakan yang terakhir.
Berikut kode yang sesuai untuk 0,068% (kurang-lebih) dari populasi yang lahir pada hari itu:
Inilah hasilnya:
sumber
Jika Anda ingin mencetak ini di halaman menggunakan templat Django, maka berikut ini mungkin cukup:
sumber
|timesince
untuk menghitung timedelta selama beberapa tahun karena itu tidak memperhitungkan tahun kabisat dan karenanya menghasilkan hasil yang tidak akurat. Lihat tiket Django # 19210 untuk info lebih lanjut tentang ini.Berikut adalah solusi untuk menemukan usia seseorang sebagai tahun atau bulan atau hari.
Katakanlah tanggal lahir seseorang adalah 2012-01-17T00: 00: 00 Karena itu, usianya pada 2013-01-16T00: 00: 00 adalah 11 bulan
atau jika ia dilahirkan pada 2012-12-17T00: 00: 00 , usianya pada 2013-01-12T00: 00: 00 akan menjadi 26 hari
atau jika dia dilahirkan pada 2000-02-29T00: 00: 00 , usianya pada 2012-02-29T00: 00: 00 akan menjadi 12 tahun
Anda perlu mengimpor datetime .
Ini kodenya:
Beberapa fungsi tambahan yang digunakan dalam kode di atas adalah:
Dan
Sekarang, kita harus memberi makan get_date_format () dengan string seperti 2000-02-29T00: 00: 00
Ini akan mengubahnya menjadi objek tipe tanggal yang akan diumpankan ke get_person_age (date_birth, date_today) .
Fungsi get_person_age (date_birth, date_today) akan mengembalikan umur dalam format string.
sumber
Memperluas Solusi Danny , tetapi dengan segala macam cara untuk melaporkan usia bagi kaum muda (catatan, hari ini
datetime.date(2015,7,17)
):Kode sampel:
sumber
Karena saya tidak melihat implementasi yang benar, saya recoded saya dengan cara ini ...
Anggapan sebagai "18" pada tanggal 28 Februari ketika lahir pada tanggal 29 adalah salah. Menukar batas dapat diabaikan ... itu hanya kenyamanan pribadi untuk kode saya :)
sumber
Perpanjang ke Danny W. Adair Answer , untuk mendapatkan bulan juga
sumber
Tanggal hari ini
Tanggal lahirmu
Usia kamu
sumber
mengimpor datetime
Dalam kasus Anda:
sumber
Sedikit modifikasi solusi Danny untuk memudahkan membaca dan memahami
sumber