dateutil.relativedelta - How to get duration in days? - python

I wish to get the total duration of a relativedelta in terms of days.
Expected:
dateutil.timedelta(1 month, 24 days) -> dateutil.timedelta(55 days)
What I tried:
dateutil.timedelta(1 month, 24 days).days -> 24 (WRONG)
Is there a simple way to do this? Thanks!

This one bothered me as well. There isn't a very clean way to get the span of time in a particular unit. This is partly because of the date-range dependency on units.
relativedelta() takes an argument for months. But when you think about how long a month is, the answer is "it depends". With that said, it's technically impossible to convert a relativedelta() directly to days, without knowing which days the delta lands on.
Here is what I ended up doing.
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
rd = relativedelta(years=3, months=7, days=19)
# I use 'now', but you may want to adjust your start and end range to a specific set of dates.
now = datetime.now()
# calculate the date difference from the relativedelta span
then = now - rd
# unlike normal timedelta 'then' is returned as a datetime
# subtracting two dates will give you a timedelta which contains the value you're looking for
diff = now - then
print diff.days

Simple date diff does it actually.
>>> from datetime import datetime
>>> (datetime(2017, 12, 1) - datetime(2018, 1, 1)).days
-31
To get positive number You can swap dates or use abs:
>>> abs((datetime(2017, 12, 1) - datetime(2018, 1, 1)).days)
31

In many situations you have a much restricted relativedelta, in my case, my relativedelta had only relative fields set (years, months, weeks, and days) and no other field. You may be able to get away with the simple method.
This is definitely off by few days, but it may be all you need
(365 * duration.years) + (30 * duration.months) + (duration.days)

Related

How to Split a substract of a date in python

