5

I'm stumped. The date-cleaning functions I wrote work in Python 2.7.5 on my Mac but not in 2.7.6 on my Ubuntu server.

Python 2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> date = datetime.strptime('2013-08-15 10:23:05 PDT', '%Y-%m-%d %H:%M:%S %Z')
>>> print(date)
2013-08-15 10:23:05

Why does this not work in 2.7.6 on Ubuntu?

Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> date = datetime.strptime('2013-08-15 10:23:05 PDT', '%Y-%m-%d %H:%M:%S %Z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data '2013-08-15 10:23:05 PDT' does not match format '%Y-%m-%d %H:%M:%S %Z'

Edit: I tried using the timezone offset with the lowercase %z, but still get an error (although a different one):

>>> date = datetime.strptime('2013-08-15 10:23:05 -0700', '%Y-%m-%d %H:%M:%S %z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 317, in _strptime
    (bad_directive, format))
ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'
Pacific Stickler
  • 1,078
  • 8
  • 20
Nicole White
  • 7,720
  • 29
  • 31
  • Just to narrow it down, same machine or different machines? – NPE Sep 10 '14 at 20:01
  • 1
    Oh, just noticed the different OSes, so clearly different machines. – NPE Sep 10 '14 at 20:02
  • Different machines. I have 2.7.5 on my Mac but the server (Ubuntu) I'm trying to run the script on has 2.7.6. – Nicole White Sep 10 '14 at 20:02
  • I am thinking that it's more likely to do with the underlying operating systems or with how the two machines are configured than with any differences between 2.7.5 and 2.7.6. – NPE Sep 10 '14 at 20:04
  • 3
    Are both machines in a locale where the time zone is PDT? `%Z` will only match `PDT` if the machine's local time zone name is PDT. – unutbu Sep 10 '14 at 20:04
  • 4
    https://docs.python.org/2/library/time.html#time.strptime says "Support for the %Z directive is based on the values contained in tzname and whether daylight is true. Because of this, it is platform-specific except for recognizing UTC and GMT which are always known (and are considered to be non-daylight savings timezones)." This *might* shed some light. – NPE Sep 10 '14 at 20:05
  • @unutbu I didn't realize that's how it worked. How do I read in dates that have different time zones on a single machine? There will be dates in PDT, GMT, etc. that I'll need to convert to date objects. – Nicole White Sep 10 '14 at 20:09
  • @NicoleWhite: You're welcome (not that it helps much in solving the actual problem). – NPE Sep 10 '14 at 20:13
  • I think @unutbu might be on to something. I get the same `ValueError` when I run the code on my Mac (which has exactly the same version of Python as your Mac, but is configured for a timezone other than PDT). – NPE Sep 10 '14 at 20:15
  • 2
    @NicoleWhite: Parsing the timezone abbreviation is problematic because they do not uniquely specify a timezone. For example, EST can mean Eastern Standard Time in the US, or it could mean Eastern Summer Time in Australia. (More on this, with links, [here](http://stackoverflow.com/a/22364003/190597)) – unutbu Sep 10 '14 at 20:22
  • @unutbu Ok. I can convert all of them to their offsets, but in my edits you can see that the %z doesn't work either. http://bugs.python.org/issue6641 – Nicole White Sep 10 '14 at 20:27
  • can you check what you get from `import time` and then `time.tzname` on your machine? Any other value apart from these may fail – Pacific Stickler Sep 10 '14 at 20:29
  • @PacificStickler Right. I get ('UTC', 'UTC'), so I'll have to figure something out. – Nicole White Sep 10 '14 at 20:33
  • @unutbu Can you go ahead and add your comments as an answer? – Nicole White Sep 10 '14 at 20:38

2 Answers2

5

Timezone abbreviations are ambiguous. For example, EST can mean Eastern Standard Time in the US, or it could mean Eastern Summer Time in Australia.

Therefore, datetime strings which contain timezone abbreviations can not be reliably parsed into timezone-aware datetime objects.

strptime's '%Z' format will only match UTC, GMT or the timezone abbreviation listed in time.tzname, which is machine-locale dependent.

If you can change the datetime strings to ones containing UTC offsets, then you could use dateutil to parse the strings into timezone-aware datetime objects:

import dateutil
import dateutil.parser as DP
date = DP.parse('2013-08-15 10:23:05 -0700')
print(repr(date))
# datetime.datetime(2013, 8, 15, 10, 23, 5, tzinfo=tzoffset(None, -25200))
Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
3

%Z will only accept GMT, UTC, and whatever is listed in time.tzname, since the time zone functionality is platform specific, as is given here:

Support for the %Z directive is based on the values contained in tzname and whether daylight is true. Because of this, it is platform-specific except for recognizing UTC and GMT which are always known (and are considered to be non-daylight savings timezones).

So try to figure out what time zones are supported by your platform by running the following:

import time
time.tzname

I get the following:

('PST', 'PDT')

Thus, your best bet might be to convert your time beforehand to one of the default allowed time zones.

Pacific Stickler
  • 1,078
  • 8
  • 20