python как преобразовать даты datetime в десятичные годы

Я ищу способ преобразования объектов datetime в десятичный год. Ниже приведен пример

>>> obj = SomeObjet()
>>> obj.DATE_OBS
datetime.datetime(2007, 4, 14, 11, 42, 50)

Как преобразовать datetime.датавремя(2007, 4, 14, 11, 42, 50) десятичная лет? От этого формата dd/mm / yyyy до такого формата yyyy.yyyy

6 ответов


from datetime import datetime as dt
import time

def toYearFraction(date):
    def sinceEpoch(date): # returns seconds since epoch
        return time.mktime(date.timetuple())
    s = sinceEpoch

    year = date.year
    startOfThisYear = dt(year=year, month=1, day=1)
    startOfNextYear = dt(year=year+1, month=1, day=1)

    yearElapsed = s(date) - s(startOfThisYear)
    yearDuration = s(startOfNextYear) - s(startOfThisYear)
    fraction = yearElapsed/yearDuration

    return date.year + fraction

демо:

>>> toYearFraction(dt.today())
2011.47447514

этот метод, вероятно, точен в течение секунды (или часа, если действует летнее время или другие странные региональные вещи). Он также работает правильно во время leapyears. Если вам нужно резкое разрешение (например, из-за изменений во вращении Земли), вам лучше запросить сетевую службу.


Я предполагаю, что вы используете это для сравнения значений datetime. Для этого, пожалуйста, используйте timedelta объекты вместо reiniventing колесо.

пример:

>>> from datetime import timedelta
>>> from datetime import datetime as dt
>>> d = dt.now()
>>> year = timedelta(days=365)
>>> tomorrow = d + timedelta(days=1)
>>> tomorrow + year > d + year
True

если по какой-то причине вы действительно нужно десятичное лет, datetime метод объекты strftime() может дать вам целое представление день на %j - если это то, что вы ищете, ниже простой пример (только на 1 день разрешение):

>>> from datetime import datetime
>>> d = datetime(2007, 4, 14, 11, 42, 50)
>>> (float(d.strftime("%j"))-1) / 366 + float(d.strftime("%Y"))
2007.2814207650274

после реализации принятого решения у меня было откровение, что эта современная версия панды идентична и намного проще:

dat['decimal_date']=dat.index.year+ (dat.index.dayofyear -1)/365

должен использоваться в фрейме данных индекса даты и времени Pandas. Добавление как это решение сообщение появляется в верхней части моего поиска google для этой проблемы.


Это немного проще, чем другие решения:

import datetime
def year_fraction(date):
    start = datetime.date(date.year, 1, 1).toordinal()
    year_length = datetime.date(date.year+1, 1, 1).toordinal() - start
    return date.year + float(date.toordinal() - start) / year_length

>>> print year_fraction(datetime.datetime.today())
2016.32513661

обратите внимание, что это вычисляет дробь на основе начала дня, поэтому 31 декабря будет 0.997, а не 1.0.


удивлен, никто не упомянул об этом... но ... --1--> объекты, которые являются результатом вычитания datetime.datetime объекты имеют метод разделения. Таким образом, вы можете использовать простую функцию

from datetime import datetime
def datetime2year(dt): 
    year_part = dt - datetime(year=dt.year, month=1, day=1)
    year_length = datetime(year=dt.year+1, month=1, day=1) - datetime(year=dt.year, month=1, day=1)
    return dt.year + year_part/year_length

где деление между datetime.timedelta объекты.


можно вычислить десятичную дату, используя юлианскую дату Панды и следующие формулы.

в случае, когда ваш фрейм данных pandas имеет индекс, который является датой-временем:

JD=dat.index.to_julian_date() #create julian date
L= JD+68569
N= 4*L/146097
L= L-(146097*N+3)/4
I= 4000*(L+1)/1461001
L= L-1461*I/4+31
J= 80*L/2447
K= L-2447*J/80
L= J/11
J= J+2-12*L
decimal_date= 100*(N-49)+I+L

decimal_date-это серия вашей даты (в том же TZ, что и индекс фрейма данных) в виде чего-то вроде 2007.123452.

взято из этого поста.