* Avoid narrowing duration day counts to the original representation
* Keep duration field values in the promoted representation
---------
Co-authored-by: Aikhan Jumashukurov <117706338+aikhanj@users.noreply.github.com>
Compute the upper bound as 2^digits with std::ldexp instead of
static_cast<FromRep>(max) + 1, which is only exact when rounding to
nearest: with FE_UPWARD in an unoptimized build the bound became
2^63 + 2048 and a count of 2^63 reached the undefined conversion.
Truncate the count once and use it for both the check and the cast.
Skip the checks that need safe duration casts when
FMT_SAFE_DURATION_CAST is 0, where the NaN time point check failed.
Drop the 1e300 time point and two bool assertions, which don't catch
anything the others don't, and test max + 1 and NaN directly.
* fix unchecked float to integral conversion in detail::duration_cast
* Check the truncated count in float to integral duration_cast
* Keep the duration_cast fallback for custom representations
* Use an explicit rep in the custom_rep duration_cast test
std::chrono::seconds is duration<long> on 64-bit Linux so common_type<long,
custom_rep> had no specialization and chrono-test failed to compile there.
* Exclude bool from the checked float to integral duration_cast
Compute the ISO week-based year and week number from the day of the year
of the Thursday in the current week instead of the weekday of December 31.
This only needs a leap year check, which works for negative years without
floored division, and is about 3 times faster.
For std::tm values with tm_wday and tm_yday inconsistent with tm_year,
%G, %g and %V now give the same results as strftime.
Replace the negative year tests with a year_month_day test that also
covers the leap year check and days_from_civil for negative years.
iso_year_weeks computed the weekday of December 31 with truncating
division and a remainder that is negative for negative years, so it
returned the wrong number of ISO weeks for years before year 0. As a
result %V and %G/%g were wrong around the start and end of such years,
e.g. 1 January of year -1 was formatted as week 52 of year -2 instead
of week 53, and 31 December of year -2 as week 1 of year -1.
Use floored division and a non-negative remainder.
Claude-Session: https://claude.ai/code/session_01Y1b55sEL1gA1c3FCMcQCbm
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The year_month_day formatter only filled in tm_year, tm_mon and tm_mday,
so specifiers that depend on the weekday or the day of the year (%a, %A,
%u, %w, %j, %U, %W, %V, %G, %g) were formatted from zero-initialized
fields, e.g. every date was printed as a Sunday. Compute tm_wday and
tm_yday from the date before passing it to the tm formatter.
Floor the seconds before calling gmtime instead of adjusting tm_sec, and
keep the subsecond remainder in the common duration type, which fixes
overflow for narrow reps such as duration<int16_t, std::micro>.
tm_writer takes a locale_ref and the localized flag instead of a std::locale
reference, and resolves the locale the same way numeric {:L} does: classic
unless localized, otherwise the one passed to the formatting function or the
global one. The facet calls are confined to three shims, so with locale
support disabled nothing pulls in std::locale. get_locale, which existed only
to materialize and own a std::locale, is no longer needed.
The std::tm formatter treated a missing locale argument as the classic locale
rather than the global one, and since #4935 routes {:L} on weekday and month
through it, {:L} without a locale argument ignored the global locale for all
calendar types. It now uses the global locale, as numeric {:L} does. Output
with an explicit locale is unchanged. With FMT_USE_LOCALE=0, {:L} no longer
consults the global locale, matching numeric formatting under that option. An
-Os test program loses all 16 of its std::locale and time_put symbols.
* implement year_month_day, also changed weekday, day, month, year's formatter to use formatter<std::tm, Char> so they all support the format strings
* support ":L" for month and weekday