You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
<chrono>: Incorrect output formatting negative years #3166
I think this is the intended behavior. The %C century 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.
You'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 %y gives -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 %C and with strftime as to %y. It also formats the first centuries BCE and CE as -0 and 00, 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.
The 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"
We 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?
Update 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.
Activity
MattStephanson commentedon Oct 21, 2022
I 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.blippyblips commentedon Oct 21, 2022
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 commentedon Oct 22, 2022
You'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.
blippyblips commentedon Oct 22, 2022
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 reference
The 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,
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.
StephanTLavavej commentedon Oct 26, 2022
We 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 commentedon Oct 26, 2022
Stephan T. Lavavej (@StephanTLavavej) --- I'll write it up and see if Victor or Howard want to add anything before it's submitted.
MattStephanson commentedon Nov 9, 2022
Update 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.
MattStephanson commentedon Nov 20, 2022
LWG-3831