create - Python timedelta en años
string to datetime python (14)
Necesito comprobar si han pasado algunos años desde alguna fecha. Actualmente tengo timedelta
del módulo de datetime
y datetime
y no sé cómo convertirlo a años.
¿Qué tan exacto lo necesitas para ser? td.days / 365.25
te td.days / 365.25
bastante, si te preocupan los años bisiestos.
Al final, lo que tienes es un problema matemático. Si cada 4 años tenemos un día extra, luego buceamos en timedelta en días, no en 365 sino en 365 * 4 + 1, lo que le daría la cantidad de 4 años. Luego divídalo nuevamente por 4. timedelta / ((365 * 4) +1) / 4 = timedelta * 4 / (365 * 4 +1)
Aquí hay una función DOB actualizada, que calcula los cumpleaños de la misma manera que los humanos:
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)))
Aunque este hilo ya está muerto, ¿podría sugerir una solución de trabajo para este mismo problema al que me enfrentaba? Aquí está (la fecha es una cadena en el formato dd-mm-aaaa):
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
Bueno, la pregunta parece bastante fácil. Necesita verificar el número de años "completos" y solo si es igual a 18 necesita molestarse con meses y días. El caso límite es: endDate.year - startDate.year == 18
y se divide en dos casos: startDate.month != endDate.month
y startDate.month == endDate.month
, cuando solo tiene que verificar los días:
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
Todavía es más que un liner-lambda, pero aún es bastante corto y parece rápido en su ejecución.
En primer lugar, al nivel más detallado, el problema no se puede resolver exactamente. Los años varían en duración, y no hay una clara "elección correcta" para la duración del año.
Dicho esto, obtenga la diferencia en las unidades que sean "naturales" (probablemente segundos) y divida por la relación entre eso y años. P.ej
delta_in_days / (365.25)
delta_in_seconds / (365.25*24*60*60)
...o lo que sea. Mantente alejado de los meses, ya que están menos definidos que años.
Esta es la solución que resolví, espero que pueda ayudar ;-)
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
Necesita más que un timedelta
para contar cuántos años han pasado; también necesita saber la fecha de inicio (o finalización). (Es algo del año bisiesto).
Su mejor dateutil.relativedelta
es usar el object dateutil.relativedelta
, pero es un módulo de terceros. Si desea saber la datetime
que fue n
años a partir de una fecha (por defecto en este momento), puede hacer lo siguiente ::
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)
Si prefieres quedarte con la biblioteca estándar, la respuesta es un poco más compleja:
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)
Si es 2/29, y hace 18 años no hubo 2/29, esta función devolverá 2/28. Si prefiere devolver 3/1, simplemente cambie la última declaración de return
para leer ::
return from_date.replace(month=3, day=1,
year=from_date.year-years)
Su pregunta originalmente decía que quería saber cuántos años han pasado desde alguna fecha. Suponiendo que desea un número entero de años, puede adivinar en base a 365.25 días por año y luego verificar usando cualquiera de las funciones del año anterior definidas anteriormente ::
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
Obtenga el número de días, luego divida por 365.2425 (el año gregoriano medio) durante años. Divida por 30.436875 (el mes gregoriano medio) durante meses.
Si está tratando de verificar si alguien tiene 18 años de edad, usar timedelta
no funcionará correctamente en algunos casos timedelta
debido a los años bisiestos. Por ejemplo, una persona nacida el 1 de enero de 2000 cumplirá 18 años exactamente 6575 días después el 1 de enero de 2018 (5 años bisiestos incluidos), pero una persona nacida el 1 de enero de 2001 cumplirá 18 años exactamente 6574 días después el 1 de enero. 2019 (4 años bisiestos incluidos). Por lo tanto, si alguien tiene exactamente 6574 días, no puede determinar si tiene 17 o 18 años sin conocer un poco más de su fecha de nacimiento.
La forma correcta de hacerlo es calcular la edad directamente a partir de las fechas, restando los dos años, y luego restar uno si el mes / día actual precede al mes / día de nacimiento.
Sin embargo, otra lib de terceros no mencionada aquí es mxDateTime (predecesora de pytime datetime
y 3rd party timeutil
) podría utilizarse para esta tarea.
El año anterior sería:
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)
Se espera que el primer parámetro sea una instancia de DateTime
.
Para convertir datetime
ordinario en DateTime
, puede usar esto para una precisión de 1 segundo):
def DT_from_dt_s(t):
return DT.DateTimeFromTicks(time.mktime(t.timetuple()))
o esto para una precisión de 1 microsegundo:
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)
Y sí, agregar la dependencia de esta única tarea en cuestión definitivamente sería una exageración en comparación incluso con el uso de timeutil (sugerido por Rick Copeland).
esta función devuelve la diferencia en años entre dos fechas (tomada como cadenas en formato ISO, pero puede modificarse fácilmente para tomar cualquier formato)
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
¿Qué es pyfdate?
Dado el objetivo de Python de ser un lenguaje de scripting poderoso y fácil de usar, sus características para trabajar con fechas y horas no son tan fáciles de usar como deberían. El objetivo de pyfdate es remediar esa situación proporcionando funciones para trabajar con fechas y horas que sean tan potentes y fáciles de usar como el resto de Python.
el tutorial
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