Manipulation with datetime in python - python

I am developing an application in python where I need to calculate time elapsed and take appropriate action.
I have two times as by default provided and current. I want compare the difference with some other time which is provided in string format.
I have tried following:
d1 = datetime.datetime(2015, 1, 21, 9, 54, 54, 340000)
print d1
d2 = datetime.datetime.now()
print d2
print d2 - d1
d3 =datetime.datetime.strptime("22:17:46.476000","%H:%M:%S.%f")
print d3
Output of the above program is :
2015-01-21 09:54:54.340000
2015-01-21 22:28:45.070000
12:33:50.730000
1900-01-01 22:17:46.476000
Here time difference is' 12:33:50.730000' and I want to compare it with '22:17:46.476000' which is string.
As I tried to convert string '22:17:46.476000' to time I got year as 1990. I want only time as '22:17:46.476000'. So I can compare these two time using timedelta.
How to get rid of year 1990-01-01. I want only '22:17:46.476000'.
I tried using time as time.strptime("22:17:46.476000","%H:%M:%S.%f") but it give output as time.struct_time(tm_year=1900, tm_mon=1, tm_mday=1, tm_hour=22, tm_min=17, tm_sec=46, tm_wday=0, tm_yday=1, tm_isdst=-1)
Thanks

As it stands, you are comparing two fundamentally different grandeurs.
When you subtract one Datetime object from another you get a "timedelta" object - that is a period of time, which can be expressed in days, hours, seconds, or whatever time unit.
Datetime objects on the other hand mark an specific point in time. When you parse the time-only string to a Datetime, since no year, month or day is specified, they get the default values of 1900-01-01.
So, since the value you want to compare the interval with is a time interval, not an specific point in time, that is what you should have on the other hand of the comparison.
The easiest way to do that from where you are is indeed to subtract, from your parsed object, the midnight of 1900-01-01 - and then you have a "timedelta" object, with just that duration. However, note that this is a hack, and as soon as the time interval you need to parse against is larger than 24h it will break (strptime certainly won't parse "30:15:..." as the 6th hour of 1901-01-02)
So, you'd better break apart and build a timedelta object from scratch for your string:
hour, min, sec = "22:17:46.476000".split(":")
d3 = datetime.timedelta(hours=int(hour), minutes=int(minutes), seconds=float(sec))

Given a datetime d3, you could obtain the time (without the date) using the time method:
>>> d3.time()
datetime.time(22, 17, 46, 476000)
You could then compare this time with d2.time():
>>> d2.time() > d3.time()
False
Alternatively, you could use combine to build a datetime out of d2's date and d3's time:
import datetime as DT
d1 = DT.datetime(2015, 1, 21, 9, 54, 54, 340000)
d2 = DT.datetime.now()
d3 = DT.datetime.strptime("22:17:46.476000","%H:%M:%S.%f")
d3 = DT.datetime.combine(d2.date(), d3.time())
print(d3)
# 2015-01-21 22:17:46.476000
You can then compare the two datetimes: d2 and d3. For example:
>>> d2 < d3
True
>>> (d3-d2).total_seconds()
36664.503375

The difference between two datetimes is a duration represented as a datetime.timedelta and not a datetime, so you can't format it using strftime.
Instead of using strptime to parse your value for d3, you should construct a datetime.timedelta directly. See the documentation for its constructor.
If you really need to parse d3 from a string, then you can either do the parsing yourself or use the python-dateutil package.

If I understand you correctly, 22:17:46.476000 doesn't represent a time but a time delta (because you want to compare it to another time delta).
If so, what you really need is to construct a datetime.timedelta object from your string. Unfortunately, it looks like there is no built-in way to do it, however, here you may find some recipes.

Related

Python: date time difference giving incorrect result

I have written a simple code to check if the time difference between 2 date timestamps is more than 7 days, which comes to 604,800 seconds.
If the time in seconds is more than 604,800 then it should print "Relax you have time!!!"
Please find my code below:
import time, datetime, sys, os
start_time = time.time()
from datetime import datetime, timedelta, date
from dateutil.parser import *
datetime1="2018-07-13 03:30:00"
datetime2="2018-07-20 04:30:00"
datetime2=datetime.strptime(datetime2, "%Y-%m-%d %H:%M:%S").date() # this is to convert it into a datetime object
datetime1=datetime.strptime(datetime1, "%Y-%m-%d %H:%M:%S").date() # this is to convert it into a datetime object
difference1 =(datetime2-datetime1).total_seconds()
print("the difference in seconds is "+str(difference1))
if difference1 > 604800: #if the difference is more than 7 days, relax , else start preparing
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")
Problem:
The code somehow calculates the time in seconds to be more than 604800 only if I change the "datetime2" to "2018-07-21" which means that it is calculating the difference in rounded-off days and not seconds and then simply converting the rounded-off days into seconds, giving the incorrect answer.
For example, in the above code, since "datetime2" is in reality away from "datetime1" by more than 604,800 seconds(to be precise it is 608,400 seconds away), the output should be "Relax you have time!!!", but we get a different output.
What have I done to solve this?
Till now I have looked at similar questions:
How do I check the difference, in seconds, between two dates? (did not work for me as I got TypeError: an integer is required (got type datetime.date))
and
Time difference in seconds (as a floating point) (this caters to only very tiny time differences and does not capture a scenario when user enters timestamps himself)
and
How to calculate the time interval between two time strings (this is what I have done in my code, but it does not work as expected)
Can you please suggest the problem in my code?
UPDATE: Thanks to #Tim Peters for pointing out that .date() discards the hours,mins and seconds.
I only needed to discard .date() for it to work correctly.
In this case the issue is that you create two datetime.datetime objects with strptime and immediately truncate them to datetime.date objects, which don't have the time components (hours, minutes, seconds, microseconds, tzinfo), so you get two calendar dates which are exactly 7 days apart.
You can fix your original code like this:
from datetime import datetime, timedelta
datetime1 = "2018-07-13 03:30:00"
datetime2 = "2018-07-20 04:30:00"
# The following creates two datetime.datetime objects
datetime2 = datetime.strptime(datetime2, "%Y-%m-%d %H:%M:%S")
datetime1 = datetime.strptime(datetime1, "%Y-%m-%d %H:%M:%S")
difference1 =(datetime2-datetime1).total_seconds()
print("the difference in seconds is "+str(difference1))
# if the difference is more than 7 days, relax , else start preparing
if difference1 > 604800:
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")
But one additional thing to note is that datetime.timedelta objects can be directly compared, so you do not need to calculate the number of seconds, so you can change that part to avoid the "number of seconds" calculation (and your intention is clearer):
difference1 = datetime2 - datetime1
# if the difference is more than 7 days, relax , else start preparing
if difference1 > timedelta(days=7):
I imagine that in reality you are not constructing the datetime.datetime objects from string literals as you have in this example, but in case you are, I would also note that you can directly construct those literals as well, so with that refactoring in place, here's how I would have written your example:
from datetime import datetime, timedelta
# The following creates two datetime.datetime objects
datetime1 = datetime(2018, 7, 13, 3, 30)
datetime2 = datetime(2018, 7, 20, 4, 30)
difference1 = datetime2 - datetime1
# if the difference is more than 7 days, relax , else start preparing
if difference1 > timedelta(days=7):
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")

how to subtract date from date from sql in python

I run a sql query that returns a date in the format '2015-03-01T17:09:00.000+0000' I want to subtract this from today's date.
I am getting today's date with the following:
import datetime
now = datetime.datetime.now()
The formats don't seem to line up and I can't figure out a standardize format.
You can use strptime from datetime module to get python compatible date time from your query result using a format string. (You might have to play with the format string a bit to suit your case)
ts = '2015-03-01T17:09:00.000+0000' to a format string like
f = '%Y-%m-%dT%H:%M:%S.%f%z'
date_from_sql = datetime.datetime.strptime(ts, f)
now = datetime.datetime.now()
delta = date_from_sql - now
The .000 is probably microseconds (denoted by %f in the format string) and the +0000 is the utc offset (denoted by %z in the format string). Check this out for more formatting options: https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior
Check out this thread for an example: what is the proper way to convert between mysql datetime and python timestamp?
Checkout this for more on strptime https://docs.python.org/2/library/datetime.html#datetime.datetime.strptime
Getting the delta between two datetime objects in Python is really simple, you simply subtract them.
import datetime
d1 = datetime.datetime.now()
d2 = datetime.datetime.now()
delta = d2 - d1
print delta.total_seconds()
d2 - d1 returns a datetime.timedelta object, from which you can get the total second difference between the two dates.
As for formatting the dates, you can read about formatting strings into datetime objects, and datetime objects into string here
You'll read about the strftime() and strptime() functions, and with them you can get yourself two datetime objects which you can subtract from each other.

Datetime ints in fewer lines

Right now I am using the following functions to calculate a date and time int like this (ymd), (hms). I believe it is easier to do this for comparison.
def getDayAsInt():
time = datetime.datetime.now()
year = time.strftime("%Y")
month=makeTimeTwoDigit(time.strftime("%m"))
day=makeTimeTwoDigit(time.strftime("%d"))
return year+month+day
def getTimeOfDay():
day=makeTimeTwoDigit(time.strftime("%d"))
hour=makeTimeTwoDigit(time.strftime("%H"))
minute=makeTimeTwoDigit(time.strftime("%M"))
second=makeTimeTwoDigit(time.strftime("%S"))
return hour+minute+second
I initially tried something like this:
'date': str(datetime.now()),
However I ran into an issue of easier generating a date range to query it. For example if today is 20140616 I can simply query dates between 20140601 and 20140616 where as generating all of the possible date times is harder. Does that make sense?
Ex I want to find out events that happened today but having a date time string stored in dynamodb is harder (more things to match to) to match.
I'm wondering if there is an easier or more efficient way? Is breaking the date and time down like that done? Should I take this:
year = time.strftime("%Y")
month=makeTimeTwoDigit(time.strftime("%m"))
day=makeTimeTwoDigit(time.strftime("%d"))
And do it inn one line? Like should I do time.strftime("%Y%m%d")?
If you are doing the comparisons in python, an easier solution would be to use builtin datetime objects and the normal comparison operators, like < and >.
from datetime import datetime
dt_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
if datetime(2006, 6, 5, 0, 0, 0) <= dt_object < datetime(2006, 6, 6, 0, 0, 0):
# do something when date is anytime on June 5th, 2006
If you must do the comparison in the query, you can use regular string comparison as long as your dates are stored in ISO-8601 format. The advantage of ISO-8601 is that chronological sorting is equivalent to lexographic sorting, i.e. you can treat them as normal strings.
The equivalent comparison using ISO-8601 format:
'2006-06-05T00:00:00Z' <= dt < '2006-06-06T00:00:00Z'
I thinking breaking the day (year/month/date) from time (hour/minute/second) is the cleanest solution for you since you want to do query on day.

Getting a lists of times in Python from 0:0:0 to 23:59:59 and then comparing with datetime values

I was working on code to generate the time for an entire day with 30 second intervals. I tried using DT.datetime and DT.time but I always end up with either a datetime value or a timedelta value like (0,2970). Can someone please tell me how to do this.
So I need a list that has data like:
[00:00:00]
[00:00:01]
[00:00:02]
till [23:59:59] and needed to compare it against a datetime value like 6/23/2011 6:38:00 AM.
Thanks!
Is there a reason you want to use datetimes instead of just 3 for loops counting up? Similarly, do you want to do something fancy or do you want to just compare against the time? If you don't need to account for leap seconds or anything like that, just do it the easy way.
import datetime
now = datetime.datetime.now()
for h in xrange(24):
for m in xrange(60):
for s in xrange(60):
time_string = '%02d:%02d:%02d' % (h,m,s)
if time_string == now.strftime('%H:%m:%S'):
print 'you found it! %s' % time_string
Can you give any more info about why you are doing this? It seems like you would be much much better off parsing the datetimes or using strftime to get what you need instead of looping through 60*60*24 times.
There's a great answer on how to get a list of incremental values for seconds for a 24-hour day. I reused a part of it.
Note 1. I'm not sure how you're thinking of comparing time with datetime. Assuming that you're just going to compare the time part and extracting that.
Note 2. The time.strptime call expects a 12-hour AM/PM-based time, as in your example. Its result is then passed to time.strftime that returns a 24-hour-based time.
Here's what I think you're looking for:
my_time = '6/23/2011 6:38:00 AM' # time you defined
from datetime import datetime, timedelta
from time import strftime, strptime
now = datetime(2013, 1, 1, 0, 0, 0)
last = datetime(2013, 1, 1, 23, 59, 59)
delta = timedelta(seconds=1)
times = []
while now <= last:
times.append(now.strftime('%H:%M:%S'))
now += delta
twenty_four_hour_based_time = strftime('%H:%M:%S', strptime(my_time, '%m/%d/%Y %I:%M:%S %p'))
twenty_four_hour_based_time in times # returns True

Converting date formats python - Unusual date formats - Extract %Y%M%D

I have a large data set with a variety of Date information in the following formats:
DAYS since Jan 1, 1900 - ex: 41213 - I believe these are from Excel http://www.kirix.com/stratablog/jd-edwards-date-conversions-cyyddd
YYDayofyear - ex 2012265
I am familiar with python's time module, strptime() method, and strftime () method. However, I am not sure what these date formats above are called on if there is a python module I can use to convert these unusual date formats.
Any idea how to get the %Y%M%D format from these unusual date formats without writing my own calculator?
Thanks.
You can try something like the following:
In [1]: import datetime
In [2]: s = '2012265'
In [3]: datetime.datetime.strptime(s, '%Y%j')
Out[3]: datetime.datetime(2012, 9, 21, 0, 0)
In [4]: d = '41213'
In [5]: datetime.date(1900, 1, 1) + datetime.timedelta(int(d))
Out[5]: datetime.date(2012, 11, 2)
The first one is the trickier one, but it uses the %j parameter to interpret the day of the year you provide (after a four-digit year, represented by %Y). The second one is simply the number of days since January 1, 1900.
This is the general conversion - not sure of your input format but hopefully this can be tweaked to suit it.
On the Excel integer to Python datetime bit:
Note that there are two Excel date systems (one 1-Jan-1900 based and another 1-Jan 1904 based); see https://support.microsoft.com/en-us/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel for more information.
Also note that the system is NOT zero-based. So, in the 1900 system, 1-Jan-1900 is day 1 (not day 0).
import datetime
EXCEL_DATE_SYSTEM_PC=1900
EXCEL_DATE_SYSTEM_MAC=1904
i = 42129 # Excel number for 5-May-2015
d = datetime.date(EXCEL_DATE_SYSTEM_PC, 1, 1) + datetime.timedelta(i-2)
Both of these formats seems pretty straightforward to work with. The first one, in fact, is just an integer, so why don't you just do something like this?
import datetime
def days_since_jan_1_1900_to_datetime(d):
return datetime.datetime(1900,1,1) + \
datetime.timedelta(days=d)
For the second one, the details depend on exactly how the format is defined (e.g. can you always expect 3 digits after the year even when the number of days is less than 100, or is it possible that there are 2 or 1 – and if so, is the year always 4 digits?) but once you've got that part down it can be done very similarly.
According to http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior
, day of the year is "%j", whereas the first case can be solved by toordinal() and fromordinal(): date.fromordinal(date(1900, 1, 1).toordinal() + x)
I'd think timedelta.
import datetime
d = datetime.timedelta(days=41213)
start = datetime.datetime(year=1900, month=1, day=1)
the_date = start + d
For the second one, you can 2012265[:4] to get the year and use the same method.
edit: See the answer with %j for the second.
from datetime import datetime
df(['timeelapsed'])=(pd.to_datetime(df['timeelapsed'], format='%H:%M:%S') - datetime(1900, 1, 1)).dt.total_seconds()

Categories

Resources