Skip to content

datetime.datetime should have a timestamp() method #59113

Closed

Description

@djc
BPO 14908
Nosy @malemburg, @tim-one, @warsaw, @jribbens, @amauryfa, @mdickinson, @abalkin, @pitrou, @catlee, @vstinner, @djc, @bitdancer
Superseder
  • bpo-2736: datetime needs an "epoch" method
  • Files
  • issue14908.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/abalkin'
    closed_at = <Date 2012-06-08.16:38:21.223>
    created_at = <Date 2012-05-25.08:53:19.672>
    labels = ['type-feature', 'library']
    title = 'datetime.datetime should have a timestamp() method'
    updated_at = <Date 2012-06-08.16:38:21.222>
    user = 'https://github.com/djc'

    bugs.python.org fields:

    activity = <Date 2012-06-08.16:38:21.222>
    actor = 'belopolsky'
    assignee = 'belopolsky'
    closed = True
    closed_date = <Date 2012-06-08.16:38:21.223>
    closer = 'belopolsky'
    components = ['Library (Lib)']
    creation = <Date 2012-05-25.08:53:19.672>
    creator = 'djc'
    dependencies = []
    files = ['25865']
    hgrepos = []
    issue_num = 14908
    keywords = ['patch']
    message_count = 16.0
    messages = ['161558', '161568', '162263', '162267', '162268', '162269', '162270', '162278', '162280', '162282', '162288', '162316', '162452', '162483', '162531', '162534']
    nosy_count = 26.0
    nosy_names = ['lemburg', 'tim.peters', 'ping', 'barry', 'jribbens', 'guettli', 'amaury.forgeotdarc', 'mark.dickinson', 'davidfraser', 'belopolsky', 'pitrou', 'andersjm', 'catlee', 'vstinner', 'tomster', 'werneck', 'djc', 'hodgestar', 'Neil Muller', 'erik.stephens', 'steve.roberts', 'r.david.murray', 'vivanov', 'python-dev', 'Jay.Taylor', 'Alexandre.Zani']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '2736'
    type = 'enhancement'
    url = 'https://bugs.python.org/issue14908'
    versions = ['Python 3.3']

    Activity

    1. djc commented on May 25, 2012

      @djc
      ContributorAuthor

      There's datetime.fromtimestamp() and datetime.timetuple(), but no datetime.timestamp(). It should be possible to round-trip a UNIX timestamp through a datetime.datetime.

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on May 25, 2012
    3. AlexanderBelopolsky commented on May 25, 2012

      AlexanderBelopolskymannequin
      Mannequin
    4. warsaw commented on Jun 4, 2012

      @warsaw
      Member

      I completely agree. As easy (but obscure) as it is, it seems quite silly to have to go through time.mktime(dt.timetuple())

    5. abalkin commented on Jun 4, 2012

      @abalkin
      Member

      Barry,

      Did you review the long discussion under bpo-2736? Specifically, please note the part about mxDateTime, ticks() and gmticks(). I am -0 on adding ticks() and gmticks() and as far as I can tell no one has implemented these methods for datetime without introducing some subtle bugs.

      I also suspect that those who ask for a timestamp() method expect that it will do more than

      EPOCH = datetime(1970, 1, 1)
      def timestamp(t):
            return (t - EPOCH).total_seconds()

      For example, account for leap seconds or magically guess the DST offset. If we introduce a method that implements the code above, we have to prepare to explain why it does not do those things.

      If instead we introduce a shortcut for time.mktime(t.timetuple()), we will have to deal with the fact that mktime() behaves differently on different systems.

    6. warsaw commented on Jun 4, 2012

      @warsaw
      Member

      On Jun 04, 2012, at 03:45 PM, Alexander Belopolsky wrote:

      Did you review the long discussion under bpo-2736? Specifically, please
      note the part about mxDateTime, ticks() and gmticks(). I am -0 on adding
      ticks() and gmticks() and as far as I can tell no one has implemented these
      methods for datetime without introducing some subtle bugs.

      I skimmed it, but I don't have time to read the whole bug. I'll note that
      I've recently had to convert a bunch of code from using mxDateTime to
      datetime+time, for the only reason that we had to support Python 3 and mxDT
      isn't yet ported.

      I also suspect that those who ask for a timestamp() method expect that it
      will do more than

      EPOCH = datetime(1970, 1, 1)
      def timestamp(t):
      return (t - EPOCH).total_seconds()

      Not really.

      For example, account for leap seconds or magically guess the DST offset. If
      we introduce a method that implements the code above, we have to prepare to
      explain why it does not do those things.

      That's fine, explain away!

      If instead we introduce a shortcut for time.mktime(t.timetuple()), we will
      have to deal with the fact that mktime() behaves differently on different
      systems.

      Not really. If developers even care, they will know that the epoch is
      different for different systems. We don't have to deal with it, we just have
      to mention it. Let them use more verbose "correct" code if they care.

      Seriously, we should not over-engineer this. It's purely a more discoverable
      convenience and I think implementing the moral equivalent to
      time.mktime(t.timetuple()) is exactly the right thing to do.

    7. AlexanderBelopolsky commented on Jun 4, 2012

      AlexanderBelopolskymannequin
      Mannequin

      On Mon, Jun 4, 2012 at 11:57 AM, Barry A. Warsaw <report@bugs.python.org> wrote:

      I've recently had to convert a bunch of code from using mxDateTime to
      datetime+time,

      That's a valuable experience. How big of a deal was the lack of
      .ticks() and .gmticks()? How did you work around it?

    8. warsaw commented on Jun 4, 2012

      @warsaw
      Member

      On Jun 04, 2012, at 04:03 PM, Alexander Belopolsky wrote:

      That's a valuable experience. How big of a deal was the lack of
      .ticks() and .gmticks()? How did you work around it?

      It was *much* less of an issue than all the magic date format parsing that
      mxDT supports. That's actually something that I think is a more serious
      deficiency, since .strptime() is pretty limited (e.g. how would you parse ISO
      8601 dates both with and without the 'T'?). A Python 3 compatible time format
      parser would make for a very nice separate library (PyPI) and/or addition to
      the stdlib (eventually).

      FWIW, here's the changeset.

      http://bazaar.launchpad.net/~gwibber-committers/gwibber/trunk/revision/1354

    9. AlexandreZani commented on Jun 4, 2012

      AlexandreZanimannequin
      Mannequin

      I think the easiest and most intuitive approach is to simply define timestamp() as being the reverse of fromtimestamp(). Don't worry about leap seconds and all that stuff.

      If non-1970 epochs are a concern, this could be renamed to posix_timestamp or some such with perhaps a generic timestamp function that takes both a time and epoch.

      But let's not let such a useful function not happen just because it won't solve everyone's problem.

    10. AlexanderBelopolsky commented on Jun 4, 2012

      AlexanderBelopolskymannequin
      Mannequin

      On Mon, Jun 4, 2012 at 1:33 PM, Alexandre Zani <report@bugs.python.org> wrote:

      I think the easiest and most intuitive approach is to simply define timestamp()
      as being the reverse of fromtimestamp().

      I would like to invite everyone to review the discussion leading to
      closing of bpo-2736. We cannot implement "the reverse of
      fromtimestamp()" because fromtimestamp() is not reversible in presence
      of DST and because float cannot represent all values that datetime
      supports. Both issues can be resolved, but I did not see any solution
      that I would call intuitive.

      Is anyone motivated enough to port mxDT's ticks() method to datetime?
      I don't think we need to reinvent the wheel.

    11. AlexandreZani commented on Jun 4, 2012

      AlexandreZanimannequin
      Mannequin

      I'm still reading through the issue you mentioned. (It's a painful read I have to admit) One major obstacle seems to be that during the DST switch over, an hour gets repeated and so the datetime object is ambiguous. (are you on the first or second hour?) I would argue that it isn't a problem that this function needs to solve. The ambiguity isn't tied to the conversion. It's tied to the datetime object itself.

      Let's add an optional parameter to specify the DST status, doc the pitfall and not worry overmuch about it.

      Side note: Let me know if I misunderstood Alexander, but if I didn't this should be documented with the datetime object. Based upon my understanding, the datetime object is a bad choice if you care about that ambiguity. That's not really clear.

    12. AlexanderBelopolsky commented on Jun 4, 2012

      AlexanderBelopolskymannequin
      Mannequin

      On Mon, Jun 4, 2012 at 3:21 PM, Alexandre Zani <report@bugs.python.org> wrote:

      Let me know if I misunderstood Alexander, but if I didn't this should be documented with
      the datetime object. Based upon my understanding, the datetime object is a bad choice
      if you care about that ambiguity. That's not really clear.

      The datetime object is neither good nor bad if you want to deal with
      the DST ambiguity. If you want to store times as local time, the best
      practice is to include the UTC offset. The datetime module now
      provides the facilities to do so. If you neglect the timezone and
      deal with naive datetime objects instead, you should probably avoid
      mixing it with POSIX timestamps in the same application.

      Here is an example where naive datetime is quite appropriate: a
      timekeeping application for a small business with a single location.
      If you need to generate opening hours for a given week,
      [datetime(y,m,d, 9, 0) + datetime(i) for i in range(5)] is an adequate
      solution, but if you compare it to [datetime.fromtimestamp(x +
      24*3600*i) for i in range(5)], you may be off by one hour if your week
      spans the DST change.

      In most applications, however, keeping local time without UTC offset
      is a bad choice. POSIX's timestamp only advantage is that it does no
      allow keeping local time at all.

    13. abalkin commented on Jun 5, 2012

      @abalkin
      Member

      Barry,

      I looked at your changeset at http://bazaar.launchpad.net/~gwibber-committers/gwibber/trunk/revision/1354 and at the specification at http://developers.facebook.com/docs/reference/api/event/.

      Am I correct that you are parsing "string containing an ISO-8601 formatted date/time or a UNIX timestamp; if it contains a time zone (not recommended), it will be converted to Pacific time before being stored and displayed"?

      If so, it looks like converting input to POSIX timestamps is the wrong thing to do because users who specify naive time expect it to be displayed without conversion.

      The way I read the specs, a better implementation would store input in naive datetime objects, converting UNIX timestamps or TZ-aware strings to Pacific timezone.

    14. self-assigned this
      on Jun 5, 2012
    15. abalkin commented on Jun 7, 2012

      @abalkin
      Member

      I think the attached patch implements what was agreed to on python-dev. We need more tests, particularly around DST change. I tested the patch on OSX, but I am interested to hear feedback from users of other OSes.

    16. abalkin commented on Jun 7, 2012

      @abalkin
      Member

      Updated patch adds a few more tests and improves error handling in C implementation.

    17. abalkin commented on Jun 8, 2012

      @abalkin
      Member

      Added ReST documentation. Will commit soon. Merging nosy list from bpo-2736.

    18. abalkin commented on Jun 8, 2012

      @abalkin
      Member

      I associated my commit with bpo-2736 by mistake, but it is probably a good thing because that issue contains a longer history.

      Closing this as a duplicate.

    19. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions