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

Functions in time module should support year < 1900 when accept2dyear = 0 #55036

Closed
abalkin opened this issue Jan 4, 2011 · 12 comments
Closed
Assignees
Labels
extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error

Comments

@abalkin
Copy link
Member

abalkin commented Jan 4, 2011

BPO 10827
Nosy @birkenfeld, @abalkin, @vstinner, @Trundle
Superseder
  • bpo-1777412: datetime.strftime dislikes years before 1900
  • Files
  • issue10827.diff
  • issue10827a.diff
  • issue10827b.diff
  • issue10827c.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 2011-01-07.20:41:52.245>
    created_at = <Date 2011-01-04.16:48:19.610>
    labels = ['extension-modules', 'type-bug']
    title = 'Functions in time module should support year < 1900 when accept2dyear = 0'
    updated_at = <Date 2011-01-08.16:38:02.921>
    user = 'https://github.com/abalkin'

    bugs.python.org fields:

    activity = <Date 2011-01-08.16:38:02.921>
    actor = 'vstinner'
    assignee = 'belopolsky'
    closed = True
    closed_date = <Date 2011-01-07.20:41:52.245>
    closer = 'belopolsky'
    components = ['Extension Modules']
    creation = <Date 2011-01-04.16:48:19.610>
    creator = 'belopolsky'
    dependencies = []
    files = ['20260', '20261', '20275', '20295']
    hgrepos = []
    issue_num = 10827
    keywords = ['patch']
    message_count = 12.0
    messages = ['125339', '125343', '125345', '125349', '125353', '125356', '125432', '125609', '125707', '125708', '125714', '125791']
    nosy_count = 5.0
    nosy_names = ['georg.brandl', 'belopolsky', 'vstinner', 'Trundle', 'SilentGhost']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = '1777412'
    type = 'behavior'
    url = 'https://bugs.python.org/issue10827'
    versions = ['Python 3.2']

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 4, 2011

    """

    http://docs.python.org/library/time.html#time-y2kissues
    "Values 100–1899 are always illegal."

    Why are these values illegal? The GNU libc accepts year in [1900-2^31; 2^31-1] (tm_year in [-2147483648; 2147481747]). If time.accept2dyear=False, we should at least accept years in [1; 9999]. The system libc would raise an error (return NULL) if it doesn't know how to format years older than 1900.
    """ -- Victor Stinner at msg12516

    @abalkin abalkin self-assigned this Jan 4, 2011
    @abalkin abalkin added extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error labels Jan 4, 2011
    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 4, 2011

    The system libc would raise an error (return NULL) if it doesn't know
    how to format years older than 1900.

    As experience with asctime has shown, system libc can do whatever it pleases with out of range values including overrunning a fixed size buffer, returning non-sensical values etc. However, now that we have control over asctime implemetation (see bpo-8013), I don't see any problem in supporting at least year > 999 in time.asctime and time.ctime. (Supporting full [1900-maxint, maxint] range would involve a decision on whether to fill < 4-digit values.) Some extra care would be required for time.strftime() because some systems may not support year < 1900 as well as others.

    It looks like POSIX does not make any strong mandates:

    "tm_year is a signed value; therefore, years before 1900 may be represented."

    http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html

    and regardless of what POSIX or C standards have to say, this is the area where systems a known to have spotty compliance records.

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 4, 2011

    I am attaching a patch. While working on the patch, I noticed that although time.accept2dyear is documented as boolean, the current code expects int and treats any non-int including True as 0:

    >>> time.accept2dyear = True; time.asctime((99,) + (0,)*8)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: year >= 1900 required
    
    >>> time.accept2dyear = 1; time.asctime((99,) + (0,)*8)
    'Mon Jan  1 00:00:00 1999'

    This is clearly a bug. (Although Y2K note contradicts time.accept2dyear documentation.)

    Supporting year < 1900 would be a feature in my view, but I agree with SilentGhost that once we extended support to 5+ digit years, it is odd to keep year >= 1900 restriction.

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 4, 2011

    On Tue, Jan 4, 2011 at 1:30 PM, Alexander Belopolsky
    <report@bugs.python.org> wrote:
    ..

    This is clearly a bug.  (Although Y2K note contradicts time.accept2dyear documentation.)

    PyObject_IsTrue() may fail - this is probably the reason for the
    current odd logic. My patch should be fixed top respect that, but I
    still maintain that time.accept2dyear = True should work as expected.
    (Would also make True the default rather 1.)

    @birkenfeld
    Copy link
    Member

    But if it fails, why not just let it fail?

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 4, 2011

    On Tue, Jan 4, 2011 at 1:49 PM, Georg Brandl <report@bugs.python.org> wrote:
    ..

    But if it fails, why not just let it fail?

    Sure. That's what I meant by fixing the patch. See new patch attached.

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 5, 2011

    Attached patch, issue10827b.diff, fixes the accept2dyear = True issue and removes unnecessary struct_time to tuple conversion, but otherwise does not change the Y2K behavior. The code handling accept2dyear is refactored so that it is now easy to accept y < 1900 in accept2dyear = False mode. The patch also includes unit tests.

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 7, 2011

    Attached patch, issue10827c.diff, implements the following logic in gettmarg:

    /* If year is specified with less that 4 digits, its interpretation                                                                                                                                       
     * depends on the accept2dyear value.                                                                                                                                                                     
     *                                                                                                                                                                                                        
     * If accept2dyear is true (default), a backward compatibility behavior is                                                                                                                                
     * invoked as follows:                                                                                                                                                                                    
     *                                                                                                                                                                                                        
     *   - for 2-digit year, century is guessed according to POSIX rules for                                                                                                                                  
     *      %y strptime format: 21st century for y < 69, 20th century                                                                                                                                         
     *      otherwise.  A deprecation warning is issued when century                                                                                                                                          
     *      information is guessed in this way.                                                                                                                                                               
     *                                                                                                                                                                                                        
     *   - for 3-digit or negative year, a ValueError exception is raised.                                                                                                                                    
     *                                                                                                                                                                                                        
     * If accept2dyear is false (set by the program or as a result of a                                                                                                                                       
     * non-empty value assigned to PYTHONY2K environment variable) all year                                                                                                                                   
     * values are interpreted as given.                                                                                                                                                                       
     */
    

    It is easy to restore year >= 1900 limit for strftime, but I would rather add tests that time.strftime either produces correct values or raises ValueError and see if buildbots discover any platform bugs.

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 7, 2011

    Committed in 87829.

    I added a year >= 1900 check in time.strftime for now because removing or relaxing this limit should be done in coordination with similar datetime module issue. See bpo-1777412.

    See also python-dev discussion starting at

    http://mail.python.org/pipermail/python-dev/2011-January/107186.html

    @abalkin
    Copy link
    Member Author

    abalkin commented Jan 7, 2011

    Commit link: r87829

    @abalkin abalkin closed this as completed Jan 7, 2011
    @vstinner
    Copy link
    Member

    vstinner commented Jan 7, 2011

    I tried time.asctime() on Windows 32 bits (compiled with Visual Studio) with accept2dyear=False: it accepts years in [-2^31; 2^31-1], cool.

    @vstinner
    Copy link
    Member

    vstinner commented Jan 8, 2011

    time.asctime(), time.ctime() and time.strftime() are no more not limited for the year field if accept2dyear=0. Except with Visual Studio or on Solaris: the year is limited to the range [1; 9999].

    @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
    extension-modules C modules in the Modules dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants