I am looking for a way to convert datetime objects to decimal(/float) year, including fractional part. Example:
>>> obj = SomeObjet()
>>> o
After implementing the accepted solution, I had the revelation that this modern pandas version is identical, and much simpler:
dat['decimal_date']=dat.index.year+ (dat.index.dayofyear -1)/365
Must be used on a date-time index Pandas dataframe. Adding as this solution post comes up in the top of my google search for this issue.
If you want to include the minutes and seconds use this:
YearF=[(x.timetuple().tm_yday-1+x.timetuple().tm_hour/24+x.timetuple().tm_min/(60*24)+x.timetuple().tm_sec/(24*3600))/(365+((x.timetuple().tm_year//4)==(x.timetuple().tm_year/4)))+x.timetuple().tm_year for x in DateArray]
I'm assuming that you are using this to compare datetime values. To do that, please use the the timedelta objects instead of reiniventing the wheel.
Example:
>>> 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
If for some reason you truly need decimal years, datetime
objects method strftime()
can give you an integer representation of day of the year if asked for %j
- if this is what you are looking for, see below for a simple sample (only on 1 day resolution):
>>> from datetime import datetime
>>> d = datetime(2007, 4, 14, 11, 42, 50)
>>> (float(d.strftime("%j"))-1) / 366 + float(d.strftime("%Y"))
2007.2814207650274
This is a little simpler way than the other solutions:
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
Note that this calculates the fraction based on the start of the day, so December 31 will be 0.997, not 1.0.
Surprised no one has mentioned this... but the datetime.timedelta
objects that result from subtracting datetime.datetime
objects have a division method. So, you could use the simple function
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
where the division is between datetime.timedelta
objects.
It's possible to calculate decimal date by using Pandas's julian date and the following formulas.
In the case where your pandas dataframe has an index that is date-time:
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 is a series of your date (in the same TZ as the dataframe index) in form of something like 2007.123452.
Adapted from this post.