Prakhar Mehrotra
Prakhar Mehrotra

Reputation: 1231

Converting time stamp to minutes elapsed in Python

I am making a news blog for my project in which I have to display time under the news title as x minutes ago etc.

From the RSS feed of the news, I have the time stamp in the form of a string. For example:

timestamp = 'Tue, 12 Feb 2013 07:43:09 GMT'

I am trying to find the difference between this timestamp and the present time using datetime module in python. But for some reason it gives error:

ValueError: astimezone() cannot be applied to a naive datetime

I'll appreciate if somebody can point me in the right direction. Below is my attempt in Python:

from datetime import datetime
from pytz import timezone
timestamp = 'Tue, 12 Feb 2013 07:43:09 GMT'  
t = datetime.strptime(timestamp, '%a, %d %b %Y %I:%M:%S %Z')
now_time = datetime.now(timezone('US/Pacific'))
# converting the timestamp to Pacific time
t_pacific = t.astimezone(timezone('US/Pacific'))   # get error here
diff = t_pacific - t

Thanks! Prakhar

Upvotes: 1

Views: 2115

Answers (2)

abarnert
abarnert

Reputation: 365717

The problem here is that t does not have a timezone—that's what the error message means by "naive datetime". From the docs:

There are two kinds of date and time objects: “naive” and “aware”… An aware object has sufficient knowledge of… time zone and daylight savings time information… A naive object does not…

You can verify that it's naive by doing this:

print(t.tzinfo)

The answer will be None.

As the astimezone docs say:

self must be aware (self.tzinfo must not be None, and self.utcoffset() must not return None).

The strptime function always generates a naive datetime.

You can fix this in various ways:

  • First convert t to a GMT datetime instead of a naive one, and then your conversion to 'US/Pacific' will work.

As the docs say, "If you merely want to attach a time zone object tz to a datetime dt without adjustment of date and time data, use dt.replace(tzinfo=tz)." Since you know the time is in UTC, just replace the empty tz with UTC, and you've got an aware time.

  • Convert to PST with a different mechanism than astimezone, on which will assume UTC or which allows you to specify the source.

There are various alternatives out there, but you're already using pytz, so see its documentation.

  • Convert now_time to UTC instead of converting t to PST.

The last one is probably the simplest and best for most use cases. Since you've only got now_time in PST because you explicitly asked for it that way, all you have to do is not do that (or explicitly ask for 'GMT' instead of 'US/Pacific'). Then you can just do your date arithmetic on UTC times.

If you need to display final results in PST, it's still often better to do the arithmetic in UTC, and convert at the end. (For example, you can have two times that are an hour apart, but have the same value in Pacific, because of 1am on DST day being repeated twice; that won't be an issue if you stay in UTC all the time.)

Upvotes: 2

Craig McQueen
Craig McQueen

Reputation: 43446

Your example had a few problems (I see you've fixed them now):

  • First line should be:

    from datetime import datetime
    
  • It looks as though you're missing a closing parenthesis on the 4th line:

    now_time = datetime.now(timezone('US/Pacific')
    
  • What is timezone()? Where does that come from?

You don't really need to mess with timezones, I don't think — just use GMT (UTC). How about something more like this:

from datetime import datetime
timestamp = 'Tue, 12 Feb 2013 07:43:09 GMT'  
t = datetime.strptime(timestamp, '%a, %d %b %Y %I:%M:%S %Z')
t_now = datetime.utcnow()
diff = t_now - t

Upvotes: 3

Related Questions