2

I'm trying to convert a date string into an age.

The string is like: "Mon, 17 Nov 2008 01:45:32 +0200" and I need to work out how many days old it is.

I have sucessfully converted the date using:

>>> time.strptime("Mon, 17 Nov 2008 01:45:32 +0200","%a, %d %b %Y %H:%M:%S +0200")
(2008, 11, 17, 1, 45, 32, 0, 322, -1)

For some reason %z gives me an error for the +0200 but it doesn't matter that much.

I can get the current time using:

>>> time.localtime()
(2009, 2, 3, 19, 55, 32, 1, 34, 0)

but how can I subtract one from the other without going though each item in the list and doing it manually?

Benjamin Gruenbaum
  • 246,787
  • 79
  • 474
  • 476
Ashy
  • 1,893
  • 5
  • 20
  • 24

6 Answers6

16

You need to use the module datetime and the object datetime.timedelta

from datetime import datetime

t1 = datetime.strptime("Mon, 17 Nov 2008 01:45:32 +0200","%a, %d %b %Y %H:%M:%S +0200")
t2 = datetime.now()

tdelta = t2 - t1 # actually a datetime.timedelta object
print tdelta.days
Georg Schölly
  • 116,521
  • 48
  • 204
  • 258
  • The code snippet is incorrect. You need to import 'datetime' from datetime, not date (or use the date object, rather than the datetime object). – Tony Meyer Feb 04 '09 at 09:08
  • 1
    The result is incorrect if input date string is not in the local timezone. You need [an aware datetime object as in my answer](http://stackoverflow.com/a/25426694/4279) instead or some other way to track given UTC offset e.g., [`email.utils.parsedate_tz()`-based solution](http://stackoverflow.com/a/510638/4279). Also, `tdelta.days` may give a surprising result e.g., `timedelta(seconds=-5).days == -1`; `tdelta / timedelta(1)` could be used instead (or its analog on older Python versions: `timedelta(seconds=-5).total_seconds() / 86400`). – jfs Aug 21 '14 at 12:46
  • the result may be also wrong if `t1` and `t2` have different UTC offsets e.g., if `t1` is a standard time and `t2` is a summer time (`is_dst=1`) -- see [what may happen if `t1` and `t2` are on the opposite sides of DST transition](http://stackoverflow.com/a/25427822/4279). – jfs Aug 25 '14 at 18:12
5

In Python, datetime objects natively support subtraction:

from datetime import datetime
age = datetime.now() - datetime.strptime(...)
print age.days

The result is a timedelta object.

Ben Blank
  • 50,243
  • 26
  • 123
  • 150
  • [The result is incorrect if input date string is not in the local timezone.](http://stackoverflow.com/questions/508727/python-time-to-age/25426694#comment39666382_508742) – jfs Aug 21 '14 at 12:49
2
from datetime import datetime, timedelta
datetime.now()
datetime.datetime(2009, 2, 3, 15, 17, 35, 156000)
datetime.now() - datetime(1984, 6, 29 )
datetime.timedelta(8985, 55091, 206000)
datetime.now() - datetime(1984, 6, 29 )
datetime.timedelta(8985, 55094, 198000) # my age...

timedelta(days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])

Alex. S.
  • 126,349
  • 16
  • 50
  • 61
1

If you don't want to use datetime (e.g. if your Python is old and you don't have the module), you can just use the time module.

s = "Mon, 17 Nov 2008 01:45:32 +0200"
import time
import email.utils # Using email.utils means we can handle the timezone.
t = email.utils.parsedate_tz(s) # Gets the time.mktime 9-tuple, plus tz
d = time.time() - time.mktime(t[:9]) + t[9] # Gives the difference in seconds.
Tony Meyer
  • 9,361
  • 5
  • 38
  • 47
  • +1 for parsedate_tz. Though your code produces a wrong result due to `+ t[9]`, [use mktime_tz() as in my answer instead](http://stackoverflow.com/a/25426694/4279) – jfs Aug 21 '14 at 12:45
0

Since Python 3.2, datetime.strptime() returns an aware datetime object if %z directive is provided:

#!/usr/bin/env python3
from datetime import datetime, timezone, timedelta

s = "Mon, 17 Nov 2008 01:45:32 +0200"
birthday = datetime.strptime(s, '%a, %d %b %Y %H:%M:%S %z')
age = (datetime.now(timezone.utc) - birthday) / timedelta(1) # age in days
print("%.0f" % age)

On older Python versions the correct version of @Tony Meyer's answer could be used:

#!/usr/bin/env python
import time
from email.utils import parsedate_tz, mktime_tz

s = "Mon, 17 Nov 2008 01:45:32 +0200"
ts = mktime_tz(parsedate_tz(s))   # seconds since Epoch
age = (time.time() - ts) / 86400  # age in days
print("%.0f" % age)

Both code examples produce the same result.

Community
  • 1
  • 1
jfs
  • 346,887
  • 152
  • 868
  • 1,518
0

Thanks guys, I ended up with the following:

def getAge( d ):
    """ Calculate age from date """
    delta = datetime.now() - datetime.strptime(d, "%a, %d %b %Y %H:%M:%S +0200")
    return delta.days + delta.seconds / 86400.0 # divide secs into days

Giving:

>>> getAge("Mon, 17 Nov 2008 01:45:32 +0200")
78.801319444444445
Ashy
  • 1,893
  • 5
  • 20
  • 24