Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

time.time() documentation should mention UTC timezone #73212

Closed
vstinner opened this issue Dec 20, 2016 · 13 comments
Closed

time.time() documentation should mention UTC timezone #73212

vstinner opened this issue Dec 20, 2016 · 13 comments
Labels
3.7 (EOL) end of life docs Documentation in the Doc dir

Comments

@vstinner
Copy link
Member

BPO 29026
Nosy @malemburg, @ncoghlan, @abalkin, @vstinner, @Mariatta, @appeltel
PRs
  • bpo-29026: Clarify documentation of time.time #34
  • [3.6] bpo-29026: Clarify documentation of time.time (GH-34) #417
  • [3.5] bpo-29026: Clarify documentation of time.time (GH-34) #418
  • Files
  • 29026_unixtime_v1.patch
  • 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 2017-03-14.21:47:16.282>
    created_at = <Date 2016-12-20.14:24:49.035>
    labels = ['3.7', 'docs']
    title = 'time.time() documentation should mention UTC timezone'
    updated_at = <Date 2017-03-24.23:06:56.435>
    user = 'https://github.com/vstinner'

    bugs.python.org fields:

    activity = <Date 2017-03-24.23:06:56.435>
    actor = 'Mariatta'
    assignee = 'docs@python'
    closed = True
    closed_date = <Date 2017-03-14.21:47:16.282>
    closer = 'vstinner'
    components = ['Documentation']
    creation = <Date 2016-12-20.14:24:49.035>
    creator = 'vstinner'
    dependencies = []
    files = ['46005']
    hgrepos = []
    issue_num = 29026
    keywords = ['patch']
    message_count = 13.0
    messages = ['283690', '283697', '283698', '283845', '283871', '283885', '283887', '287630', '287926', '288904', '289623', '290331', '290332']
    nosy_count = 7.0
    nosy_names = ['lemburg', 'ncoghlan', 'belopolsky', 'vstinner', 'docs@python', 'Mariatta', 'Eric Appelt']
    pr_nums = ['34', '417', '418']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue29026'
    versions = ['Python 3.5', 'Python 3.6', 'Python 3.7']

    @vstinner
    Copy link
    Member Author

    The documentation of the time.time() mentions "epoch" which it doesn't define epoch. If I recall correctly, it's January 1st, 1970 on most OS and most implementations of Python, except of IronPython which uses a different epoch.

    https://docs.python.org/dev/library/time.html#time.time

    Moreover, the timezone is not defined. In practice, it's UTC, so it would be nice to document it.

    I opened this issue because I wasn't sure if time.time() is impacted by DST or not. The answer is no. Maybe the behaviour of time.time() on DST should also be documentation. Hint: it is not impacted by DST since it uses UTC timezone.

    Related question on StackOverflow:
    http://stackoverflow.com/questions/32469318/python-time-time-and-daylight-saving-time

    @vstinner vstinner added the 3.7 (EOL) end of life label Dec 20, 2016
    @vstinner vstinner added the docs Documentation in the Doc dir label Dec 20, 2016
    @malemburg
    Copy link
    Member

    time.time() is not quite UTC on Unix: it usually (*) doesn't include leap seconds, which UTC does.

    The Wikipedia page has a good definition and explanation:

    https://en.wikipedia.org/wiki/Unix_time

    (*) "usually" because POSIX defines time() to not include leap seconds, but on some older or not quite POSIX compliant Unix systems, leap seconds are included.

    @vstinner
    Copy link
    Member Author

    time.time() is not quite UTC on Unix

    Handling time is a complex task, so we should enhance the doc to help users.

    If there are multiple cases, we can list them: "time.time() uses UTC timezone with or without leap seconds". Maybe with a link to https://en.wikipedia.org/wiki/Unix_time ?

    @appeltel
    Copy link
    Mannequin

    appeltel mannequin commented Dec 22, 2016

    I would be happy to work on a documentation patch for this - I'll try to have something up by tomorrow evening if no one beats me to it.

    @appeltel
    Copy link
    Mannequin

    appeltel mannequin commented Dec 23, 2016

    I looked at the documentation and implementation and made a patch to hopefully clarify the issue. I also have some comments:

    • The term "epoch" is actually defined at the top of the page with instructions for how to determine it, i.e. run "gmtime(0)".

    • I added a definition for the term "seconds since the epoch" since this typically means the number of seconds that have elapsed since the epoch excluding leap seconds, although it may vary by platform.

    • I'm a bit uncomfortable with potential confusion regarding Windows, since the Windows epoch begins on 1601, although we adjust it to 1970:

      cpython/Python/pytime.c

      Lines 536 to 539 in d739274

      /* 11,644,473,600,000,000,000: number of nanoseconds between
      the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
      days). */
      *tp = large.QuadPart * 100 - 11644473600000000000;
      I didn't add a note in the patch as I am not a windows developer, but I wonder if there could be some confusion.

    • Even though its redundant with the top of the page, I added specific clarification to time.time() as it appears that most readers are going to navigate to that anchor specifically and not read the discussion of what we mean by "epoch" above.

    • I need to test my assertion that Windows does not count leap seconds. I'm pretty sure but not 100% confident that I am correct from what I read, but I need to find someone with a windows machine tomorrow and actually check it. The windows documentation for the FILETIME structure suggests that leap seconds might be counted - https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx - but I think this is just an oversight in the documentation.

    • Just out of personal curiousity does anyone have an example of a legacy UNIX system that counts leap seconds in the epoch? This seems tricky to do as I would presume that the OS would need some table that would be updated whenever the astronomers declare a new leap second.

    @vstinner
    Copy link
    Member Author

    Another suggestion: mention localtime() and gmtime() in time() documentation to explain how to convert such timestamp to a more common date format.

    @appeltel
    Copy link
    Mannequin

    appeltel mannequin commented Dec 23, 2016

    I had some checks performed on a Windows platform using the following snippet:

    # valid for 2016
    import time
    def check():
        t = time.gmtime()
        print(46*86400*365 + 11*86400 + (t.tm_yday-1)*86400 + t.tm_hour*3600 + t.tm_min*60 + t.tm_sec)
        print(time.time())
        print(time.gmtime(0))
    check()

    This ensures that the time since the epoch is counted excluding leap seconds if the first two lines of output are approximately the same (to nearest second), and finally that the epoch is the Unix epoch.

    On Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32 I see:

    1482502941
    1482502941.9609053
    time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)

    Unless there is major variation among windows versions on how FILETIMEs are calculated and the results of basic system calls, I feel fairly confident now that the calculation of time since the epoch in CPython is the same on Windows as it is in POSIX-compliant platforms.

    @appeltel
    Copy link
    Mannequin

    appeltel mannequin commented Feb 12, 2017

    As we have moved to GitHub and mandatory reviews with Pull Requests, I have created a new patch in PR#34 which incorporates Victor's suggestions.

    @vstinner
    Copy link
    Member Author

    New changeset 23557d5 by Victor Stinner in branch 'master':
    bpo-29026: Clarify documentation of time.time (#34)
    23557d5

    @Mariatta
    Copy link
    Member

    Mariatta commented Mar 3, 2017

    Hi, does this need backport to 2.7?
    I'm getting a lot of conflicts while trying to do that... Not sure how to proceed.

    @vstinner
    Copy link
    Member Author

    Mariatta: "Hi, does this need backport to 2.7? I'm getting a lot of conflicts while trying to do that... Not sure how to proceed."

    I think it's ok to leave Python 2.7 doc unchanged. It's only a minor doc enhancement, the 2.7 doc is still correct. I close the issue.

    @Mariatta
    Copy link
    Member

    New changeset 8c851fa by Mariatta in branch '3.5':
    bpo-29026: Clarify documentation of time.time (GH-34) (GH-418)
    8c851fa

    @Mariatta
    Copy link
    Member

    New changeset b8f5d07 by Mariatta in branch '3.6':
    bpo-29026: Clarify documentation of time.time (GH-34) (GH-417)
    b8f5d07

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life docs Documentation in the Doc dir
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants