Bir tarihten bu yana birkaç yıl geçip geçmediğini kontrol etmem gerekiyor. Şu elimdeki timedelta
gelen datetime
modül ve ben yıllardır dönüştürmek nasıl bilmiyorum.
Bir tarihten bu yana birkaç yıl geçip geçmediğini kontrol etmem gerekiyor. Şu elimdeki timedelta
gelen datetime
modül ve ben yıllardır dönüştürmek nasıl bilmiyorum.
Yanıtlar:
timedelta
Kaç yıl geçtiğini söylemek için a'dan fazlasına ihtiyacınız var; ayrıca başlangıç (veya bitiş) tarihini de bilmeniz gerekir. (Bu artık bir yıl.)
En iyi seçiminiz dateutil.relativedelta
nesneyi kullanmaktır , ancak bu bir üçüncü taraf modülüdür. Bunun belirli bir tarihten sonraki yıllar datetime
olduğunu bilmek istiyorsanız n
(varsayılan olarak şu an için), aşağıdakileri yapabilirsiniz ::
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)
Standart kütüphaneye bağlı kalmayı tercih ederseniz, cevap biraz daha karmaşıktır ::
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 ve 18 yıl önce 2/29 olmasaydı, bu işlev 2/28 döndürür. 3/1 döndürmek isterseniz, son return
ifadeyi şu şekilde değiştirin :
return from_date.replace(month=3, day=1,
year=from_date.year-years)
Sorunuz başlangıçta bir tarihten bu yana kaç yıl geçtiğini bilmek istediğinizi söyledi. Tam sayı bir yıl istediğinizi varsayarsak, yılda 365,25 güne göre tahmin edebilir ve sonra yearsago
yukarıda tanımlanan işlevlerden birini kullanarak kontrol edebilirsiniz ::
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()
) tarafından sunulan fark, ortalama Julian ( 365.25
) ve Gregorian ( 365.2425
) yılları arasındaki farktan daha büyük . . Doğru yaklaşım @Adam Rosenfield'ın cevabında
Birinin 18 yaşında olup olmadığını kontrol etmeye çalışıyorsanız timedelta
, artık yıllar nedeniyle bazı kenar durumlarda doğru şekilde çalışmaz. Örneğin, 1 Ocak 2000'de doğan biri, 1 Ocak 2018'de tam olarak 6575 gün sonra 18'i (5 artık yıl dahil), ancak 1 Ocak 2001'de doğan biri, 1 Ocak'ta tam olarak 6574 gün sonra 18'i, 2019 (4 artık yıl dahil). Böylece, eğer birisi tam olarak 6574 günlükse, doğum tarihi hakkında biraz daha fazla bilgi bilmeden 17 veya 18 olup olmadığını belirleyemezsiniz.
Bunu yapmanın doğru yolu, iki yılı çıkararak ve sonra geçerli ayın / günün doğum ayından / gününden önce olması durumunda yaşı doğrudan tarihlerden hesaplamaktır.
Öncelikle, en ayrıntılı düzeyde, sorun tam olarak çözülemez. Yıllar uzunluk olarak değişir ve yıl boyu için net bir "doğru seçim" yoktur.
Bununla birlikte, hangi birimlerin "doğal" (muhtemelen saniye) olduğu farkını elde edin ve o ve yıllar arasındaki orana bölün. Örneğin
delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)
...ya da her neyse. Yıllardan daha az iyi tanımlandıkları için aylardan uzak durun.
İşte doğum günlerini insanların yaptığı gibi hesaplayan güncellenmiş bir DOB işlevi:
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)))
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
Ne kadar kesin olması gerekiyor? td.days / 365.25
Eğer artık yıllar hakkında endişeleniyorsanız, size oldukça yakın olacak.
Yine burada belirtilmeyen başka bir 3. taraf lib mxDateTime (hem python hem de datetime
3. tarafın selefi timeutil
) bu görev için kullanılabilir.
Yukarıda belirtilenler 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)
İlk parametrenin bir DateTime
örnek olması beklenir .
Sıradan dönüştürmek datetime
için DateTime
bunu 1 saniye hassasiyetle kullanabilirsiniz):
def DT_from_dt_s(t):
return DT.DateTimeFromTicks(time.mktime(t.timetuple()))
veya 1 mikrosaniye hassasiyet için:
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)
Ve evet, söz konusu bu göreve bağımlılık eklemek, timeutil (Rick Copeland tarafından önerilen) kullanımı ile karşılaştırıldığında kesinlikle aşırıya kaçmak olacaktır.
Sonunda elinizde matematik sorunu var. Eğer her 4 yılda bir ekstra günümüz varsa, zaman dilimini 365 gün değil, 365 * 4 + 1 ile günler halinde dalış yapalım, bu size 4 yıl verir. Sonra tekrar 4'e bölün. Timedelta / ((365 * 4) +1) / 4 = timedelta * 4 / (365 * 4 +1)
Çalıştığım çözüm bu, umarım yardımcı olabilir ;-)
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
Bu iş parçacığı zaten ölü olsa da, karşılaştığım aynı sorun için çalışan bir çözüm önerebilir miyim. İşte (tarih dd-aa-yyyy biçiminde bir dizedir):
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
bu işlev iki tarih arasındaki yıl farkını döndürür (ISO biçiminde dize olarak alınır, ancak herhangi bir biçimde almak için kolayca değiştirilebilir)
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
Ben önermek olacak Pyfdate
Pyfdate nedir?
Python'un güçlü ve kullanımı kolay bir komut dosyası dili olma hedefi göz önüne alındığında, tarih ve saatlerle çalışma özellikleri olması gerektiği gibi kullanıcı dostu değildir. Pyfdate'in amacı, Python'un geri kalanı kadar güçlü ve kullanımı kolay tarih ve saatlerle çalışmak için özellikler sağlayarak bu durumu düzeltmektir.
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()
Bu, Atlı Karınca operatörünün Logan's Run filminde çalıştırdığı koddur;)
Bu soruya rastladım ve Adams'ın en faydalı yanıtı buldum https://stackoverflow.com/a/765862/2964689
Ama yönteminin python örneği yoktu ama işte sonunda kullandığım şey.
input: datetime nesnesi
çıktı: tam yıl tamsayı
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'nin basitliği için çözümünü beğendim ve 28 Şubat veya 1 Mart'ta artık bir yıl olmadığında, 29 Şubat'ta doğan insanların yaşını nasıl belirleyeceğinden endişe duymuyorum. Bence şikayetleri ele alıyor:
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