This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: strftime/strptime round trip fails even for UTC datetime object
Type: behavior Stage: resolved
Components: Extension Modules, Library (Lib) Versions: Python 3.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: belopolsky Nosy List: akira, belopolsky, berker.peksag, brett.cannon, gvanrossum, mark.dickinson, python-dev
Priority: normal Keywords: easy, patch

Created on 2014-08-21 11:35 by akira, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue22241.diff belopolsky, 2015-08-28 16:07 review
issue22241-2.diff belopolsky, 2015-09-06 17:02 review
Messages (12)
msg225606 - (view) Author: Akira Li (akira) * Date: 2014-08-21 11:35
>>> from datetime import datetime, timezone
  >>> dt = datetime.now(timezone.utc)
  >>> fmt = '%Y-%m-%d %H:%M:%S.%f %Z%z'
  >>> datetime.strptime(dt.strftime(fmt), fmt)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/cpython/Lib/_strptime.py", line 500, in _strptime_datetime
      tt, fraction = _strptime(data_string, format)
    File "/cpython/Lib/_strptime.py", line 337, in _strptime
      (data_string, format))
  ValueError: time data '2014-08-21 11:29:13.537251 UTC+00:00+0000'
  does not match format '%Y-%m-%d %H:%M:%S.%f %Z%z'

The issue is that dt.strftime('%Z') produces 'UTC+00:00'
(due to timezone.utc.tzname(dt) returning 'UTC+00:00')
instead of 'UTC' that strptime() accepts and %Z examples [1]
in the docs demonstrate.

[1] https://docs.python.org/3.4/library/datetime.html#strftime-and-strptime-behavior
msg225609 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2014-08-21 14:46
This is a duplicate of #15873.
msg225623 - (view) Author: Akira Li (akira) * Date: 2014-08-21 23:45
I don't see, how it is a duplicate. Everything works if pytz.utc (.tzname() == 'UTC')
is used instead of timezone.utc (.tzname() == 'UTC+00:00').
Everything works if UTC class from the example [1] 
in the tzinfo docs is used.
It only breaks due to the weird timezone.utc.tzname() return value.

[1] https://docs.python.org/3.4/library/datetime.html#datetime.tzinfo.fromutc

Why does datetime.now(timezone.utc).strftime('%Z')
(via timezone.utc.tzname(dt)) produce 'UTC+00:00'?
How is it motivated?
Is it documented somewhere?
Can datetime.now(timezone.utc).strftime('%Z') be changed to return 'UTC'?
msg225625 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2014-08-22 00:25
I see.  I thought you were complaining about "%z" format not supporting "00:00" as in 

>>> from datetime import *
>>> datetime.strptime("00:00","%z")
Traceback (most recent call last):
 ..
ValueError: time data '00:00' does not match format '%z'

but your issue is that %Z does not parse "UTC+00:00" as in

>>> datetime.strptime("UTC+00:00x","%Zx")
Traceback (most recent call last):
 ..
ValueError: time data 'UTC+00:00x' does not match format '%Zx'

The name produced by timezone when no name is explicitly specified is documented:

https://docs.python.org/3.4/library/datetime.html#datetime.timezone.tzname


> Can datetime.now(timezone.utc).strftime('%Z') be changed to return 'UTC'?

I think it can.  I am surprised this did not come up in #5094 where UTC±hh:mm syntax was discussed.

The change would be trivial - just supply explicit name to utc singleton.

Please ask on Python-Dev if anyone would object.
msg225626 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2014-08-22 00:40
See also <http://bugs.python.org/issue5094#msg106476>.

It looks like providing 'UTC' as the name of utc singleton was part of my original proposal.  I have no recollection on why it was not implemented that way.
msg225630 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2014-08-22 00:56
Akira,

I see that you participated in the original discussion (msg107608).  We settled on str(timezone.utc) == 'UTC+00:00' and this was clearly a deliberate choice.  I don't think we can revisit this now, but we can probably make strptime smart enough to parse UTC±hh:mm with %Z format code.
msg225644 - (view) Author: Akira Li (akira) * Date: 2014-08-22 05:01
> I see that you participated in the original discussion (msg107608).
> We settled on str(timezone.utc) == 'UTC+00:00' and this was clearly a
> deliberate choice.  I don't think we can revisit this now, but we can
> probably make strptime smart enough to parse UTC±hh:mm with %Z format
> code.

I see it advocates either 'UTC' or '+00:00' ('-00:00' is semantically
different) i.e., mutually exclusive options: UTC is special enough
(it is a real timezone that is widely used) to warrant 'UTC' name. On
the other hand '+HH:MM' (%:z) (note: *without* 'UTC' prefix) is easily
extendable for a fixed-offset tzinfo family and it allows to use %Z to
generate/parse date/time strings with rfc3339-like utc offset and the
"numeric" tzname() would stress that a fixed-offset datetime.timezone
doesn't represent "real" zoneinfo timezone.

UTC+HH:MM is neither here nor there: it is easily confusable with
deprecated :GMT+H, Etc/GMT-H zoneinfo timezones (I'm not sure about
the signs) and it doesn't help generate/parse isoformat() strings
e.g., it confuses dateutil.parser therefore *strftime('... %Z') with
datetime.timezone should be avoided.*

pytz is *the* module that exposes zoneinfo (*the* timezone database)
to Python. Its tzname() methods (and therefore strftime('%Z')) produce
timezone abbreviations such as 'UTC', 'EST', 'CST' (all %Z examples in
datetime docs) that may be ambiguous (the same abbreviation can be
used by several timezones) and in reverse -- a single timezone can use
several abbreviations for the same purpose (non-DST related). I find
'%Z%z' to be easier to read at a glance compared to %z along (imagine
you look at dozens timestamps at once e.g., in a log collected from
several machines).
msg249211 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2015-08-26 17:19
OK, I guess we can change stdlib datetime.timezone.utc's str() to 'UTC'. Make sure to update both the C and the Python version, and the tests, and the docs. It's going to have to go into 3.6.
msg249627 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2015-09-03 10:41
I left a couple comments on Rietveld.
msg249999 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2015-09-06 17:02
Addressed review comments.
msg250000 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-09-06 17:07
New changeset f904b7eb3981 by Alexander Belopolsky in branch 'default':
Closes Issue#22241: timezone.utc name is now plain 'UTC', not 'UTC-00:00'.
https://hg.python.org/cpython/rev/f904b7eb3981
msg250133 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-09-07 22:15
New changeset ea1bfb64e898 by Victor Stinner in branch 'default':
Issue #22241: Fix a compiler waring
https://hg.python.org/cpython/rev/ea1bfb64e898
History
Date User Action Args
2022-04-11 14:58:07adminsetgithub: 66437
2015-09-07 22:15:43python-devsetmessages: + msg250133
2015-09-06 17:09:43belopolskysetstatus: open -> closed
2015-09-06 17:09:31belopolskysetresolution: fixed
stage: commit review -> resolved
2015-09-06 17:07:36python-devsetnosy: + python-dev
messages: + msg250000
2015-09-06 17:02:27belopolskysetfiles: + issue22241-2.diff

messages: + msg249999
2015-09-03 10:41:35berker.peksagsetnosy: + berker.peksag
messages: + msg249627
2015-09-02 19:33:20belopolskysetstage: patch review -> commit review
2015-08-28 16:08:01belopolskysetfiles: - issue22241.diff
2015-08-28 16:07:51belopolskysetfiles: + issue22241.diff
2015-08-28 15:41:38belopolskysetfiles: + issue22241.diff
keywords: + patch
stage: needs patch -> patch review
2015-08-26 17:20:36belopolskysetassignee: belopolsky
stage: needs patch
type: enhancement -> behavior
versions: + Python 3.6, - Python 3.5
2015-08-26 17:19:15gvanrossumsetnosy: + gvanrossum
messages: + msg249211
2014-08-22 05:01:33akirasetmessages: + msg225644
2014-08-22 00:56:11belopolskysetmessages: + msg225630
2014-08-22 00:40:02belopolskysetnosy: + brett.cannon, mark.dickinson
messages: + msg225626
2014-08-22 00:25:32belopolskysetstatus: closed -> open
superseder: datetime: add ability to parse RFC 3339 dates and times ->
messages: + msg225625

keywords: + easy
resolution: duplicate -> (no value)
2014-08-21 23:45:20akirasetmessages: + msg225623
2014-08-21 14:46:51belopolskysetstatus: open -> closed

superseder: datetime: add ability to parse RFC 3339 dates and times
components: + Extension Modules
versions: - Python 3.4
messages: + msg225609
type: behavior -> enhancement
resolution: duplicate
2014-08-21 13:51:03brett.cannonsetnosy: + belopolsky
2014-08-21 11:35:17akiracreate