Мне нужно проверить, было ли какое-то количество лет с какой-то даты. В настоящее время у меня есть timedelta
от datetime
модуля, и я не знаю, как его преобразовать в годы.Python timedelta в годах
ответ
Вам нужно больше, чем timedelta
, чтобы рассказать, сколько лет прошло; вам также нужно знать дату начала (или окончания). (Это високосный год.)
Ваш лучший выбор - использовать dateutil.relativedelta
object, но это сторонний модуль. Если вы хотите знать, что 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
Вы можете быть полностью точным с 365.2425 (вместо 365.25), что учитывает исключение 400 лет для григорианского календаря. – brianary
Ваша функция легально ломается для таких стран, как Великобритания и Гонконг, потому что они «округляются» до 1 марта в високосные годы. – antihero
@brianary: он не будет «полностью точным», например [разница, введенная локальным часовым поясом ('datetime.now()') больше, чем разница между * average * Julian ('365.25') и григорианской ('365.2425') лет.] (Http://stackoverflow.com/a/32658742/4279). Правильный подход предлагается в ответе [@Adam Rosenfield] (http://stackoverflow.com/a/765862/4279) – jfs
Насколько он вам нужен? td.days/365.25
доставит вас довольно близко, если вы беспокоитесь о високосных годах.
Прежде всего, на самом детальном уровне проблема не может быть решена точно. Годы различаются по длине, и нет четкого «правильного выбора» на протяжении года.
Таким образом, получите разницу во всех единицах, которые являются «естественными» (вероятно, секундами) и делятся на соотношение между этим и годами. Например.
delta_in_days/(365.25)
delta_in_seconds/(365.25*24*60*60)
... или что-то еще. Держитесь подальше от месяцев, поскольку они еще менее четко определены, чем годы.
Это НЕ то, что кто-либо подразумевает или использует, когда речь идет о том, сколько лет службы или человек достиг определенного возраста. –
Ваш 365,25 должен составлять 365,2425, чтобы принять во внимание 400-летнее исключение григорианского календаря. – brianary
Ну, проблема * может * быть решена правильно - вы можете сказать заранее, какие годы имеют прыжки и прыжки секунд и все такое. Просто нет чрезвычайно элегантного способа сделать это, не вычитая годы, затем месяцы, дни и т. Д. В двух отформатированных датах: – Litherum
Если вы пытаетесь проверить, является ли кто-то 18 лет, использование timedelta
не будет корректно работать на некоторых случаях с краями из-за високосных годов. Например, кому-то, родившемуся 1 января 2000 года, исполнилось 18 ровно 6575 дней спустя 1 января 2018 года (включая 5 високосных лет), но кто-то, родившийся 1 января 2001 года, исполнится 18 ровно 6574 дня спустя 1 января 2000 года. 2019 (включая 4 високосных года). Таким образом, если вам ровно 6574 дня, вы не можете определить, являются ли они 17 или 18, не зная немного больше информации о своей дате рождения.
Правильный способ сделать это - рассчитать возраст непосредственно из дат, вычитая два года, а затем вычесть его, если текущий месяц/день предшествует месяцу/дню рождения.
: [Возраст от даты рождения в python] (http: // stackoverflow. com/a/9754466/4279) – jfs
Даже если этот поток уже мертв, могу я предложить рабочего решения для этой же проблемы, с которой я столкнулся.Здесь (дата является строкой в формате дд-мм-гггг):
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
Ну, вопрос кажется довольно простым. Вам нужно проверить количество «полных» лет, и только если он равен 18, вам нужно беспокоиться месяцами и днями. Случай край: endDate.year - startDate.year == 18
и она распадается на два случая: startDate.month != endDate.month
и startDate.month == endDate.month
, когда вы просто должны проверить дни:
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
Это все еще больше, чем один вкладыш лямбда, но это все еще довольно короткий, и, кажется, быстрый в исполнении.
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
Лицо, родившееся 29 февраля, будет считаться имеющим возраст 1 следующего 28 февраля. –
Хорошо. Исправлено для размещения 0,08% населения, родившегося 29-го, путем инвертирования теста с «день рождения после сегодняшнего дня» до «день рождения до сегодняшнего дня». Решает ли это? –
Нет, это не решает проблему. Вы не верите в тестирование? –
Я предлагаю Pyfdate
Что pyfdate?
Учитывая цели Python, чтобы быть мощной и простой в использовании сценариев языка, его особенности для работы с датами и временем, не так удобно, как они должны быть. Цель pyfdate заключается в том, чтобы исправить эту ситуацию , предоставляя функции для , работающих с датами и временем, которые являются столь же мощными и удобными, как и остальной частью Python.
Еще одна третья сторона Lib не упоминается здесь mxDateTime (предшественник как питон datetime
и 3-й партии 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)
И да, добавляя зависимость для этого сингла задача, о которой идет речь, определенно будет излишним сравнением даже с использованием timeutil (предложенный Риком Коуплэнд).
Получите количество дней, а затем разделите их на 365.2425 (средний григорианский год) в течение многих лет. Разделите на 30.436875 (средний григорианский месяц) месяцами.
В конце концов, у вас есть проблема с математикой. Если каждые 4 года у нас есть дополнительный день, мы можем погрузиться в timedelta за несколько дней, а не 365, а 365 * 4 + 1, что даст вам 4 года. Затем разделите его на 4. timedelta/((365 * 4) + 1)/4 = timedelta * 4/(365 * 4 +1)
Значение високосного года не применяется, если годы делятся на 100, за исключением случаев, когда они делятся на 400. Таким образом, на 2000 год: - он делится на четыре, поэтому он должен прыгать, но ... - он также делится на сто, поэтому он не должен прыгать, но ... - он делится на 400, так что это был действительно високосный год. За 1900: - он делится на 4, поэтому должен быть прыжок. - он делится на 100, поэтому он не должен прыгать. - он не делится на 400, поэтому это правило не применяется. 1900 год был не високосным. – Jblasco
Это решение, которое я разработал, я надеюсь, может помочь ;-)
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
Вот обновленная функция 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)))
Это ломается, когда dob - 29 февраля, а текущий год - не високосный год. –
- 1. Python 2.6.5: Divide timedelta с timedelta
- 2. Infinite Timedelta in Python
- 3. форматирование объектов python timedelta
- 4. python sort on timedelta
- 5. Python negative timedelta issue
- 6. Как рассчитать timedelta python
- 7. Python timedelta удалить микросекунды
- 8. python Timedelta overflow
- 9. Формат Python timedelta для строки
- 10. python convert str to timedelta
- 11. Python & Pandas: series to timedelta
- 12. Python: преобразовать timedelta в int в dataframe
- 13. Процент в объектах timedelta в Python?
- 14. Как форматировать продолжительность в Python (timedelta)?
- 15. Python timedelta и datetime.min в Руби
- 16. Удалить время из timedelta output в python
- 17. Как получить процент timedelta в python
- 18. Как получить сумму timedelta в Python?
- 19. Как преобразовать timedelta во времени в python?
- 20. Манипулирование объектами DateTime и TimeDelta в python
- 21. Как изменить timedelta на время в Python?
- 22. Понимание timedelta
- 23. Класс TimeDelta в ActionScript?
- 24. DateTimes разница в годах
- 25. Проверьте разницу в годах
- 26. Python Timedelta Arithmetic With noleap Календари
- 27. Python 3 - Работа с объектами datetime.time - timedelta
- 28. Что-то вроде python timedelta in golang
- 29. python TypeError добавляет время, используя timedelta
- 30. Использование пользовательского календаря python для вычислений timedelta
см этот ответ: http://stackoverflow.com/a/9754466/65387 – Adam
связанные: [Как конвертировать года до второй ] (http://stackoverflow.com/a/32658742/4279) – jfs