Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 50 additions & 12 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,19 @@ namespace chrono {
return _Rnext;
}

template <class _Period, class _CharT, class _Traits>
void _Write_unit_suffix(basic_ostream<_CharT, _Traits>& _Os) {
constexpr auto _Suffix = _Get_literal_unit_suffix<_CharT, _Period>();
if constexpr (_Suffix == nullptr) {
_CharT _Buffer[2 * (numeric_limits<intmax_t>::digits10 + 1) + 5] = {}; // 2 numbers + "[/]s\0"
const _CharT* const _Begin =
_Get_general_unit_suffix<_CharT>(_STD end(_Buffer), _Period::num, _Period::den);
_Os << _Begin;
} else {
_Os << _Suffix;
}
}

template <class _CharT, class _Traits, class _Rep, class _Period>
basic_ostream<_CharT, _Traits>& operator<<(
basic_ostream<_CharT, _Traits>& _Os, const duration<_Rep, _Period>& _Dur) {
Expand All @@ -782,16 +795,7 @@ namespace chrono {
_Sstr.imbue(_Os.getloc());
_Sstr.precision(_Os.precision());
_Sstr << _Dur.count();

constexpr auto _Suffix = _Get_literal_unit_suffix<_CharT, _Period>();
if constexpr (_Suffix == nullptr) {
_CharT _Buffer[2 * (numeric_limits<intmax_t>::digits10 + 1) + 5] = {}; // 2 numbers + "[/]s\0"
const _CharT* const _Begin =
_Get_general_unit_suffix<_CharT>(_STD end(_Buffer), _Period::num, _Period::den);
_Sstr << _Begin;
} else {
_Sstr << _Suffix;
}
_Write_unit_suffix<_Period>(_Sstr);

return _Os << _Sstr.str();
}
Expand Down Expand Up @@ -5470,6 +5474,12 @@ namespace chrono {
_Write_seconds(_Os, hh_mm_ss{_Val - _Dp});
}

template <class _CharT, class _Traits, class _Rep, class _Period>
void _Write_seconds(basic_ostream<_CharT, _Traits>& _Os, const duration<_Rep, _Period>& _Val) {
const auto _Dp = _CHRONO duration_cast<days>(_Val);
_Write_seconds(_Os, hh_mm_ss{_Val - _Dp});
}

template <class _Ty>
_NODISCARD tm _Fill_tm(const _Ty& _Val) {
unsigned int _Day = 0;
Expand All @@ -5480,7 +5490,10 @@ namespace chrono {
int _Minutes = 0;
int _Seconds = 0;

if constexpr (is_same_v<_Ty, day>) {
if constexpr (_Is_specialization_v<_Ty, duration>) {
const auto _Dp = _CHRONO duration_cast<days>(_Val);
return _Fill_tm(hh_mm_ss{_Val - _Dp});
} else if constexpr (is_same_v<_Ty, day>) {
_Day = static_cast<unsigned int>(_Val);
} else if constexpr (is_same_v<_Ty, month>) {
_Month = static_cast<unsigned int>(_Val);
Expand Down Expand Up @@ -5779,7 +5792,9 @@ namespace chrono {

template <class _Ty>
_NODISCARD constexpr bool _Is_valid_type(const char _Type) noexcept {
if constexpr (is_same_v<_Ty, day>) {
if constexpr (_Is_specialization_v<_Ty, duration>) {
return _Type == 'j' || _Type == 'q' || _Type == 'Q' || _Is_valid_type<hh_mm_ss<seconds>>(_Type);
} else if constexpr (is_same_v<_Ty, day>) {
return _Type == 'd' || _Type == 'e';
} else if constexpr (is_same_v<_Ty, month>) {
return _Type == 'b' || _Type == 'B' || _Type == 'h' || _Type == 'm';
Expand Down Expand Up @@ -5825,6 +5840,10 @@ namespace chrono {
if (_Val.is_negative()) {
_Stream << _CharT{'-'};
}
} else if constexpr (_Is_specialization_v<_Ty, duration>) {
if (_Val < _Ty::zero()) {
_Stream << _CharT{'-'};
}
}

for (const auto& _Spec : _Specs._Chrono_specs_list) {
Expand Down Expand Up @@ -5892,6 +5911,21 @@ namespace chrono {
}
_Os << _Time.tm_mday;
return true;
case 'j':
if constexpr (_Is_specialization_v<_Ty, duration>) {
_Os << _STD abs(_CHRONO duration_cast<days>(_Val).count());
}
return true;
case 'q':
if constexpr (_Is_specialization_v<_Ty, duration>) {
_Write_unit_suffix<typename _Ty::period>(_Os);
}
return true;
case 'Q':
if constexpr (_Is_specialization_v<_Ty, duration>) {
_Os << _STD abs(_Val.count());
}
return true;
case 'm':
if (_Has_modifier) {
return false;
Expand Down Expand Up @@ -5997,6 +6031,10 @@ private:
_CHRONO _Chrono_formatter<_CharT> _Impl;
};

template <class _Rep, class _Period, class _CharT>
struct formatter<_CHRONO duration<_Rep, _Period>, _CharT>
: _Fill_tm_formatter<_CHRONO duration<_Rep, _Period>, _CharT> {};

template <class _CharT>
struct formatter<_CHRONO day, _CharT> //
: _Fill_tm_formatter<_CHRONO day, _CharT> {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,27 @@ constexpr void print(Str str) {
}
}

template <typename CharT>
void test_duration_formatter() {
empty_braces_helper(seconds{5}, STR("5s"));
empty_braces_helper(minutes{7}, STR("7min"));
empty_braces_helper(hours{9}, STR("9h"));
empty_braces_helper(days{2}, STR("2d"));
empty_braces_helper(-seconds{5}, STR("-5s"));
empty_braces_helper(duration<int, ratio<3, 1>>{40}, STR("40[3]s"));
empty_braces_helper(duration<int, ratio<3, 7>>{40}, STR("40[3/7]s"));

assert(format(STR("{:%T}"), 4083007ms) == STR("01:08:03.007"));
assert(format(STR("{:%T}"), -4083007ms) == STR("-01:08:03.007"));

assert(format(STR("{:%T %j %q %Q}"), days{4} + 30min) == STR("00:30:00 4 min 5790"));
assert(format(STR("{:%T %j %q %Q}"), -days{4} - 30min) == STR("-00:30:00 4 min 5790"));
assert(format(STR("{:%T %j}"), days{4} + 23h + 30min) == STR("23:30:00 4"));
assert(format(STR("{:%T %j}"), -days{4} - 23h - 30min) == STR("-23:30:00 4"));
assert(format(STR("{:%T %j}"), duration<float, days::period>{1.55f}) == STR("13:11:59 1"));
assert(format(STR("{:%T %j}"), duration<float, days::period>{-1.55f}) == STR("-13:11:59 1"));
}

template <typename CharT>
void test_clock_formatter() {
empty_braces_helper(sys_seconds{}, STR("1970-01-01 00:00:00"));
Expand Down Expand Up @@ -597,6 +618,9 @@ int main() {
test_parse_chrono_format_specs<char>();
test_parse_chrono_format_specs<wchar_t>();

test_duration_formatter<char>();
test_duration_formatter<wchar_t>();

test_clock_formatter<char>();
test_clock_formatter<wchar_t>();

Expand Down