21

Following on from my previous question, Python time to age, I have now come across a problem regarding the timezone, and it turns out that it's not always going to be "+0200". So when strptime tries to parse it as such, it throws up an exception.

I thought about just chopping off the +0200 with [:-6] or whatever, but is there a real way to do this with strptime?

I am using Python 2.5.2 if it matters.

>>> from datetime import datetime >>> fmt = "%a, %d %b %Y %H:%M:%S +0200" >>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200", fmt) datetime.datetime(2008, 7, 22, 8, 17, 41) >>> datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0300", fmt) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.5/_strptime.py", line 330, in strptime (data_string, format)) ValueError: time data did not match format: data=Tue, 22 Jul 2008 08:17:41 +0300 fmt=%a, %d %b %Y %H:%M:%S +0200 
0

5 Answers 5

40

is there a real way to do this with strptime?

No, but since your format appears to be an RFC822-family date, you can read it much more easily using the email library instead:

>>> import email.utils >>> email.utils.parsedate_tz('Tue, 22 Jul 2008 08:17:41 +0200') (2008, 7, 22, 8, 17, 41, 0, 1, 0, 7200) 

(7200 = timezone offset from UTC in seconds)

Sign up to request clarification or add additional context in comments.

6 Comments

Interesting, but then can I somehow work out the difference between two dates easily?
If you're using datetime, create a datetime using the first six values of the resulting tuple, then compensate for the zone by subtracting a delta of the last value, eg. “datetime.datetime(*a[:6])-datetime.timedelta(seconds= a[-1])”. Then proceed to compare datetimes as in the previous question.
If you're using plain old ‘time’, use mktime() to go from a tuple of all but the last value to a numeric timestamp, then subtract the last value. Note that mktime gives you a timestamp based on your local server timezone not UTC, but that doesn't matter if you are merely comparing two timestamps.
Funny that the email module actually does the job easier than the timedate module itself!
@Ashy: to find the difference, you could convert time tuples into seconds since the Epoch: ts = mktime_tz(parsedate_tz(date_str)).
|
28

New in version 2.6.

For a naive object, the %z and %Z format codes are replaced by empty strings.

It looks like this is implemented only in >= 2.6, and I think you have to manually parse it.

I can't see another solution than to remove the time zone data:

from datetime import timedelta,datetime try: offset = int("Tue, 22 Jul 2008 08:17:41 +0300"[-5:]) except: print "Error" delta = timedelta(hours = offset / 100) fmt = "%a, %d %b %Y %H:%M:%S" time = datetime.strptime("Tue, 22 Jul 2008 08:17:41 +0200"[:-6], fmt) time -= delta 

3 Comments

Once again, thanks gs and also David :) I guess I'll just have to chop the end off, don't wanna rely on 2.6 for this.
Doesn't work for timezones like Venezuela: -0430
@chachan: But trivially adapted.
18

You can use the dateutil library which is very useful:

from datetime import datetime from dateutil.parser import parse dt = parse("Tue, 22 Jul 2008 08:17:41 +0200") ## datetime.datetime(2008, 7, 22, 8, 17, 41, tzinfo=tzoffset(None, 7200)) <- dt print dt 2008-07-22 08:17:41+02:00 

1 Comment

I was not aware of this solution, just tested: works really great!
1

As far as I know, strptime() doesn't recognize numeric time zone codes. If you know that the string is always going to end with a time zone specification of that form (+ or - followed by 4 digits), just chopping it off and parsing it manually seems like a perfectly reasonable thing to do.

Comments

0

It seems that %Z corresponds to time zone names, not offsets.

For example, given:

>>> format = '%a, %d %b %Y %H:%M:%S %Z' 

I can parse:

>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 GMT', format) datetime.datetime(2008, 7, 22, 8, 17, 41) 

Although it seems that it doesn't do anything with the time zone, merely observing that it exists and is valid:

>>> datetime.datetime.strptime('Tue, 22 Jul 2008 08:17:41 NZDT', format) datetime.datetime(2008, 7, 22, 8, 17, 41) 

I suppose if you wished, you could locate a mapping of offsets to names, convert your input, and then parse it. It might be simpler to just truncate your input, though.

2 Comments

%Z is the timezone as a name, %z in houres.
If I try to use %z in strptime, I get: ValueError: 'z' is a bad directive in format '%z'

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.