1. 30

    1. 23

      The problem is that naïve datetimes and TZ aware datetimes are represented by a single type in the first place. They should have been separate types and not intermixed.

    2. 13

      So why would you want to work with naive datetimes in the first place?

      The reason TFA gives for using naive datetimes isn’t good IMO. Naive datetimes are an extremely specialized type. You only need them if you are making human friendly repeating events. If you have a meeting every Monday at 9am, that’s going to shift during DST, so it needs to be stored in a naive datetime.

      In every other case, for example an app that does everything in local time, you can just store a TZ aware datetime and do a conversion at display time.

      1. 6

        Totally agree! Even for calendars, yeah using simple UTC offsets will hit DST issues for recurring events, but the answer is something like iCal Date-Time Form #3, not naive datetimes:

        Floating time SHOULD only be used where that is the reasonable behavior.

        In most cases, a fixed time is desired. To properly communicate a fixed time in a property value, either UTC time or local time with time zone reference MUST be specified.



        The date and local time with reference to time zone information is identified by the use the “TZID” property parameter to reference the appropriate time zone definition. “TZID” is discussed in detail in Section 3.2.19. For example, the following represents 2:00 A.M. in New York on January 19, 1998:


        If, based on the definition of the referenced time zone, the local time described occurs more than once (when changing from daylight to standard time), the DATE-TIME value refers to the first occurrence of the referenced time. Thus, TZID=America/New_York:20071104T013000 indicates November 4, 2007 at 1:30 A.M. EDT (UTC-04:00). If the local time described does not occur (when changing from standard to daylight time), the DATE-TIME value is interpreted using the UTC offset before the gap in local times. Thus, TZID=America/New_York:20070311T023000 indicates March 11, 2007 at 3:30 A.M. EDT (UTC-04:00), one hour after 1:30 A.M. EST (UTC-05:00).

        RFC 5545 § 3.3.5

        If that 9am Monday meeting is a call between the London and New York offices, for example, or a cross-country flight, or Monday Night Football, you’ll want time zones.

    3. 13

      If you ask me, I think the names of these functions are misleading. A function that is called utcnow() should be expected to return UTC datetimes, as implied by the name.

      You don’t say. Face, meet palm.

    4. 8

      the timestamp() method that returns the incorrect UNIX time in the example was introduced in Python 3.3 and nothing similar appears to have existed back in Python 2 times.

      This boggles the mind.

      1. 5

        It existed, but by way of a struct_time and it was in the lower level time module (and a little awkward to use, inheriting a lot of legacy from unix/libc time stuff.)

        timestamp = time.mktime(datetime.now().timetuple())

        But mktime was explicitly defined as the inverse of localtime not gmtime, which I suspect is where the behavior of timestamp comes from.

        1. 2

          Yes, that definition of mktime() comes from the C world. The inverse of gmtime() is timegm() but annoyingly timegm() is still not blessed by the standards even though it has been around for decades.

    5. 2

      Also, if you have to deal with timezones in Python, use pendulum (https://pendulum.eustace.io)

      1. 1

        Wasn’t aware of this. It looks great, thanks!

        1. 2

          Also sometimes useful is this library which does not actually implement any date/time logic but does provide drop-in wrappers for the datetime module’s contents, with the specific goal of making dates and datetimes, and the timezone-aware and timezone-naïve versions of them, all be different and incompatible-to-a-type-checker types. So, for example, datetype.AwareDateTime is a separate type from, and type-checks as incompatible with, datetype.NaiveDateTime and datetype.Date.

    6. 2

      This does not count as OOWTDI, IMO.