5

I extract the launch_time from EC2 instance, it returns a unicode string like this:

2014-12-22T08:46:10.000Z

I use dateutil parser to convert it to datetime with

launch_time = parser.parse(instance.launch_time)

so I get lunch_time after converted like this:

2014-12-22 08:46:10+00:00

And I want to compare this launchtime with current time to see how long this instance has been running.

I get current_time with:

current_time = datetime.datetime.now()

and I get it like this:

2014-12-22 11:46:10.527010

Now I have two timestamps, I have this function

def timeDiff(launch_time, current_time):
    running_time = current_time - launch_time
    return running_time.seconds/60

I expect the result would be 180 minutes (3 hours). But I got this error:

TypeError: can't subtract offset-naive and offset-aware datetimes

I think there's obvious difference between these two timestamps. I need to compare exactly date and time to see how long it has been running. I couldn't find a proper way to solve this. Any thoughts appreciated!

Ragnarsson
  • 1,715
  • 7
  • 41
  • 74
  • 1
    unrelated: use `running_time.total_seconds()` instead of `.seconds`. – jfs Dec 22 '14 at 15:25
  • related: [Find if 24 hrs have passed between datetimes](http://stackoverflow.com/q/26313520/4279) – jfs Dec 22 '14 at 15:27
  • It's useful to be aware that the OP assumed that the time diff is < 1 day and that the code will not work for time diff > 1 day, because `.seconds` does not count days. See https://stackoverflow.com/questions/5522031/convert-timediff-to-total-seconds – Alex Harvey Jun 20 '17 at 02:32

2 Answers2

8

You can specify the timezone you want from now() like the following:

current_time = datetime.datetime.now(launch_time.tzinfo)

Then your subtraction should work, as both of the times will be timezone aware.

Edit: I should note that you can put whatever timezone object you want in now() and it will work just fine. now() will convert the time to whatever timezone you pass. The important part is to simply ensure that if you're adding/subtracting datetime objects that they both have timezones (or they both lack timezones).

alienth
  • 349
  • 2
  • 8
  • 1
    Thanks a lot. It worked just fine with launch_time.tzinfo. I got the expected result. Thanksss! – Ragnarsson Dec 22 '14 at 15:15
  • @LouisTran: another way is to remove `tzinfo`: `(datetime.utcnow() - launch_time.replace(tzinfo=None)).total_seconds()` but @alienth solution is better because it works even if `launch_time` is not in UTC timezone. – jfs Dec 22 '14 at 15:24
1
import boto.ec2
from dateutil.parser import *
import subprocess
import datetime


instance_id = subprocess.check_output(['curl', '-s', 'http://169.254.169.254/latest/meta-data/instance-id'])

conn = boto.ec2.connect_to_region('ap-southeast-2',aws_access_key_id='Your_Key', aws_secret_access_key='Your_Secret')

reservations = conn.get_all_reservations(instance_ids=[instance_id])

for r in reservations:
    for instance in r.instances:
        lt_datetime = parse(instance.launch_time)
        lt_delta = datetime.datetime.now(lt_datetime.tzinfo) - lt_datetime
        uptime = str(lt_delta)
        print(uptime)
user223903
  • 21
  • 3