I have been playing a bit to try to understand pandas timestamps and timedeltas. I like how you can operate with them, but when trying subtraction I found this a bit odd:
now = pd.Timestamp('now')
then = now - pd.to_timedelta('1h')
print (now - then)
print (then - now)
print ((now - then).seconds)
print ((then - now).seconds)
Results in:
0 days 01:00:00
-1 days +23:00:00
3600
82800
a) How should I understand this behavior?
b) Is there a way to have an absolute value of the difference of timestamps, the equivalent to abs()?
The reason for this seemingly strange/buggy behaviour is that the .seconds attribute of a timedelta (for pandas.Timedelta, but this is inherited from standard library's timedelta.timedelta) is very ambigous.
The timedelta is stored in 3 parts: days, seconds, microseconds (https://docs.python.org/2/library/datetime.html#timedelta-objects). So the seconds is the sum of hours, minutes and seconds (in seconds).
So there are 2 'strange' things that can lead to confusion:
When having a negative timedelta, you get -1 days +23:00:00 instead of -01:00:00. This is because only the days part can be negative. So a negative timedelta will always be defined as a negative number of days with adding hours or seconds again to get the correct value. So this gives you the +23h part.
The seconds is the sum of hours, minutes and seconds. So the +23:00:00 we get is equal to 82800 seconds.
Bottomline is, the .seconds attribute of a timedelta does not give you the seconds part neither the total seconds (timedelta converted to seconds). So in practice, I think you should almost never use it.
To obtain the timedelta in seconds, you can use the total_seconds method. If I define the negative difference to diff = then - now:
In [12]: diff
Out[12]: Timedelta('-1 days +23:00:00')
In [13]: diff.seconds
Out[13]: 82800
In [14]: diff.total_seconds()
Out[14]: -3600.0
Related
In my small script I wanted to give script task time. In small time like under 1 min, I give min as -999999999.
But there is no problem in others. Seconds and microseconds can be got and they are int type, though min <class 'datetime.timedelta'>
My related code bunch is:
from datetime import datetime,timedelta
now = datetime.now()
# some code here
then = datetime.now()
delta= then-now
print(delta.seconds) # 10
print(delta.microseconds) # 432214
print(delta.min) # '-999999999 days, 0:00:00'
In the console I give:
datetime.timedelta(days=-999999999)
Where am I doing wrong?
Only days, seconds and microseconds are stored internally in a timedelta objects
The min attribute that you are accessing does not represent minutes and is actually the most negative timedelta object, timedelta(-999999999)
You can get the value of minutes using the total_seconds method from the timedelta object:
minutes = delta.total_seconds() / 60
Read documentation about min attribute here
timedelta.min doesn't give you minutes, but according to the documentation the smallest possible delta value.
timedelta.min
The most negative timedelta object, timedelta(-999999999).
I have timestamps that are calculated by a given interval. Ex: timestamp being 193894 and interval being 20000. The time is calculated by doing 193894/20000 = 9.6947. 9.6947 being 9 minutes and 0.6947 of a minute in seconds (0.6947 * 60) = 42 s (rounded up) thus the human readable timestamp being 9 min 42 sec.
Is there a Pythonic (assuming there is some library) way of doing this rather than doing a silly math calculation like this for every timestamp?
The reason being is because if timestamp is 1392338 (1 hour 9 min 37 sec) something that yields in the hours range, I want to be able to keep it dynamic.
I am just wondering if there was a better way to do this than the mathematical calculation way.
The linked question can help you actually format timedelta object once you have it, but there are a few tweaks you need to make to get the exact behavior you want
from __future__ import division
from datetime import timedelta
from math import ceil
def get_interval(timestamp, interval):
# Create our timedelta object
td = timedelta(minutes=timestamp/interval)
s = td.total_seconds()
# This point forward is based on http://stackoverflow.com/a/539360/2073595
hours, remainder = divmod(s, 3600)
minutes = remainder // 60
# Use round instead of divmod so that we'll round up when appropriate.
# To always round up, use math.ceil instead of round.
seconds = round(remainder - (minutes * 60))
return "%d hours %d min %d sec" % (hours, minutes, seconds)
if __name__ == "__main__:
print print_interval(1392338, 20000)
print get_interval(193894, 20000)
Output:
1 hours 9 min 37 sec
0 hours 9 min 42 sec
I have a function that accepts a date and returns the difference in time between then and the current time (in seconds). It works fine for everything less than a day. But when I even enter a date that's a year in the future, it still returns a number around 84,000 seconds (there are around 86,400 seconds in a day).
def calc_time(date):
future_date = str(date)
t_now = str(datetime.utcnow())
t1 = datetime.strptime(t_now, "%Y-%m-%d %H:%M:%S.%f")
t2 = datetime.strptime(future_date, "%Y-%m-%d %H:%M:%S.%f")
return ((t2-t1).seconds)
Even when I run it with a parameter whose date is in 2014, i get a number way too low.
Anyone have any insight?
Reading the datetime.timedelta docs.
All arguments are optional and default to 0. Arguments may be ints,
longs, or floats, and may be positive or negative.
Only days, seconds and microseconds are stored internally. Arguments
are converted to those units:
A millisecond is converted to 1000 microseconds. A minute is converted
to 60 seconds. An hour is converted to 3600 seconds. A week is
converted to 7 days. and days, seconds and microseconds are then
normalized so that the representation is unique, with
0 <= microseconds < 1000000 0 <= seconds < 3600*24 (the number of
seconds in one day)
-999999999 <= days <= 999999999
The solution is to use .total_seconds() instead of .seconds
The following code will return you the number of days between the two given dates
$daysremaining = ceil(abs(strtotime($yourdate) - strtotime($currentdate)) / 86400);
and to get the difference in seconds use
$secondsremaining = strtotime($yourdate) - strtotime($currentdate);
upvote if useful
ahh. apparently .seconds will only return the difference of seconds within the range of a day.
.seconds will include both hours and minutes, so i needed to add that to .days*86400 to get total seconds.
thanks for the help, everyone! ;D
I want to find time difference between two date and then compare the difference time in hours. Something like this,
StartTime = 2011-03-10 15:45:48
EndTime = 2011-03-10 18:04:00
And then find the difference as,
timeDifference = abs(StartTime - EndTime)
And then I need to compare the results as,
If timeDifference > 6 hours
...
When I use this method, the results I got was is in time format, how should I change time format into hours in python?
Thank you,
Let's assume that you have your two dates and times as datetime objects (see datetime.datetime):
>>> import datetime
>>> start_time = datetime.datetime(2011,3,10,15,45,48)
>>> end_time = datetime.datetime(2011,3,10,18,4,0)
Subtracting one datetime from another gives you a timedelta object, and you can use abs to ensure the time difference is positive:
>>> start_time - end_time
datetime.timedelta(-1, 78108)
>>> abs(start_time - end_time)
datetime.timedelta(0, 8292)
Now, to convert the seconds difference from a timedelta into hours, just divide by 3600:
>>> hours_difference = abs(start_time - end_time).total_seconds() / 3600.0
>>> hours_difference
2.3033333333333332
Note that the total_seconds() method was introduced in Python 2.7, so if you want that on an earlier version, you'll need to calculate it yourself from .days and .seconds as in this answer
Update: Jochen Ritzel points out in a comment below that if it's just the comparison with a number of hours that you're interested in, rather that the raw value, you can do that more easily with:
abs(start_time - end_time) > timedelta(hours=6)
What I am trying to do is to subtract 7 hours from a date. I searched stack overflow and found the answer on how to do it here. I then went to go read the documentation on timedelta because I was unable to understand what that line in the accepted answer does, rewritten here for ease:
from datetime import datetime
dt = datetime.strptime( date, '%Y-%m-%d %H:%M' )
dt_plus_25 = dt + datetime.timedelta( 0, 2*60*60 + 30*60 )
Unfortunately, even after reading the documentation I still do not understand how that line works.
What is the timedelta line doing? How does it work?
Additionally, before I found this stackoverflow post, I was working with time.struct_time tuples. I had a variable tm:
tm = time.strptime(...)
I was simply accessing the hour through tm.tm_hour and subtracting seven from it but this, for obvious reasons, does not work. This is why I am now trying to use datetime. tm now has the value
tm = datetime.strptime(...)
I'm assuming using datetime is the best way to subtract seven hours?
Note: subtracting seven hours because I want to go from UTC to US/Pacific timezone. Is there a built-in way to do this?
What is the timedelta line doing? How does it work?
It creates a timedelta object.
There are two meanings of "time".
"Point in Time" (i.e, date or datetime)
"Duration" or interval or "time delta"
A time delta is an interval, a duration, a span of time. You provided 3 values.
0 days.
2*60*60 + 30*60 seconds.
timedelta() generates an object representing an amount of timeāthe Greek letter delta is used in math to represent "difference". So to compute an addition or a subtraction of an amount of time, you take the starting time and add the change, or delta, that you want.
The specific call you've quoted is for generating the timedelta for 2.5 hours. The first parameter is days, and the second is seconds, so you have (0 days, 2.5 hours), and 2.5 hours in seconds is (2 hours * 60 minutes/hour * 60 seconds/minute) + (30 minutes * 60 seconds / minute).
For your case, you have a negative time delta of 0 days, 7 hours, so you'd write:
timedelta(0, -7 * 60 * 60)
... or timedelta(0, -7 * 3600) or whatever makes it clear to you what you're doing.
Note: subtracting seven hours because I want to go from UTC to US/Pacific timezone. Is there a built-in way to do this?
Yes there is: datetime has built-in timezone conversion capabilities. If you get your datetime object using something like this:
tm = datetime.strptime(date_string, '%Y-%m-%d %H:%M')
it will not have any particular timezone "attached" to it at first, but you can give it a timezone using
tm_utc = tm.replace(tzinfo=pytz.UTC)
Then you can convert it to US/Pacific with
tm_pacific = tm_utc.astimezone(pytz.all_timezones('US/Pacific'))
I'd suggest doing this instead of subtracting seven hours manually because it makes it clear that you're keeping the actual time the same, just converting it to a different timezone, whereas if you manually subtracted seven hours, it looks more like you're actually trying to get a time seven hours in the past. Besides, the timezone conversion properly handles oddities like daylight savings time.
To do this you will need to install the pytz package, which is not included in the Python standard library.