9

I have the following string "2017-03-30 08:25:00CET" which I want to convert to a datetime tz-aware object.

According this SO question, from python 3.2 it can be done using only datetime module. In addition, from the documentation, I see

%z |  UTC offset in the form +HHMM or -HHMM (empty string if the object is naive). |  (empty), +0000, -0400, +1030
%Z |  Time zone name (empty string if the object is naive).                        |  (empty), UTC, EST, CST

So I try the following

datetime.strptime(dep_dt, '%Y-%m-%d %H:%M:%S%Z')

I do not get any error, but then the object I get is not tz-aware

datetime.datetime(2017, 3, 30, 8, 25)

On the other hand, if I convert my string to "2017-03-30 08:25:00+0200" and then convert it to an object with

datetime.strptime(dep_dt, '%Y-%m-%d %H:%M:%S%z')

I do get a tz-aware datetime:

datetime.datetime(2017, 3, 30, 8, 25, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

Any ideas of why it works with %z but not with %Z? What am I doing wrong?

Community
  • 1
  • 1
J0ANMM
  • 7,849
  • 10
  • 56
  • 90
  • Relevant for you: http://stackoverflow.com/questions/1703546/parsing-date-time-string-with-timezone-abbreviated-name-in-python http://stackoverflow.com/questions/3305413/python-strptime-and-timezones. Timezone names (such as `cet`) are ambiguous. Your second example works because you specifically give the timezone offset `+0200`. use the parser within dateutil, or manually specify your timezone using tzinfo(). – Chuck Feb 02 '17 at 11:22
  • 1
    Using Python 3.6, I get a `ValueError: time data '2017-03-30 08:25:00CET' does not match format '%Y-%m-%d %H:%M:%S%Z'` from executing `datetime.strptime("2017-03-30 08:25:00CET", '%Y-%m-%d %H:%M:%S%Z')`, which differs from what you say. – martineau Feb 02 '17 at 11:22
  • @CharlesMorris , thanks for the links. I found the 2nd specially interesting. To me it does not make sense that in the documentation the possibility of using timezone names is given, but then it does not work because it is ambiguous. – J0ANMM Feb 02 '17 at 11:37
  • http://bugs.python.org/issue22377 – Chuck Feb 02 '17 at 11:38
  • @martineau , strange... I am using python 3.5.2. and do not get any error. I just copy-pasted your line in my shell, and it works as I described. – J0ANMM Feb 02 '17 at 11:39
  • 2
    This is a known bug described here: http://bugs.python.org/issue22377 – Chuck Feb 02 '17 at 11:44
  • @martineau , for me it does not make any difference if having "UTC" or "CET" at the end. I tried both and get not error, but in both cases as result I get a naive datetime object `datetime.datetime(2017, 3, 30, 8, 25)` – J0ANMM Feb 02 '17 at 11:45
  • J0ANMM: My interpretation of the docs wasn't exactly correct, only UTC avoids the error (EST and CST aren't acceptable). @CharlesMorris must be correct that this is bug. – martineau Feb 02 '17 at 11:50

1 Answers1

4

Judging from the information given by tzinfo, the %Z does not work the way that you feed in a string like "UTC" and it will return a datetime instance with the correct timezone.

pytz provides a possible solution to your problem. However, the documentation says, that there is no guarentee that your timezone will be recognized by datetime and recommends working with UTC as long as possible.

Solution using pytz:

from datetime import datetime
from pytz import timezone
dep_dt = '2017-03-30 08:25:00CET'
dt = datetime.strptime(dep_dt, '%Y-%m-%d %H:%M:%S%Z')
timezone(dep_dt[19:]).localize(dt)

Out:

datetime.datetime(2017, 3, 30, 8, 25, tzinfo=<DstTzInfo 'CET' CEST+2:00:00 DST>)
UpSampler
  • 399
  • 2
  • 6
  • 1
    Does that mean that the documentation from `datetime` is just wrong? – J0ANMM Feb 02 '17 at 11:42
  • At least it is not very clear. There is a note explaining the behavior, but this does not make it clear either in my opinon: "%Z If tzname() returns None, %Z is replaced by an empty string. Otherwise %Z is replaced by the returned value, which must be a string. Changed in version 3.2: When the %z directive is provided to the strptime() method, an aware datetime object will be produced. The tzinfo of the result will be set to a timezone instance" – UpSampler Feb 02 '17 at 11:53
  • I added a solution using pytz now. – UpSampler Feb 02 '17 at 12:12
  • If I run your code on Python 3.8.5, I get ValueError: time data '2017-03-30 08:25:00CET' does not match format '%Y-%m-%d %H:%M:%S%Z'. I remember there is a change from earlier version.. – Lan Si Dec 01 '21 at 05:39