Skip to content

datetime module missing some important methods #44656

Closed

Description

@jribbens
mannequin
BPO 1673409
Nosy @tim-one, @smontanaro, @jribbens, @srittau, @amauryfa, @mdickinson, @pitrou, @catlee, @vstinner
Superseder
  • bpo-2736: datetime needs an "epoch" method
  • Files
  • timedelta.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 = None
    closed_at = <Date 2010-04-21.18:03:30.573>
    created_at = <Date 2007-03-04.11:59:05.000>
    labels = ['type-feature', 'library']
    title = 'datetime module missing some important methods'
    updated_at = <Date 2010-04-21.18:52:38.900>
    user = 'https://github.com/jribbens'

    bugs.python.org fields:

    activity = <Date 2010-04-21.18:52:38.900>
    actor = 'mark.dickinson'
    assignee = 'none'
    closed = True
    closed_date = <Date 2010-04-21.18:03:30.573>
    closer = 'mark.dickinson'
    components = ['Library (Lib)']
    creation = <Date 2007-03-04.11:59:05.000>
    creator = 'jribbens'
    dependencies = []
    files = ['8837']
    hgrepos = []
    issue_num = 1673409
    keywords = ['patch']
    message_count = 39.0
    messages = ['55042', '55043', '55573', '55585', '55586', '57050', '57051', '57052', '57057', '57058', '57059', '57078', '57080', '58007', '58009', '58068', '69516', '75408', '75410', '75411', '75423', '75426', '75724', '75754', '75859', '75860', '75863', '77859', '77861', '77862', '77865', '77867', '77868', '77869', '77871', '103868', '103874', '103878', '103888']
    nosy_count = 14.0
    nosy_names = ['tim.peters', 'skip.montanaro', 'jribbens', 'srittau', 'guettli', 'amaury.forgeotdarc', 'mark.dickinson', 'pitrou', 'catlee', 'vstinner', 'tomster', 'erik.stephens', 'steve.roberts', 'Alexander.Belopolsky']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = None
    status = 'closed'
    superseder = '2736'
    type = 'enhancement'
    url = 'https://bugs.python.org/issue1673409'
    versions = ['Python 2.7']

    Activity

    1. jribbens commented on Mar 4, 2007

      jribbensmannequin
      MannequinAuthor

      The datetime module is missing some important methods for interacting with timestamps (i.e. seconds since 1970-01-01T00:00:00).

      There are methods to convert from a timestamp, i.e. date.fromtimestamp and datetime.fromtimestamp, but there are no methods to convert back.

      In addition, timedelta has no method for returning the number of seconds it represents (i.e. days*86400+seconds+microseconds/1000000).

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Mar 4, 2007
    3. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Mar 4, 2007
    4. guettli commented on Mar 22, 2007

      guettlimannequin
      Mannequin

      Yes, that's true.

    5. smontanaro commented on Sep 2, 2007

      @smontanaro
      Contributor

      There is no datetime.totimestamp because the range
      of time represented by a datetime object far
      exceeds the range of a normal int-based Unix
      timestamp (roughly 1970-2038). Datetime objects
      before the start of the Unix epoch would be
      represented by negative numbers. As far as I
      know, the common Unix library functions which
      accept epoch times wouldn't know what to do
      with a negative number.

      That said, you stated these missing methods
      were important. Can you offer some use
      cases which would support that contention?
      I personally don't think a argument for
      symmetry would be a convincing use case and
      that's the only one I can think of.

    6. jribbens commented on Sep 2, 2007

      jribbensmannequin
      MannequinAuthor

      Almost everything you just said about time_t is wrong. time_t is signed,
      and always has been (otherwise the 'end of time' for 32-bit time_t would
      be 2106, not 2038). Also, time_t does not end at 2038 because nothing
      says it must be 32 bits. Also, Python has 'long integers' which do not
      overflow.

      Also, I don't understand what you mean about use cases. The "use case"
      is "dealing with anything which expects standard Unix time_t, for
      example the Python standard library". The use case I have personally is
      the program I was working on when I encountered the problem described in
      this bug report. Also I think symmetry is a darn good argument. Why does
      fromtimestamp exist if, as you claim, nobody uses time_t?

    7. smontanaro commented on Sep 2, 2007

      @smontanaro
      Contributor

      Jon> Almost everything you just said about time_t is wrong. time_t is
      Jon> signed, and always has been (otherwise the 'end of time' for 32-bit
      Jon> time_t would be 2106, not 2038). Also, time_t does not end at 2038
      Jon> because nothing says it must be 32 bits. Also, Python has 'long
      Jon> integers' which do not overflow.

      My apologies about goofing up on the signedness of time_t. What are you
      going to do with a long integer that you can't do with a datetime object?
      You clearly can't pass it directly to any Unix library functions which
      expect time_t. Converting it can overflow.

      Jon> Also, I don't understand what you mean about use cases. The "use
      Jon> case" is "dealing with anything which expects standard Unix time_t,
      Jon> for example the Python standard library". The use case I have
      Jon> personally is the program I was working on when I encountered the
      Jon> problem described in this bug report. Also I think symmetry is a
      Jon> darn good argument. Why does fromtimestamp exist if, as you claim,
      Jon> nobody uses time_t?
      

      What should datetime.datetime(9999, 1, 1).totimestamp() return? How would
      you pass it to something which accepts a time_t? The fromtimestamp
      functions work simply because the range of time_t is a proper subset of the
      range of Python's datetime objects. Symmetry gets you little. In
      situations where you need Unix timestamps and you know your datetime objects
      are within the bounds representable by time_t, you can define a convenience
      function:

          def totimestamp(dt):
              return time.mktime(dt.timetuple()) + dt.microsecond/1e6

      This will, of course, fail if the year is too big or too small (and will
      fail in platform-dependent ways if the underlying platform's range of
      representable dates has different bounds than Unix does). Doing it without
      resorting to calling time.mktime is also nontrivial. Under the covers the
      datetime module currently uses platform functions to get time information
      anyway. It doesn't do a lot of low-level time arithmethic itself.
      Implementing fromtimestamp would require a fair amount of effort unless you
      were willing to punt and just raise OverflowError for dates outside the
      system's range.

      Skip

    8. tomster commented on Nov 2, 2007

      tomstermannequin
      Mannequin

      unless I'm missing something important this will do the trick quite
      nicely:

          >>> from datetime import datetime
          >>> datetime(2007, 12, 24, 20, 0).strftime("%s")
          '1198522800'

      For most imaginable use cases, where an epoch style time stamp is
      required this should be enough.

      HTH,

      Tom

    9. smontanaro commented on Nov 2, 2007

      @smontanaro
      Contributor

      Tom> unless I'm missing something important this will do the trick quite
      Tom> nicely:

          >>>> from datetime import datetime
          >>>> datetime(2007, 12, 24, 20, 0).strftime("%s")
          Tom>     '1198522800'
      Tom> For most imaginable use cases, where an epoch style time stamp is
      Tom> required this should be enough.
      

      No fractions of a second...

      Skip

    10. jribbens commented on Nov 2, 2007

      jribbensmannequin
      MannequinAuthor

      No fractions of a second...

      If we're expecting floating-point, then everything you said earlier
      about the limitations of ints was a bit redundant ;-)

    11. smontanaro commented on Nov 2, 2007

      @smontanaro
      Contributor

      > No fractions of a second...

      Jon> If we're expecting floating-point, then everything you said earlier
      Jon> about the limitations of ints was a bit redundant ;-)
      

      Yes, sorry. I responded to the mail without going back and reviewing the
      entire thread. (It's been a couple months.) Note however that my example
      to_timestamp() function converts the microseconds field to seconds and
      include them in the result.

      So, are we concluding that nothing needs to be added to the datetime module?

      Skip

    12. 20 remaining items

    13. srittau commented on Dec 15, 2008

      srittaumannequin
      Mannequin

      A timedelta.toseconds method (or equivalent) makes no sense. The number
      of seconds in a day is not fixed (due to leap seconds) and relying on
      such a method would introduce subtle bugs. The only way to find out the
      number of seconds in a range of dates is if you have a concrete date range.

    14. vstinner commented on Dec 15, 2008

      @vstinner
      Member

      The number of seconds in a day is not fixed (due to leap seconds)

      POSIX timestamp doesn't count leap seconds. It looks like the datetime
      module is not aware of the leap seconds:

      >>> print datetime.datetime(2006, 1, 1) - datetime.datetime(2005, 12, 
      31)
      1 day, 0:00:00

      About my method: I finally prefer datetime/datetime or
      datetime//datetime instead of a toseconds() method. And to convert a
      timestamp to a timestamp: see my patch attached to issue bpo-2736.

    15. vstinner commented on Dec 15, 2008

      @vstinner
      Member

      I removed my ".toseconds() method" patch because I prefer division.
      See issue bpo-2706 for divison, divmod, etc.

    16. pitrou commented on Dec 15, 2008

      @pitrou
      Member

      I also think totimestamp() on datetime objects would be useful, I've
      missed it myself a couple of times. The return value should be similar
      to that of time.time(), i.e. a float.

    17. srittau commented on Dec 15, 2008

      srittaumannequin
      Mannequin

      Leap second handling is usually configurable. Default on Debian Linux
      (but similar on RHEL and SuSE):

      >>> int(date(1994,1,1).strftime("%s")) - int(date(1993,1,1).strftime("%s"))
      31536000

      After doing "cp /usr/share/zoneinfo/right/Europe/Berlin /etc/localtime":

      >>> int(date(1994,1,1).strftime("%s")) - int(date(1993,1,1).strftime("%s"))
      31536001

      Also, NTP servers usually get this right. I don't think, Python should
      promote a wrong date handling by default, even if it's convenient.

    18. vstinner commented on Dec 15, 2008

      @vstinner
      Member

      (...) totimestamp() (...) return value should be similar
      to that of time.time(), i.e. a float

      float is a source of many problems (rounding problems), especially for
      huge values: float is unable to store correctly microseconds for big
      values: see msg75426. A simple tuple (int, int) is simple and there is
      no rounding/float limit.

    19. pitrou commented on Dec 15, 2008

      @pitrou
      Member

      What you say is "with 99500 days or more, the microsecond error is
      bigger than 90%". It means that with epoch starting at 1970, you can
      still return timestamps with a 1-2 microsecond accuracy for the year 2242.

      Additional precision would be overkill.

    20. jribbens commented on Dec 15, 2008

      jribbensmannequin
      MannequinAuthor

      A timedelta.toseconds method (or equivalent) makes no sense.
      The number of seconds in a day is not fixed (due to leap seconds) and
      relying on such a method would introduce subtle bugs.

      You are misunderstanding what timedelta is. It is a fixed-length period
      of time. It is stored as a number of (24x3600-second) days, seconds and
      microseconds. There is no "start date" or "end date", so the concept of
      leap seconds just does not apply.

    21. AlexanderBelopolsky commented on Apr 21, 2010

      AlexanderBelopolskymannequin
      Mannequin

      With bpo-2706 accepted, I think this issue can now be rejected because proposed td.tosecs() can now be spelled simply as td/timedelta(seconds=1).

      The other RFE for a totimestamp() method is a duplicate of bpo-2736.

    22. mdickinson commented on Apr 21, 2010

      @mdickinson
      Member

      Closing this as a duplicate of bpo-2736, as suggested. I'll combine the nosy lists.

      (BTW, as well as the newly introduced division methods, td.tosecs already exists, except that it's spelt td.total_seconds.)

    23. AlexanderBelopolsky commented on Apr 21, 2010

      AlexanderBelopolskymannequin
      Mannequin

      On Wed, Apr 21, 2010 at 2:03 PM, Mark Dickinson <report@bugs.python.org> wrote:
      ..

      (BTW, as well as the newly introduced division methods, td.tosecs already exists, except that it's spelt td.total_seconds.)

      Aggrrr! How did that slip in? :-)

      86399999913600.0

      Shouldn't td.total_seconds() return Decimal? Maybe in py4k ...

    24. mdickinson commented on Apr 21, 2010

      @mdickinson
      Member

      Aggrrr! How did that slip in? :-)

      Blame Antoine. :) (See bpo-5788 and revision 76529.)

      Shouldn't td.total_seconds() return Decimal? Maybe in py4k ...

      Yes, that would have been nice.

      I'm not sure that the Decimal type is well-established enough yet that it's okay to return Decimal instances from random unrelated modules, though. Maybe someday.

    25. 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

    No one assigned

      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