Muszę sprawdzić, czy od pewnej daty upłynęła pewna liczba lat. Obecnie mam timedelta
z modułu datetime
i nie wiem jak przekonwertować go na lata.Python timedelta w latach
Odpowiedz
Potrzebujesz więcej niż timedelta
, aby powiedzieć, ile minęło lat; musisz również znać datę początkową (lub końcową). (To jest rok przestępny.)
Najlepiej jest użyć dateutil.relativedelta
object, ale to moduł innej firmy. Jeśli chcesz wiedzieć datetime
że był n
lat od jakiegoś terminu (zalegających do teraz), można wykonać następujące czynności ::
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)
Jeśli wolisz pozostać przy standardowej biblioteki, odpowiedź jest trochę bardziej skomplikowane ::
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)
Jeśli to 2/29, a 18 lat temu nie było 2/29, funkcja ta zwróci 2/28. Jeśli wolisz wrócić 3/1, wystarczy zmienić ostatni return
oświadczenie czytać ::
return from_date.replace(month=3, day=1,
year=from_date.year-years)
Twoje pytanie pierwotnie powiedział, że chciał wiedzieć, ile lat minęło od jakiegoś terminu. Zakładając, że chcesz całkowitą liczbę lat, można się domyślać na podstawie 365,25 dni w roku, a następnie sprawdzić, korzystając z jednej z yearsago
funkcjami zdefiniowanymi powyżej ::
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
Możesz być w pełni dokładny z 365.2425 (zamiast 365.25), który bierze pod uwagę wyjątek 400 lat dla kalendarza gregoriańskiego. – brianary
Twoja funkcja legalnie łamie się w krajach takich jak Wielka Brytania i Hongkong, ponieważ "zbliżają się" do 1 marca w latach przestępnych. – antihero
@brianary: nie będzie "w pełni dokładny", np. [Różnica wprowadzona przez lokalną strefę czasową ('datetime.now()') jest większa niż różnica między * średnią * Julian ('365.25') a gregoriańskim ('365.2425') years.] (Http://stackoverflow.com/a/32658742/4279). Prawidłowe podejście jest zasugerowane w odpowiedzi [@Adam Rosenfield] (http://stackoverflow.com/a/765862/4279) – jfs
Jak dokładnie powinno to być? td.days/365.25
będzie Ci bardzo bliski, jeśli martwisz się o lata przestępne.
Po pierwsze, na najbardziej szczegółowym poziomie problemu nie da się dokładnie rozwiązać. Lata różnią się długością i nie ma wyraźnego "właściwego wyboru" na rok.
Powiedziawszy to, dostań różnicę w jednostkach, które są "naturalne" (prawdopodobnie sekundy) i podziel przez stosunek między tym a latami. Na przykład.
delta_in_days/(365.25)
delta_in_seconds/(365.25*24*60*60)
... lub cokolwiek innego. Trzymaj się z dala od miesięcy, ponieważ są one jeszcze mniej zdefiniowane niż lata.
NIE JEST to, co ktokolwiek oznacza lub używa, gdy jest to kwestia tego, ile lat usługi lub osoba osiągnęła określony wiek. –
Twój 365.25 powinien być 365.2425, aby wziąć pod uwagę 400-letni wyjątek od kalendarza gregoriańskiego. – brianary
No cóż, problem * można * rozwiązać poprawnie - z wyprzedzeniem można przewidzieć, które lata mają dni przestępne i sekundy przestępne i tak dalej. Chodzi o to, że nie ma wyjątkowo eleganckiego sposobu robienia tego bez odejmowania lat, potem miesięcy, dni, itd ... w dwóch sformatowanych datach: – Litherum
Jeśli próbujesz sprawdzić, czy ktoś ma 18 lat, użycie timedelta
nie będzie działać poprawnie w niektórych przypadkach z powodu lata przestępnej. Na przykład ktoś urodzony 1 stycznia 2000 roku skończy 18 lat dokładnie 6575 dni później 1 stycznia 2018 roku (w tym 5 lat przestępnych), ale osoba urodzona 1 stycznia 2001 roku skończy 18 lat dokładnie 6574 dni później, 1 stycznia, 2019 (w tym 4 lata przestępne). Tak więc, jeśli ktoś ma dokładnie 6574 dni, nie można ustalić, czy ma on 17 lub 18 lat, nie znając nieco więcej informacji na temat ich daty urodzenia.
Prawidłowym sposobem jest obliczenie wieku bezpośrednio z dat, odjęcie dwóch lat, a następnie odjęcie jednego, jeśli bieżący miesiąc/dzień poprzedza miesiąc/dzień urodzenia.
: [Wiek od daty urodzenia w pytonie] (http: // stackoverflow. com/a/9754466/4279) – jfs
Chociaż ten wątek jest już martwy, mogę zaproponować rozwiązanie robocze dla tego samego problemu, z jakim miałem do czynienia.Oto ona (data jest ciągiem w formacie dd-mm-rrrr):
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
ta funkcja zwraca różnicę w latach między dwiema datami (rozumiana jako ciągi znaków w formacie ISO, ale można go łatwo modyfikowane w celu podjęcia w dowolnym formacie)
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
Cóż, pytanie wydaje się dość łatwe. Musisz sprawdzić liczbę pełnych lat i tylko jeśli jest równa 18, musisz zawracać sobie głowę miesiącami i dniami. Sprawa krawędź jest: endDate.year - startDate.year == 18
i dzieli na dwa przypadki: startDate.month != endDate.month
i startDate.month == endDate.month
, kiedy po prostu trzeba sprawdzić dzień:
def isOfAge(birthDate, age=18):
endDate = date.today()
years = endDate.year - birthDate.year
if years == age:
return (birthDate.month < endDate.month or
(birthDate.month == endDate.month and birthDate.day < endDate.day))
return years > age
To wciąż więcej niż jeden-liner-lambda, ale nadal jest dość krótki, a wydaje szybkie wykonanie.
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
Osoba urodzona 29 lutego będzie traktowana jak osoba, która osiągnęła wiek 1 następnego dnia 28 lutego. –
Ok. Skorygowano, aby pomieścić 0,08% populacji urodzonej 29-tego dnia, odwracając test z "jest urodziny po dniu dzisiejszym", "to urodziny przed dniem dzisiejszym". Czy to rozwiązuje? –
Nie, to nie rozwiąże problemu. Nie wierzysz w testowanie? –
będę sugerować Pyfdate
Co jest pyfdate?
Biorąc pod uwagę cel Pythona być potężnym i łatwym w użyciu skryptów język, jego funkcje do pracy z datami i czasem nie są tak łatwy w obsłudze, jak powinno być. Celem usługi pyfdate jest naprawienie tej sytuacji za pomocą funkcji przy użyciu dat i czasów, które są , tak potężne i łatwe w użyciu, jak reszta Pythona w wersji .
Kolejny 3-ga lib strona nie wspomniano tutaj jest mxDateTime (poprzednik zarówno python datetime
i 3rd party timeutil
) mogą być wykorzystane do tego zadania.
wyżej wymienionych yearsago
to: Oczekuje
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)
Pierwszy parametr, który jest wystąpienie DateTime
.
Aby przekształcić zwykły datetime
do DateTime
można to wykorzystać do 1 sekundy precyzji):
def DT_from_dt_s(t):
return DT.DateTimeFromTicks(time.mktime(t.timetuple()))
czy to dla precyzji 1 mikrosekund:
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)
I tak, dodając zależność na ten pojedynczy Zadanie to z pewnością byłoby przesadą w porównaniu nawet z użyciem timeutil (sugeruje Rick Copeland).
Zdobądź liczbę dni, a następnie podziel przez 365.2425 (średni rok gregoriański) na lata. Podziel przez 30,436875 (średni miesiąc gregoriański) na miesiące.
W końcu to, co masz, jest problemem matematycznym. Jeśli co 4 lata mamy dodatkowy dzień, to potem zanurkujemy w timedelta w dniach, a nie w 365, ale 365 * 4 + 1, co dałoby ci 4 lata. Następnie podziel go ponownie przez 4. timedelta/((365 * 4) +1)/4 = timedelta * 4/(365 * 4 +1)
Rzecz o rok przestępny nie ma zastosowania, gdy lata są podzielne przez 100, chyba że są podzielne przez 400. Więc, dla roku 2000: - jest podzielny przez cztery, więc powinien być skok, ale ... - jest również podzielny przez sto, więc nie powinien być skokiem, ale ... - jest podzielny przez 400, więc był to rok przestępny. Dla 1900: - jest podzielny przez 4, więc należy przeskoczyć. - jest podzielny przez 100, więc nie powinien być skok. - NIE jest podzielna przez 400, więc ta reguła nie ma zastosowania. 1900 nie był rokiem przestępnym. – Jblasco
To rozwiązanie wypracowałem, mam nadzieję, że może pomóc ;-)
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
Oto zaktualizowana funkcja DOB, który oblicza Urodziny ten sam sposób ludzie zrobić:
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)))
To zrywa, gdy dob jest 29 lutego, a bieżący rok nie jest rokiem przestępnym. –
- 1. Python timedelta usuń mikrosekundy
- 2. Pandy Timedelta w miesiącach
- 3. Panda Timedelta w dniach
- 4. Timedelta nie jest zdefiniowana
- 5. Python: Konwertuj timedelta na int w ramce danych
- 6. R uzyskać różnicę dat w latach (zmiennoprzecinkowa)
- 7. Różnica daty (w latach) wł. roku frakcja
- 8. datetime i timedelta
- 9. Jak sformatować timedelta do wyświetlenia?
- 10. błąd numed i pandy timedelta
- 11. Wyświetlanie obiektu timedelta w szablonie django
- 12. Jak umieścić timedelta w modelu django?
- 13. Timedelta mnożyć z pływakiem w pytonie
- 14. Jak ocenić różnicę dat w latach, miesiącach i dniach (ruby)?
- 15. Oblicz dokładną różnicę dat w latach przy użyciu SQL
- 16. inteligentne etykiety osi matplotlib dla timedelta
- 17. split-apply-Combine na pandach timedelta column
- 18. Jak skonstruować obiekt timedelta z prostego łańcucha
- 19. Konwertuj pandas freq string na timedelta
- 20. Znaleźć średnią i odchylenie standardowe obiektu timedelta w pandach df
- 21. Jak mogę wykonać divison na datetime.timedelta w python?
- 22. Tekst przycisku widgetu Android 5.0 (Lollipop) znajduje się w CAŁKOWITYCH LATACH
- 23. Chcę wypełnić pięć lat w menu rozwijanym przy użyciu javascript, a lata będą po bieżących latach
- 24. Generator pasma czasu w języku Python w dniach roboczych
- 25. Python datetime to microtime
- 26. Integer różnica w python między dwiema datami
- 27. Python: jak zapamiętujesz kolejność argumentów "super"?
- 28. Python: sprawdzania poprawności danych wejściowych Czas
- 29. Pandy - Python, usuwanie wierszy na podstawie kolumny Data
- 30. python: w ""?
zobaczyć tę odpowiedź: http://stackoverflow.com/a/9754466/65387 – Adam
related: [Jak przekonwertować lat do sekundy ] (http://stackoverflow.com/a/32658742/4279) – jfs