Repository navigation
<chrono>: Incorrect output formatting negative years #3166
Description
Activity
MattStephanson commented
on Oct 21, 2022 ContributorMore actionsI think this is the intended behavior. The
%Ccentury flag is specified in [tab:time.format.spec] as "[t]he year divided by 100 using floored division." So for -3053, that would give -31, and our convention is that the year is always century_part*100+two_digit_year, with an addition regardless of the sign of the century or year. I think this makes the most sense, given the floored division specification.I agree for %C this is doing the correct thing but this same function is also being used as part of the implementation for %y.
The last two decimal digits of the year (https://eel.is/c++draft/tab:time.format.spec#row-36-column-2-sentence-1).
In that context the pair.second from _Decompose_year is being used and it's only correct for positive inputs.MattStephanson commented
on Oct 22, 2022 ContributorMore actionsYou're right that the standard says "[t]he last two decimal digits of the year." But in practice this is often interpreted to mean the number of years since the beginning of the century. Obviously these meanings are the same when the year is positive and different when it's negative, so I suspect people sometimes say one thing while meaning another.
The original proposal claims "
strftime-like formatting", so we can look to that as a guide for existing practice. You can see at https://godbolt.org/z/Gbz7harWd that the format string"%C %ygives-31 47, which agrees with MSVC STL. On the other hand, {fmtlib}, which is also influential as to existing practice, gives-30 53. This disagrees with the standard as to%Cand withstrftimeas to%y. It also formats the first centuries BCE and CE as-0and00, which seems less than ideal for an integer value.On the whole, there doesn't seems to be a clear consensus for what the result should be, so maybe an LWG issue is needed to clarify.
It does sound like there should be separate "years since start of century" "nearest century" "truncated century" and "last two decimals of the year" identifiers, even if they are the same in many cases it's really useful for expressing intent.
C Standard
C++ Time Format for referenceThe C17 draft has slightly different phrasing then the eel.is c++ draft but it matches closer with fmts implementation of the formatting identifiers, specifically it calls for the truncated integer after division by 100 instead of floored division for %C and for %y it mentions that it's 'replaced' by the last 2 digits of the year, that seems much more strictly defined.
About the 00 case in FMT, that seems to come from 2 things,
- When writing negative numbers they seem to have interpreted the standard saying 4 digits as 4 characters and they remove 1 when adding the - sign, otherwise it would also have written -00.
- %Y for positive (0 included) is written in terms of %C%y so you're getting one zero from the century and another from the "decade/unit years"
Year formatting in fmt for reference
It makes more sense when you read the 2 different versions of the time specs(c vs c++) and try to combine them.
- addedLWG issue neededA wording defect that should be submitted to LWG as a new issueA wording defect that should be submitted to LWG as a new issue
on Oct 26, 2022 StephanTLavavej commented
on Oct 26, 2022 MemberMore actionsWe talked about this the weekly maintainer meeting and agree that an LWG issue seems necessary here. Matt Stephanson (@MattStephanson) would you like to file an issue, or would you like someone else to look into drafting one?
MattStephanson commented
on Oct 26, 2022 ContributorMore actionsStephan T. Lavavej (@StephanTLavavej) --- I'll write it up and see if Victor or Howard want to add anything before it's submitted.
Reacted by Marcus and A. JiangReacted by Casey Carter and A. JiangMattStephanson commented
on Nov 9, 2022 ContributorMore actionsUpdate for anyone who's watching this issue: I sent out the draft issue yesterday. Waiting to see if one more person wants to comment, but planning to send to LWG by next Monday at the latest.
Reacted by Stephan T. LavavejMattStephanson commented
on Nov 20, 2022 ContributorMore actions- addedblocked on LWGWaiting for WG21 to tell us what to doWaiting for WG21 to tell us what to doand removedLWG issue neededA wording defect that should be submitted to LWG as a new issueA wording defect that should be submitted to LWG as a new issue
on Mar 20, 2025 - addedbugSomething isn't workingSomething isn't workingfixedSomething works now, yay!Something works now, yay!and removedblocked on LWGWaiting for WG21 to tell us what to doWaiting for WG21 to tell us what to do
on Apr 17, 2026
Describe the bug
Incorrect values when formatting negative std::chrono::years with %y (last 2 only).
Command-line test case
Expected behavior
Would expect it to print 53
STL version
Microsoft Visual Studio Community 2022 Version 17.3.6 https://github.com/microsoft/STL/tree/mainAdditional context
Current code in master:
https://github.com/microsoft/STL/blob/2f8342a3a57fb157d881c6a2d42a917d20e413f8/stl/inc/chrono#L3168Not sure about the reason for the +100 currently there but would expect something along these lines