mirror of
https://github.com/HowardHinnant/date.git
synced 2025-07-30 10:47:14 +02:00
Unify and simplify fractional decimal seconds formatting
* Many of the ideas and some of the code herein is credited to Adrian Colomitchi * Decouple fractional decimal seconds formatting from time_of_day formatting so that it can be more easily used elsewhere in the future. * Include super-second durations such as nanocenturies and microfortnights in the class of durations that will get formatted with fractional decimal seconds. * If a duration is exactly representable with fractional decimal seconds not exceeding 18 decimal fractional digits, format it exactly. Otherwise format it to 6 fractional decimal digits (microseconds precision). The number 18 is chosen as this is the limit of std::ratio using 64 bits (i.e. atto). * The above bullet implies that durations with ratio<1, 4> will now be formatted with 2 fractional decimal digits instead of 1. ratio<1, 8> will be formatted with 3, and ratio<1, 3> with 6. * Unify the implementation into one C++11 implementation that works equally well with C++14. * Drive-by fix a couple formatting bugs dealing with negative durations. * Deprecate the make_time functions taking unsigned md by removing their documentation. Also deprecate the corresponding time_of_day constructors taking unsigned md. * This change paves the way for future formatting improvements.
This commit is contained in:
300
date.h
300
date.h
@ -4,6 +4,7 @@
|
|||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) 2015, 2016 Howard Hinnant
|
// Copyright (c) 2015, 2016 Howard Hinnant
|
||||||
|
// Copyright (c) 2016 Adrian Colomitchi
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -3383,6 +3384,130 @@ enum {am = 1, pm};
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// width<n>::value is the number of fractional decimal digits in 1/n
|
||||||
|
// width<0>::value and width<1>::value are defined to be 0
|
||||||
|
// If 1/n takes more than 18 fractional decimal digits,
|
||||||
|
// the result is truncated to 19.
|
||||||
|
// Example: width<2>::value == 1
|
||||||
|
// Example: width<3>::value == 19
|
||||||
|
// Example: width<4>::value == 2
|
||||||
|
// Example: width<10>::value == 1
|
||||||
|
// Example: width<1000>::value == 3
|
||||||
|
template <std::uint64_t n, std::uint64_t d = 10, unsigned w = 0,
|
||||||
|
bool should_continue = !(n < 2) && d != 0 && w < 19>
|
||||||
|
struct width
|
||||||
|
{
|
||||||
|
static CONSTDATA unsigned value = 1 + width<n, d%n*10, w+1>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::uint64_t n, std::uint64_t d, unsigned w>
|
||||||
|
struct width<n, d, w, false>
|
||||||
|
{
|
||||||
|
static CONSTDATA unsigned value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned exp>
|
||||||
|
struct static_pow10
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static CONSTDATA std::uint64_t h = static_pow10<exp/2>::value;
|
||||||
|
public:
|
||||||
|
static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct static_pow10<0>
|
||||||
|
{
|
||||||
|
static CONSTDATA std::uint64_t value = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned w, bool in_range = w < 19>
|
||||||
|
struct make_precision
|
||||||
|
{
|
||||||
|
using type = std::chrono::duration<std::int64_t,
|
||||||
|
std::ratio<1, static_pow10<w>::value>>;
|
||||||
|
static CONSTDATA unsigned width = w;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned w>
|
||||||
|
struct make_precision<w, false>
|
||||||
|
{
|
||||||
|
using type = std::chrono::microseconds;
|
||||||
|
static CONSTDATA unsigned width = 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Duration, unsigned w = width<Duration::period::den>::value>
|
||||||
|
class decimal_format_seconds
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using precision = typename make_precision<w>::type;
|
||||||
|
static auto CONSTDATA width = make_precision<w>::width;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::seconds s_;
|
||||||
|
precision sub_s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT
|
||||||
|
: s_(std::chrono::duration_cast<std::chrono::seconds>(d))
|
||||||
|
, sub_s_(std::chrono::duration_cast<precision>(d - s_))
|
||||||
|
{}
|
||||||
|
|
||||||
|
CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;}
|
||||||
|
CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;}
|
||||||
|
CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;}
|
||||||
|
|
||||||
|
CONSTCD14 precision to_duration() const NOEXCEPT
|
||||||
|
{
|
||||||
|
return s_ + sub_s_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT, class Traits>
|
||||||
|
friend
|
||||||
|
std::basic_ostream<CharT, Traits>&
|
||||||
|
operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x)
|
||||||
|
{
|
||||||
|
date::detail::save_stream<CharT, Traits> _(os);
|
||||||
|
os.fill('0');
|
||||||
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
|
os.width(2);
|
||||||
|
os << x.s_.count() <<
|
||||||
|
std::use_facet<std::numpunct<char>>(os.getloc()).decimal_point();
|
||||||
|
os.width(width);
|
||||||
|
os << x.sub_s_.count();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
class decimal_format_seconds<Duration, 0>
|
||||||
|
{
|
||||||
|
static CONSTDATA unsigned w = 0;
|
||||||
|
public:
|
||||||
|
using precision = std::chrono::seconds;
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::chrono::seconds s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CONSTCD11 explicit decimal_format_seconds(const precision& s) NOEXCEPT
|
||||||
|
: s_(s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <class CharT, class Traits>
|
||||||
|
friend
|
||||||
|
std::basic_ostream<CharT, Traits>&
|
||||||
|
operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x)
|
||||||
|
{
|
||||||
|
date::detail::save_stream<CharT, Traits> _(os);
|
||||||
|
os.fill('0');
|
||||||
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
|
os.width(2);
|
||||||
|
os << x.s_.count();
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
enum class classify
|
enum class classify
|
||||||
{
|
{
|
||||||
not_valid,
|
not_valid,
|
||||||
@ -3392,57 +3517,34 @@ enum class classify
|
|||||||
subsecond
|
subsecond
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
|
||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
struct classify_duration
|
struct classify_duration
|
||||||
{
|
{
|
||||||
static CONSTDATA classify value =
|
static CONSTDATA classify value =
|
||||||
Duration{1} >= days{1} ? classify::not_valid :
|
std::is_convertible<Duration, std::chrono::hours>::value
|
||||||
Duration{1} >= std::chrono::hours{1} ? classify::hour :
|
|
||||||
Duration{1} >= std::chrono::minutes{1} ? classify::minute :
|
|
||||||
Duration{1} >= std::chrono::seconds{1} ? classify::second :
|
|
||||||
classify::subsecond;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <class Duration>
|
|
||||||
struct classify_duration
|
|
||||||
{
|
|
||||||
static CONSTDATA classify value =
|
|
||||||
std::ratio_greater_equal<
|
|
||||||
typename Duration::period,
|
|
||||||
days::period >::value
|
|
||||||
? classify::not_valid :
|
|
||||||
std::ratio_greater_equal<
|
|
||||||
typename Duration::period,
|
|
||||||
std::chrono::hours::period>::value
|
|
||||||
? classify::hour :
|
? classify::hour :
|
||||||
std::ratio_greater_equal<
|
std::is_convertible<Duration, std::chrono::minutes>::value
|
||||||
typename Duration::period,
|
|
||||||
std::chrono::minutes::period>::value
|
|
||||||
? classify::minute :
|
? classify::minute :
|
||||||
std::ratio_greater_equal<
|
std::is_convertible<Duration, std::chrono::seconds>::value
|
||||||
typename Duration::period,
|
|
||||||
std::chrono::seconds::period>::value
|
|
||||||
? classify::second :
|
? classify::second :
|
||||||
|
std::chrono::treat_as_floating_point<typename Duration::rep>::value
|
||||||
|
? classify::not_valid :
|
||||||
classify::subsecond;
|
classify::subsecond;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
|
||||||
|
|
||||||
class time_of_day_base
|
class time_of_day_base
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::chrono::hours h_;
|
std::chrono::hours h_;
|
||||||
unsigned char mode_;
|
unsigned char mode_;
|
||||||
|
bool neg_;
|
||||||
|
|
||||||
enum {is24hr};
|
enum {is24hr};
|
||||||
|
|
||||||
CONSTCD11 time_of_day_base(std::chrono::hours h, unsigned m) NOEXCEPT
|
CONSTCD11 time_of_day_base(std::chrono::hours h, unsigned m) NOEXCEPT
|
||||||
: h_(h)
|
: h_(abs(h))
|
||||||
, mode_(static_cast<decltype(mode_)>(m))
|
, mode_(static_cast<decltype(mode_)>(m))
|
||||||
|
, neg_(h < std::chrono::hours{0})
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CONSTCD14 void make24() NOEXCEPT;
|
CONSTCD14 void make24() NOEXCEPT;
|
||||||
@ -3528,7 +3630,10 @@ public:
|
|||||||
|
|
||||||
CONSTCD14 explicit operator precision() const NOEXCEPT
|
CONSTCD14 explicit operator precision() const NOEXCEPT
|
||||||
{
|
{
|
||||||
return to24hr();
|
auto p = to24hr();
|
||||||
|
if (neg_)
|
||||||
|
p = -p;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTCD14 precision to_duration() const NOEXCEPT
|
CONSTCD14 precision to_duration() const NOEXCEPT
|
||||||
@ -3546,6 +3651,8 @@ public:
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
detail::save_stream<CharT, Traits> _(os);
|
detail::save_stream<CharT, Traits> _(os);
|
||||||
|
if (t.neg_)
|
||||||
|
os << '-';
|
||||||
os.fill('0');
|
os.fill('0');
|
||||||
os.flags(std::ios::dec | std::ios::right);
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
if (t.mode_ != am && t.mode_ != pm)
|
if (t.mode_ != am && t.mode_ != pm)
|
||||||
@ -3580,7 +3687,7 @@ public:
|
|||||||
|
|
||||||
CONSTCD11 explicit time_of_day_storage(std::chrono::minutes since_midnight) NOEXCEPT
|
CONSTCD11 explicit time_of_day_storage(std::chrono::minutes since_midnight) NOEXCEPT
|
||||||
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
||||||
, m_(since_midnight - h_)
|
, m_(abs(since_midnight) - h_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
||||||
@ -3595,7 +3702,10 @@ public:
|
|||||||
|
|
||||||
CONSTCD14 explicit operator precision() const NOEXCEPT
|
CONSTCD14 explicit operator precision() const NOEXCEPT
|
||||||
{
|
{
|
||||||
return to24hr() + m_;
|
auto p = to24hr() + m_;
|
||||||
|
if (neg_)
|
||||||
|
p = -p;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTCD14 precision to_duration() const NOEXCEPT
|
CONSTCD14 precision to_duration() const NOEXCEPT
|
||||||
@ -3613,15 +3723,15 @@ public:
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
detail::save_stream<CharT, Traits> _(os);
|
detail::save_stream<CharT, Traits> _(os);
|
||||||
if (static_cast<precision>(t) < std::chrono::hours{0})
|
if (t.neg_)
|
||||||
os << '-';
|
os << '-';
|
||||||
os.fill('0');
|
os.fill('0');
|
||||||
os.flags(std::ios::dec | std::ios::right);
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
if (t.mode_ != am && t.mode_ != pm)
|
if (t.mode_ != am && t.mode_ != pm)
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.h_.count()) << ':';
|
os << t.h_.count() << ':';
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.m_.count());
|
os << t.m_.count();
|
||||||
switch (t.mode_)
|
switch (t.mode_)
|
||||||
{
|
{
|
||||||
case am:
|
case am:
|
||||||
@ -3649,8 +3759,8 @@ public:
|
|||||||
|
|
||||||
CONSTCD11 explicit time_of_day_storage(std::chrono::seconds since_midnight) NOEXCEPT
|
CONSTCD11 explicit time_of_day_storage(std::chrono::seconds since_midnight) NOEXCEPT
|
||||||
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
||||||
, m_(std::chrono::duration_cast<std::chrono::minutes>(since_midnight - h_))
|
, m_(std::chrono::duration_cast<std::chrono::minutes>(abs(since_midnight) - h_))
|
||||||
, s_(since_midnight - h_ - m_)
|
, s_(abs(since_midnight) - h_ - m_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
||||||
@ -3668,7 +3778,10 @@ public:
|
|||||||
|
|
||||||
CONSTCD14 explicit operator precision() const NOEXCEPT
|
CONSTCD14 explicit operator precision() const NOEXCEPT
|
||||||
{
|
{
|
||||||
return to24hr() + s_ + m_;
|
auto p = to24hr() + s_ + m_;
|
||||||
|
if (neg_)
|
||||||
|
p = -p;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTCD14 precision to_duration() const NOEXCEPT
|
CONSTCD14 precision to_duration() const NOEXCEPT
|
||||||
@ -3686,17 +3799,17 @@ public:
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
detail::save_stream<CharT, Traits> _(os);
|
detail::save_stream<CharT, Traits> _(os);
|
||||||
if (static_cast<precision>(t) < std::chrono::hours{0})
|
if (t.neg_)
|
||||||
os << '-';
|
os << '-';
|
||||||
os.fill('0');
|
os.fill('0');
|
||||||
os.flags(std::ios::dec | std::ios::right);
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
if (t.mode_ != am && t.mode_ != pm)
|
if (t.mode_ != am && t.mode_ != pm)
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.h_.count()) << ':';
|
os << t.h_.count() << ':';
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.m_.count()) << ':';
|
os << t.m_.count() << ':';
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.s_.count());
|
os << t.s_.count();
|
||||||
switch (t.mode_)
|
switch (t.mode_)
|
||||||
{
|
{
|
||||||
case am:
|
case am:
|
||||||
@ -3715,21 +3828,21 @@ class time_of_day_storage<std::chrono::duration<Rep, Period>, detail::classify::
|
|||||||
: private detail::time_of_day_base
|
: private detail::time_of_day_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using precision = std::chrono::duration<Rep, Period>;
|
using Duration = std::chrono::duration<Rep, Period>;
|
||||||
|
using dfs = decimal_format_seconds<Duration>;
|
||||||
|
using precision = typename dfs::precision;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using base = detail::time_of_day_base;
|
using base = detail::time_of_day_base;
|
||||||
|
|
||||||
std::chrono::minutes m_;
|
std::chrono::minutes m_;
|
||||||
std::chrono::seconds s_;
|
dfs s_;
|
||||||
precision sub_s_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CONSTCD11 explicit time_of_day_storage(precision since_midnight) NOEXCEPT
|
CONSTCD11 explicit time_of_day_storage(Duration since_midnight) NOEXCEPT
|
||||||
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
: base(std::chrono::duration_cast<std::chrono::hours>(since_midnight), is24hr)
|
||||||
, m_(std::chrono::duration_cast<std::chrono::minutes>(since_midnight - h_))
|
, m_(std::chrono::duration_cast<std::chrono::minutes>(abs(since_midnight) - h_))
|
||||||
, s_(std::chrono::duration_cast<std::chrono::seconds>(since_midnight - h_ - m_))
|
, s_(abs(since_midnight) - h_ - m_)
|
||||||
, sub_s_(since_midnight - h_ - m_ - s_)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m,
|
||||||
@ -3737,20 +3850,22 @@ public:
|
|||||||
unsigned md) NOEXCEPT
|
unsigned md) NOEXCEPT
|
||||||
: base(h, md)
|
: base(h, md)
|
||||||
, m_(m)
|
, m_(m)
|
||||||
, s_(s)
|
, s_(s + sub_s)
|
||||||
, sub_s_(sub_s)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;}
|
CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;}
|
||||||
CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;}
|
CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;}
|
||||||
CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;}
|
CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_.seconds();}
|
||||||
CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;}
|
CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();}
|
||||||
CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;}
|
CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();}
|
||||||
CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;}
|
CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;}
|
||||||
|
|
||||||
CONSTCD14 explicit operator precision() const NOEXCEPT
|
CONSTCD14 explicit operator precision() const NOEXCEPT
|
||||||
{
|
{
|
||||||
return to24hr() + s_ + sub_s_ + m_;
|
auto p = to24hr() + s_.to_duration() + m_;
|
||||||
|
if (neg_)
|
||||||
|
p = -p;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTCD14 precision to_duration() const NOEXCEPT
|
CONSTCD14 precision to_duration() const NOEXCEPT
|
||||||
@ -3768,33 +3883,15 @@ public:
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
detail::save_stream<CharT, Traits> _(os);
|
detail::save_stream<CharT, Traits> _(os);
|
||||||
if (static_cast<precision>(t) < std::chrono::hours{0})
|
if (t.neg_)
|
||||||
os << '-';
|
os << '-';
|
||||||
os.fill('0');
|
os.fill('0');
|
||||||
os.flags(std::ios::dec | std::ios::right);
|
os.flags(std::ios::dec | std::ios::right);
|
||||||
if (t.mode_ != am && t.mode_ != pm)
|
if (t.mode_ != am && t.mode_ != pm)
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.h_.count()) << ':';
|
os << t.h_.count() << ':';
|
||||||
os.width(2);
|
os.width(2);
|
||||||
os << std::abs(t.m_.count()) << ':';
|
os << t.m_.count() << ':' << t.s_;
|
||||||
os.width(2);
|
|
||||||
os << std::abs(t.s_.count())
|
|
||||||
<< use_facet<numpunct<char>>(os.getloc()).decimal_point();
|
|
||||||
os.imbue(locale{});
|
|
||||||
#if __cplusplus >= 201402
|
|
||||||
CONSTDATA auto cl10 = ceil_log10(Period::den);
|
|
||||||
using scale = std::ratio_multiply<Period, std::ratio<pow10(cl10)>>;
|
|
||||||
os.width(cl10);
|
|
||||||
os << std::abs(t.sub_s_.count()) * scale::num / scale::den;
|
|
||||||
#else // __cplusplus >= 201402
|
|
||||||
// inefficient sub-optimal run-time mess, but gets the job done
|
|
||||||
const unsigned long long cl10 =
|
|
||||||
static_cast<unsigned long long>(std::ceil(log10(Period::den)));
|
|
||||||
const auto p10 = std::pow(10., cl10);
|
|
||||||
os.width(cl10);
|
|
||||||
os << static_cast<unsigned long long>(std::abs(t.sub_s_.count())
|
|
||||||
* Period::num * p10 / Period::den);
|
|
||||||
#endif // __cplusplus >= 201402
|
|
||||||
switch (t.mode_)
|
switch (t.mode_)
|
||||||
{
|
{
|
||||||
case am:
|
case am:
|
||||||
@ -3806,50 +3903,6 @@ public:
|
|||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
#if __cplusplus >= 201402
|
|
||||||
CONSTCD11 static int ceil_log10(unsigned long long i) NOEXCEPT
|
|
||||||
{
|
|
||||||
--i;
|
|
||||||
int n = 0;
|
|
||||||
if (i >= 10000000000000000) {i /= 10000000000000000; n += 16;}
|
|
||||||
if (i >= 100000000) {i /= 100000000; n += 8;}
|
|
||||||
if (i >= 10000) {i /= 10000; n += 4;}
|
|
||||||
if (i >= 100) {i /= 100; n += 2;}
|
|
||||||
if (i >= 10) {i /= 10; n += 1;}
|
|
||||||
if (i >= 1) {i /= 10; n += 1;}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSTCD11 static unsigned long long pow10(unsigned y) NOEXCEPT
|
|
||||||
{
|
|
||||||
CONSTDATA unsigned long long p10[] =
|
|
||||||
{
|
|
||||||
1ull,
|
|
||||||
10ull,
|
|
||||||
100ull,
|
|
||||||
1000ull,
|
|
||||||
10000ull,
|
|
||||||
100000ull,
|
|
||||||
1000000ull,
|
|
||||||
10000000ull,
|
|
||||||
100000000ull,
|
|
||||||
1000000000ull,
|
|
||||||
10000000000ull,
|
|
||||||
100000000000ull,
|
|
||||||
1000000000000ull,
|
|
||||||
10000000000000ull,
|
|
||||||
100000000000000ull,
|
|
||||||
1000000000000000ull,
|
|
||||||
10000000000000000ull,
|
|
||||||
100000000000000000ull,
|
|
||||||
1000000000000000000ull,
|
|
||||||
10000000000000000000ull
|
|
||||||
};
|
|
||||||
return p10[y];
|
|
||||||
}
|
|
||||||
#endif // __cplusplus >= 201402
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -3866,7 +3919,8 @@ public:
|
|||||||
#else
|
#else
|
||||||
// MS cl compiler workaround.
|
// MS cl compiler workaround.
|
||||||
template <class ...Args>
|
template <class ...Args>
|
||||||
explicit time_of_day(Args&& ...args)
|
CONSTCD11
|
||||||
|
explicit time_of_day(Args&& ...args) NOEXCEPT
|
||||||
: base(std::forward<Args>(args)...)
|
: base(std::forward<Args>(args)...)
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user