My code is the following:
date = datetime.datetime.now()- datetime.datetime.now()
print date
h, m , s = str(date).split(':')
When I print h the result is:
-1 day, 23
How do I get only the hour (the 23) from the substract using datetime?
Thanks.
If you subtract the current date from a past date, you would get a negative timedelta value.
You can get the seconds with td.seconds and corresponding hour value via just dividing by 3600.
from datetime import datetime
import time
date1 = datetime.now()
time.sleep(3)
date2 = datetime.now()
# timedelta object
td = date2 - date1
print(td.days, td.seconds // 3600, td.seconds)
# 0 0 3
You're not too far off but you should just ask your question as opposed to a question with a "real scenario" later as those are often two very different questions. That way you get an answer to your actual question.
All that said, rather than going through a lot of hoop-jumping with splitting the datetime object, assigning it to a variable which you then later use look for what you need in, it's better to just know what DateTime can do since that can be such a common part of your coding. You would also do well to look at timedelta (which is part of datetime) and if you use pandas, timestamp.
from datetime import datetime
date = datetime.now()
print(date)
print(date.hour)
I can get you the hour of datetime.datetime.now()
You could try indexing a list of a string of datetime.datetime.now():
print(list(str(datetime.datetime.now()))[11] + list(str(datetime.datetime.now()))[12])
Output (in my case when tested):
09
Hope I am of help!

Python : Is there a way to get the names of last three Month Names?

How can I extract last three month names in Python? If I am running this today then I would like to see May, June and July as my result.
Easier way is to use "%B" using datetime and timedelta
from dateutil.relativedelta import relativedelta
from datetime import datetime
today = datetime.now()
for i in range(1,4):
print((today - relativedelta(months=i)).strftime('%B'))
Output:
July
June
May
One way is to use the python calendar module, and list slice a month name for a given, extracted datetime month.
.month_name returns a list of all the month names.
calendar is part of the standard library.
For timedelta, there isn't a month parameter because the length of a month is not a constant value, so use days, as an approximation.
See datetime for the available methods.
datetime is part of the python standard library, so doesn't require a separate installation.
Use .month to extract the month from the datetime.
from datetime import datetime, timedelta
import calendar
# get the time now
now = datetime.now()
# iterate through 3 different timedeltas as an example
for x in range(1, 4):
new = now - timedelta(days=31*x)
print(calendar.month_name[new.month])
[out]:
July
June
May
As mentioned in the answer by bigbounty, using .strftime with '%B' is a better option than using calendar
However, unlike the dateutil module, timedelta still doesn't have a month parameter.
The dateutil module provides powerful extensions to the standard datetime module and must be installed, and then imported.
# get the time now
now = datetime.now()
# iterate through 3 different timedeltas as an example
for x in range(1, 4):
new = now - timedelta(days=31*x)
print(new.strftime('%B'))
[out]:
July
June
May
Best way to do this is a combination of the date and calendar modules.
date.today().month will give you a numerical value for the current month (1-12)
calendar.month_name[x] will give you the name for the month represented by the number x
the % operator will be used to wrap around the index of the month_name object to avoid the pesky 0 index returning ''
Putting them together we have:
from datetime import date
from calendar import month_name
def previous_n_months(n):
current_month_idx = date.today().month - 1 # Value is now (0-11)
for i in range(1, n+1):
# The mod operator will wrap the negative index back to the positive one
previous_month_idx = (current_month_idx - i) % 12 #(0-11 scale)
m = int(previous_month_idx + 1)
print(month_name[m])
Example usage:
>>> previous_n_months(3)
July
June
May

Convert hours from January 1st midnight to actual date

I'm working with some telemetry that uses timestamps measured in hours since January 1st at midnight of the current year.
So I get value 1 at time 8668.12034
I'd like to convert it to a more useful date format and of course I've been doing so with hardcoded math dividing into days, remainder hours, minutes, etc accounting for leap years... and it works but I'm sure there's a simple way using the datetime library or something right?
I'm thinking timedelta is the way to go since it's giving me a delta since the beginning of the year but does that account for leap years?
Curious how others would approach this issue, thanks for any advice.
# import packages we need
import datetime
From elapsed hours to datetime.datetime object
You can for example do:
hours_elapsed = 1000
your_date = datetime.datetime(2020,1,1,0,0)+datetime.timedelta(hours=hours_elapsed)
(Of course change hours_elapsed to whatever hours elapsed in your case.)
your_date will be: datetime.datetime(2020, 2, 11, 16, 0)
Yes, timedelta does know about leap years.
Further processing
If want to process this further, can do, using getattr():
timeunits = ['year', 'month', 'day', 'hour', 'minute', 'second']
[getattr(your_date,timeunit) for timeunit in timeunits]
Resulting in:
[2020, 2, 11, 16, 0, 0]

How to use 24 hour time series data as a predictive feature

I am just wondering how best to approach using this 24 hour time format as a predictive feature. My thoughts were to bin it into 24 categories for each hour of the day. Is there an easy way to convert this object into a python datetime object that would make binning easier or how would you advise handling this feature? Thanks :)
df['Duration']
0 2:50
1 7:25
2 19:00
3 5:25
4 4:45
5 2:25
df['Duration'].dtype
dtype('O')
The best solution will depend on what you hope to get from your model. In many cases it makes sense to convert it to total number of seconds (or minutes or hours) since some epoch. To convert your data to seconds since 00:00, you can use:
from datetime import datetime
t_str = "2:50"
t_delta = datetime.strptime(t_str, "%H:%M") - datetime(1900, 1, 1)
seconds = t_delta.total_seconds()
hours = seconds/60**2
print(seconds)
# 10200.0
Using Python's datetime class will not support time values over 23:59. Since it appears that your data may actually be a duration, you may want to represent it as an instance of Python's timedelta class.
from datetime import timedelta
h, m = map(int, t_str.split(sep=':'))
t_delta = timedelta(hours=h, minutes=m)
# Get total number of seconds
seconds = t_delta.total_seconds()
You can use datetime to create a useable datetime string
>>> from datetime import datetime
>>> x = datetime(2019, 1, 1, 0).strftime('%Y-%m-%d %H:%M:%S')
>>> # Use that for your timestring then you can reverse it nicely back into a datetime object
>>> d = datetime.strptime('2019-01-01 00:00:00', '%Y-%m-%d %H:%M:%S')
Of course you can use any valid format string.
You should calculate the time in seconds or minutes or hours from some initial time like the 1st time. Then you can make an x-y scatter plot of the data since the x-axis (time) is now numbers.

Subtract a year from given date (not current time) in python

I have a file in which date field in YYYYMMDD format. I need to pick that date and product to join with another file by subtracting 12 months to get other information.
File1
20180131,Apple
20180228,Orange
20180331,Grapes
File2
20170131,Apple,45
20170131,Orange,20
20170228,Orange,35
20170331,Apple,25
Output
20180131,Apple,45
20180228,Orange,35
20180331,Grapes,null
How to subtract 12 months or 1 year from given date(yyyymmdd) and get the answer in the same format.
You can use strptime from the standard library to parse the date, but unfortunately there is no calendar support in the standard library so you have to use the dateutil library to subtract the year.
import datetime
from dateutil.relativedelta import relativedelta
d = datetime.datetime.strptime('20180131', '%Y%m%d').date()
print((d - relativedelta(years=1)).strftime('%Y%m%d'))
This will print 20170131.
Note that if the input is e.g. 20160229, this will print out 20150228. I'm not sure exactly what the semantics of relativedelta are so be sure to read the docs if this is important to you.
Why not timedelta?
The datetime.timedelta is not appropriate and does not work correctly. A timedelta represents a duration in time, or it represents a number of days, but counter-intuitively, a year is not a duration but instead a calendrical concept. A year is either 365 or 366 days, depending on which year.
It becomes pretty obvious that timedelta will not work once you find the correct test cases:
In [1]: from datetime import date, timedelta
In [2]: date(2018, 1, 1) - timedelta(365)
Out[2]: datetime.date(2017, 1, 1)
In [3]: date(2017, 1, 1) - timedelta(365)
Out[3]: datetime.date(2016, 1, 2)

Categories

Resources