GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — time.strptime() with year rollover returns out-of-range tm_yday · Issue #73267 · python/cpython

time.strptime() with year rollover returns out-of-range tm_yday #73267

New issue
Copy link
New issue
Copy link
Open
Open
time.strptime() with year rollover returns out-of-range tm_yday#73267
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

hywl51
mannequin
opened on Dec 27, 2016
Issue body actions
BPO 29081
Nosy @abalkin, @pganssle, @tirkarthi

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 = None
created_at = <Date 2016-12-27.10:05:12.093>
labels = ['3.7', '3.8', 'type-bug', 'library']
title = 'time.strptime() return wrong result'
updated_at = <Date 2018-12-19.18:31:11.934>
user = 'https://bugs.python.org/hywl51'

bugs.python.org fields:

activity = <Date 2018-12-19.18:31:11.934>
actor = 'xtreak'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2016-12-27.10:05:12.093>
creator = 'hywl51'
dependencies = []
files = []
hgrepos = []
issue_num = 29081
keywords = []
message_count = 3.0
messages = ['284080', '284962', '332158']
nosy_count = 5.0
nosy_names = ['belopolsky', 'jeffknupp', 'p-ganssle', 'hywl51', 'xtreak']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue29081'
versions = ['Python 2.7', 'Python 3.7', 'Python 3.8']

Linked PRs

  • gh-73267: Normalize strptime day of year after rollover #158459
  • gh-73267: Fix tm_yday in time.strptime() when a week rolls over a year #161828

Activity

  1. hywl51 commented on Dec 27, 2016

    @hywl51
    hywl51mannequin
    on Dec 27, 2016
    MannequinAuthor
    More actions

    In [1]:import time

    In [2]: time.strptime('2016 52 0', '%Y %W %w')
    Out[2]: time.struct_time(tm_year=2017, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=367, tm_isdst=-1)

    When given the parameters above, the function return the struct_time object with tm_yday=367, that is wrong.

    I test the codes on Python 2.7.11 and 3.5.1, the error is same.

  2. hywl51
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Dec 27, 2016
  3. jeffknupp commented on Jan 8, 2017

    @jeffknupp
    jeffknuppmannequin
    on Jan 8, 2017
    Mannequin
    More actions

    I believe this is working as intended. Remember, the '%w' directive instructs strptime to consider 0 to be Sunday, while tm_wday considers 0 Monday. In 2016, the %W directive means that the first week (week #1) starts on Monday, January 4th. If you go 52 weeks forward from the 4th, you get to Monday, December 26th. By asking for day 0 (%w=0), you want the *Sunday* of the 52nd week *from the first Monday of the year*. Since Monday is day 0 of that week, you want the Sunday that is 6 days from the 26th, or Jan 1, 2017.

    One can certainly argue that tm_yday is documented to return an integer between [0,366] and thus we should never see 367, but it's the correct value given your input. The only other choice would be to raise an exception, which definitely shouldn't happen since the values you entered clearly match the format string spec.

    Perhaps the docs should be updated, but when you consider that %W goes from [0,53], tm_yday can go well past 366 and still represent a semantically valid value.

  4. tirkarthi commented on Dec 19, 2018

    @tirkarthi
    tirkarthi
    on Dec 19, 2018
    Member
    More actions

    This causes the round trip to be a ValueError.

    ./python.exe
    Python 3.8.0a0 (heads/master:1dd035954b, Dec 18 2018, 10:12:34)
    [Clang 7.0.2 (clang-700.1.81)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import time
    >>> value = '2016 51 0'
    >>> format = '%Y %W %w'
    >>> time.strftime(format, time.strptime('2016 51 0', format)) == value
    True
    >>> time.strptime('2016 52 0', format)
    time.struct_time(tm_year=2017, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=367, tm_isdst=-1)
    >>> time.strftime(format, time.strptime('2016 52 0', format)) == value
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: day of year out of range

    On Ruby this causes runtime error

    irb(main):005:0> DateTime::strptime("2016 52 0", "%Y %W %w")
    Traceback (most recent call last):
            3: from /usr/local/bin/irb:11:in `<main>'
            2: from (irb):5
            1: from (irb):5:in `strptime'
    ArgumentError (invalid date)

    With C it returns 2016 00 5 on Mac OS 10.10.4 and 2017 00 0 on Ubuntu

    #include <stdio.h>
    #include <time.h>
    
    int main() {
      struct tm ltm = {0};
      char buf[] = "2016 52 0";
      strptime(buf, "%Y %W %w", &ltm);
      time_t ptm = mktime(&ltm);
    
      printf("tm year %d\n", ltm.tm_year);
      printf("tm yday %d\n", ltm.tm_yday);
      printf("tm wday %d\n", ltm.tm_wday);
    
      char str[50];
      struct tm *tm_info = localtime(&ptm);
      strftime(str, 50, "%Y %W %w", tm_info);
      printf("%s\n", str);
    }

    Output :

    Mac

    tm year 116
    tm yday 0
    tm wday 5
    2016 00 5

    Ubuntu

    tm year 117
    tm yday 0
    tm wday 0
    2017 00 0

  5. tirkarthi
    added
    3.7 (EOL)end of lifeend of life
    3.8 (EOL)end of lifeend of life
    on Dec 19, 2018
  6. ezio-melotti
    transferred this issue fromon Apr 10, 2022
  7. serhiy-storchaka
    added this to Date and time issues 🕰️on May 21, 2022
  8. StanFromIreland commented on Mar 20, 2025

    @StanFromIreland
    StanFromIreland
    on Mar 20, 2025
    Member
    More actions

    It returns what you asked for :-) In the %W format, weeks start on Monday, and week 1 is the first week containing a Monday in that year. Week 52 in 2016 spans from December 26, 2016 to January 1, 2017. When you specify day 0, that's Sunday in this format -- the Sunday of week 52 in 2016 is January 1, 2017.

    Do we want to throw an error like Ruby? I guess we could.

    C seems to differ wildly depending on platform looking at the previous comment and my output...

    tm year 116
    tm yday 365
    tm wday 6
    2016 52 6
    
  9. encukou
    removed
    3.8 (EOL)end of lifeend of life
    3.7 (EOL)end of lifeend of life
    on Mar 21, 2025
  10. pganssle
    changed the title [-]time.strptime() return wrong result[/-] [+]time.strptime() with year rollover returns out-of-range tm_yday[/+] on Sep 27, 2026
  11. pganssle commented on Sep 27, 2026

    @pganssle
    pganssle
    on Sep 27, 2026
    Member
    More actions

    To me it seems like the issue here is consistency.

    • time.strftime cannot, as far as I can tell, cannot produce the string "2016 52 0". This represents 2017-01-01 and strftime will produce "2017 00 0"
    • For backwards rollovers, ambiguous representations are explicitly accepted and normalize to the "canonical" representation: "2015 00 1" and "2014 52 1" both produce the same time_struct with tm_year=2014.
    • The docs explicitly say that the output of tm_yday is in the range [1, 366]

    I think without the second point about backwards rollovers, it would make sense to forbid ambiguous representations, but if we want to be consistent, it would make sense for us to normalize the outputs here.

    In any case, we should not be producing something that is out of spec with the docs and where the output of time.strptime cannot be parsed by time.strftime.

  12. kevinprimeraquecreo-stack
    added this to Project_VKon Oct 18, 2026
  13. github-project-automation
    moved this to In progress in Project_VKon Oct 18, 2026
  14. kevinprimeraquecreo-stack
    added this to Project_VKon Oct 18, 2026
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/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Date and time issues 🕰️
      Status
      No status
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.