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.

Author dlenski
Recipients alex.gronholm, ammar2, belopolsky, dlenski, hongweipeng, jwilk, mehaase, p-ganssle, rdb
Date 2021-01-20.00:32:14
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1611102735.02.0.114122304478.issue35829@roundup.psfhosted.org>
In-reply-to
Content
Like many others here, I've run into this issue because I'm trying to parse timestamps from JSON.

(Specifically, I'm trying to parse timestamps from JSON serialization of Java POJOs and/or Kotlin data classes, as serialized by the Jackson serialization library for JVM languages, in conjunction with JavaTimeModule.
https://fasterxml.github.io/jackson-modules-java8/javadoc/datetime/2.9/com/fasterxml/jackson/datatype/jsr310/JavaTimeModule.html)

In order to "be lenient in what I accept" (adhering to the robustness principal), I need to add a special case for deserialization of strings ending with 'Z'. This gets pretty tricky and pretty subtle quickly.

Here is my Python 3.7+ code path (the strptime-based code path for earlier versions is much, much uglier).

    from numbers import Number
    from datetime import datetime, timezone
    def number_or_iso8601_to_dt(ts, t=datetime):
        if isinstance(ts, Number):
            return datetime.utcfromtimestamp(ts).replace(tzinfo=timezone.utc)
        elif ts.endswith('Z'):
            # This is not strictly correct, since it would accept a string with
            # two timezone specifications (e.g. ending with +01:00Z) and 
            # silently pass that erroneous representation:
            #
            # return datetime.fromisoformat(ts[:-1]).replace(tzinfo=timezone.utc)
            #
            # This version is better:
            d = datetime.fromisoformat(ts[:-1])
            if d.tzinfo is not None:
                raise ValueError(f"time data '{ts}' contains multiple timezone suffixes")
            return d.replace(tzinfo=timezone.utc)
        else:
            return datetime.fromisoformat(ts)

I don't really understand why .fromisoformat() must be *strictly* the inverse of .isoformat(). As @mehaase points out, the transformation isn't strictly reversible as is.

There are other functions where the Python standard library has special-cased options for extremely common use cases. For example, `str.split(None)`, which is certainly not the inverse of the non-existent `None.join()`.

This feels to me like a case where the standard library should simply just accept an extremely-common real-world variant in the interests of interoperability.

I would also be in favor of @p-ganssle's proposal (3), wherein `datetime.isoformat` would also output the 'Z' suffix for the UTC timezone.
History
Date User Action Args
2021-01-20 00:32:15dlenskisetrecipients: + dlenski, belopolsky, jwilk, alex.gronholm, rdb, ammar2, mehaase, p-ganssle, hongweipeng
2021-01-20 00:32:15dlenskisetmessageid: <1611102735.02.0.114122304478.issue35829@roundup.psfhosted.org>
2021-01-20 00:32:15dlenskilinkissue35829 messages
2021-01-20 00:32:14dlenskicreate