diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2019-08-08 14:36:07 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2019-08-08 14:36:07 +0000 |
commit | fde236b1f719b3a366af4cd5810e847cdb18e480 (patch) | |
tree | 6296cec6a9ef7c18f2961bc3f7ab538b1470830d /libcxx/include | |
parent | ba4bda657e13e7942a205a733548c124bb656c32 (diff) | |
download | bcm5719-llvm-fde236b1f719b3a366af4cd5810e847cdb18e480.tar.gz bcm5719-llvm-fde236b1f719b3a366af4cd5810e847cdb18e480.zip |
Implement hh_mm_ss from P1466R3. Reviewed as https://reviews.llvm.org/D65365.
llvm-svn: 368299
Diffstat (limited to 'libcxx/include')
-rw-r--r-- | libcxx/include/chrono | 120 |
1 files changed, 114 insertions, 6 deletions
diff --git a/libcxx/include/chrono b/libcxx/include/chrono index 51722add2e7..f3be02b58d7 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -612,13 +612,43 @@ constexpr year_month_weekday_last constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) noexcept; -// 25.9, class template time_of_day // C++20 -template<class Duration> class time_of_day; +// 26.9, class template hh_mm_ss +template <class Duration> +class hh_mm_ss +{ + bool is_neg; // exposition only + chrono::hours h; // exposition only + chrono::minutes m; // exposition only + chrono::seconds s; // exposition only + precision ss; // exposition only + +public: + static unsigned constexpr fractional_width = see below; + using precision = see below; + + constexpr hh_mm_ss() noexcept : hh_mm_ss{Duration::zero()} {} + constexpr explicit hh_mm_ss(Duration d) noexcept; + + constexpr bool is_negative() const noexcept; + constexpr chrono::hours hours() const noexcept; + constexpr chrono::minutes minutes() const noexcept; + constexpr chrono::seconds seconds() const noexcept; + constexpr precision subseconds() const noexcept; + + constexpr explicit operator precision() const noexcept; + constexpr precision to_duration() const noexcept; +}; + +template <class charT, class traits, class Duration> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, hh_mm_ss<Duration> const& hms); + +// 26.10, 12/24 hour functions +constexpr bool is_am(hours const& h) noexcept; +constexpr bool is_pm(hours const& h) noexcept; +constexpr hours make12(const hours& h) noexcept; +constexpr hours make24(const hours& h, bool is_pm) noexcept; -template<> class time_of_day<hours>; -template<> class time_of_day<minutes>; -template<> class time_of_day<seconds>; -template<class Rep, class Period> class time_of_day<duration<Rep, Period>>; // 25.10.2, time zone database // C++20 struct tzdb; @@ -2716,6 +2746,84 @@ inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(co inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& __dy) noexcept { *this = *this + __dy; return *this; } inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& __dy) noexcept { *this = *this - __dy; return *this; } + +template <class _Duration> +class hh_mm_ss +{ +private: + static_assert(__is_duration<_Duration>::value, "template parameter of hh_mm_ss must be a std::chrono::duration"); + using __CommonType = common_type_t<_Duration, chrono::seconds>; + + static constexpr uint64_t __pow10(unsigned __exp) + { + uint64_t __ret = 1; + for (unsigned __i = 0; __i < __exp; ++__i) + __ret *= 10U; + return __ret; + } + + static constexpr unsigned __width(uint64_t __n, uint64_t __d = 10, unsigned __w = 0) + { + if (__n >= 2 && __d != 0 && __w < 19) + return 1 + __width(__n, __d % __n * 10, __w+1); + return 0; + } + +public: + static unsigned constexpr fractional_width = __width(__CommonType::period::den) < 19 ? + __width(__CommonType::period::den) : 6u; + using precision = duration<typename __CommonType::rep, ratio<1, __pow10(fractional_width)>>; + + constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {} + + constexpr explicit hh_mm_ss(_Duration __d) noexcept : + __is_neg(__d < _Duration(0)), + __h(duration_cast<chrono::hours> (abs(__d))), + __m(duration_cast<chrono::minutes>(abs(__d) - hours())), + __s(duration_cast<chrono::seconds>(abs(__d) - hours() - minutes())), + __f(duration_cast<precision> (abs(__d) - hours() - minutes() - seconds())) + {} + + constexpr bool is_negative() const noexcept { return __is_neg; } + constexpr chrono::hours hours() const noexcept { return __h; } + constexpr chrono::minutes minutes() const noexcept { return __m; } + constexpr chrono::seconds seconds() const noexcept { return __s; } + constexpr precision subseconds() const noexcept { return __f; } + + constexpr precision to_duration() const noexcept + { + auto __dur = __h + __m + __s + __f; + return __is_neg ? -__dur : __dur; + } + + constexpr explicit operator precision() const noexcept { return to_duration(); } + +private: + bool __is_neg; + chrono::hours __h; + chrono::minutes __m; + chrono::seconds __s; + precision __f; +}; + +constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } +constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); } + +constexpr hours make12(const hours& __h) noexcept +{ + if (__h == hours( 0)) return hours(12); + else if (__h <= hours(12)) return __h; + else return __h - hours(12); +} + +constexpr hours make24(const hours& __h, bool __is_pm) noexcept +{ + if (__is_pm) + return __h == hours(12) ? __h : __h + hours(12); + else + return __h == hours(12) ? hours(0) : __h; +} + #endif // _LIBCPP_STD_VER > 17 } // chrono |