Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate time difference using Python [duplicate]

I am wondering if there is a way or builtin library available to find the difference in time from two string input.

What I mean is, if I have 2 input strings:

  1. '2013-10-05T01:21:07Z'
  2. '2013-10-05T01:21:16Z'

how can I can calculate the difference in time and print it as output.

I know it sounds a bit silly but any help on this is appreciated.

like image 880
Prince Sharma Avatar asked May 27 '14 09:05

Prince Sharma


2 Answers

Parsing your strings using strptime():

a = time.strptime('2013-10-05T01:21:07Z', '%Y-%m-%dT%H:%M:%SZ')
b = time.strptime('2013-10-05T01:21:16Z', '%Y-%m-%dT%H:%M:%SZ')

This will parse the given time strings as local times (setting daylight savings (DST) to automatic), and the results are time structs. These still reflect whether DST was explicitly off (0), on (1), or implicitly automatic (-1). Convert these to a float (seconds since 1970-01-01):

a = time.mktime(a)
b = time.mktime(b)

Then compute the difference (in seconds):

d = b - a

And convert them to days/hours/minutes/seconds:

days = int(d) / 86400
hours = int(d) / 3600 % 24
minutes = int(d) / 60 % 60
seconds = int(d) % 60

The last block only works properly for positive differences, so be careful not to swap the a and b ;-)

But @J.F.Sebastian correctly pointed out that this might not be what you intended. It seems from the notation that your strings describe a UTC time, not a local time. For mere time differences this is relevant in case your time spans over a DST switch. In this case it would of course result in a time difference one hour too great or one hour too small (because UTC is always without DST).

To avoid this, you can set the DST flag from automatic (-1) to a fixed value (e. g. 0 for off) and use these values:

a = time.mktime(a[:-1] + (0,))  # switch DST to off
b = time.mktime(b[:-1] + (0,))

Or, also as @J.F.Sebastian pointed out, you could forget about the time module and instead use datetime.datetime which is unaware of the DST aspect:

a = datetime.datetime.strptime('2013-10-05T01:21:07Z', '%Y-%m-%dT%H:%M:%SZ')
b = datetime.datetime.strptime('2013-10-05T01:21:16Z', '%Y-%m-%dT%H:%M:%SZ')

Then the results are datetime objects which can be subtracted directly to get a timedelta object which represents such a time difference as you want it. Printing it will result in sth like 0:00:05 which might well be exactly what you are looking for.

like image 135
Alfe Avatar answered Oct 13 '22 12:10

Alfe


You seem to be using an ISO 8601 formatted dateTime. This format is used in many places, including the GPS eXchange Format.

[-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]

Using datetime:

import datetime
a = datetime.datetime.strptime("2013-10-05T01:21:07Z", "%Y-%m-%dT%H:%M:%SZ")
b = datetime.datetime.strptime("2013-10-05T01:21:16Z", "%Y-%m-%dT%H:%M:%SZ")
c = b - a
print(c)

Advantages:

  • Built-in to Python Standard Library
  • Object-oriented interface

Disadvantages:

  • Need to manually handle other valid ISO 8601 representations such as '2013-10-05T01:21:16+00:00'
  • Throws exception for leap seconds such as '2012-06-30T23:59:60Z'

Using python-dateutil:

import dateutil.parser
a = dateutil.parser.parse("2013-10-05T01:21:07Z")
b = dateutil.parser.parse("2013-10-05T01:21:16Z")
c = b - a
print(c)

Advantages:

  • Automagically handles pretty much any time format

Disadvantages:

  • Needs python-dateutil library (pip install python-dateutil)
  • Throws exception for leap seconds such as '2012-06-30T23:59:60Z'

Using time.strptime and time.mktime as suggested by Alfe

Advantages:

  • Built-in to Python Standard Library
  • Can parse leap seconds such as '2012-06-30T23:59:60Z'

Disadvantages:

  • Need to manually handle other valid ISO 8601 representations such as '2013-10-05T01:21:16+00:00'
  • Loss of one leap second between '2012-06-30T23:59:60Z' and '2012-07-01T00:00:00Z' (unavoidable without knowing when leap seconds will next occur)
like image 25
anjsimmo Avatar answered Oct 13 '22 12:10

anjsimmo