Move chrono_io.h functionality into date.h.

This commit is contained in:
Howard Hinnant 2017-04-13 21:01:47 -04:00
parent 05db422ca9
commit d15491103b
3 changed files with 677 additions and 650 deletions

View File

@ -17,13 +17,11 @@ This is actually several separate C++11/C++14 libraries:
Here are the Cppcon 2016 slides on tz.h: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf Here are the Cppcon 2016 slides on tz.h: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
3. `"chrono_io.h"` is a header-only library for streaming out chrono durations. See http://howardhinnant.github.io/date/chrono_io.html for more details. 3. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details.
4. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details. 4. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details.
5. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details. 5. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details.
6. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details.
There has been a recent change in the library design. If you are trying to migrate from the previous design, rename `day_point` to `sys_days` everywhere, and that ought to bring the number of errors down to a small roar. There has been a recent change in the library design. If you are trying to migrate from the previous design, rename `day_point` to `sys_days` everywhere, and that ought to bring the number of errors down to a small roar.

View File

@ -27,651 +27,8 @@
// been invented (that would involve another several millennia of evolution). // been invented (that would involve another several millennia of evolution).
// We did not mean to shout. // We did not mean to shout.
#include <chrono> // This functionality has moved to "date.h"
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <ratio>
#include <string>
#include <type_traits>
namespace date #include "date.h"
{
namespace detail
{
#if __cplusplus >= 201402
template <class CharT, std::size_t N>
class string_literal
{
CharT p_[N];
public:
using const_iterator = const CharT*;
string_literal(string_literal const&) = default;
string_literal& operator=(string_literal const&) = delete;
template <std::size_t N1 = 2,
class = std::enable_if_t<N1 == N>>
constexpr string_literal(CharT c) noexcept
: p_{c}
{
}
constexpr string_literal(const CharT(&a)[N]) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class U = CharT, class = std::enable_if_t<1 < sizeof(U)>>
constexpr string_literal(const char(&a)[N]) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class CharT2, class = std::enable_if_t<!std::is_same<CharT2, CharT>{}>>
constexpr string_literal(string_literal<CharT2, N> const& a) noexcept
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <std::size_t N1, std::size_t N2,
class = std::enable_if_t<N1 + N2 - 1 == N>>
constexpr string_literal(const string_literal<CharT, N1>& x,
const string_literal<CharT, N2>& y) noexcept
: p_{}
{
std::size_t i = 0;
for (; i < N1-1; ++i)
p_[i] = x[i];
for (std::size_t j = 0; j < N2; ++j, ++i)
p_[i] = y[j];
}
constexpr const CharT* data() const noexcept {return p_;}
constexpr std::size_t size() const noexcept {return N-1;}
constexpr const_iterator begin() const noexcept {return p_;}
constexpr const_iterator end() const noexcept {return p_ + N-1;}
constexpr CharT const& operator[](std::size_t n) const noexcept
{
return p_[n];
}
template <class Traits>
friend
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
{
return os << s.p_;
}
};
template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
constexpr
inline
string_literal<std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>,
N1 + N2 - 1>
operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) noexcept
{
using CharT = std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>;
return string_literal<CharT, N1 + N2 - 1>{string_literal<CharT, N1>{x},
string_literal<CharT, N2>{y}};
}
template <class CharT, class Traits, class Alloc, std::size_t N>
inline
std::basic_string<CharT, Traits, Alloc>
operator+(std::basic_string<CharT, Traits, Alloc> x,
const string_literal<CharT, N>& y) noexcept
{
x.append(y.data(), y.size());
return x;
}
template <class CharT, std::size_t N>
constexpr
inline
string_literal<CharT, N>
msl(const CharT(&a)[N]) noexcept
{
return string_literal<CharT, N>{a};
}
template <class CharT,
class = std::enable_if_t<std::is_same<CharT, char>{} ||
std::is_same<CharT, wchar_t>{} ||
std::is_same<CharT, char16_t>{} ||
std::is_same<CharT, char32_t>{}>>
constexpr
inline
string_literal<CharT, 2>
msl(CharT c) noexcept
{
return string_literal<CharT, 2>{c};
}
constexpr
std::size_t
to_string_len(std::intmax_t i)
{
std::size_t r = 0;
do
{
i /= 10;
++r;
} while (i > 0);
return r;
}
template <std::intmax_t N>
constexpr
inline
std::enable_if_t
<
N < 10,
string_literal<char, to_string_len(N)+1>
>
msl() noexcept
{
return msl(char(N % 10 + '0'));
}
template <std::intmax_t N>
constexpr
inline
std::enable_if_t
<
10 <= N,
string_literal<char, to_string_len(N)+1>
>
msl() noexcept
{
return msl<N/10>() + msl(char(N % 10 + '0'));
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
std::enable_if_t
<
std::ratio<N, D>::type::den != 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
to_string_len(std::ratio<N, D>::type::den) + 4>
>
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
msl<R::den>() + msl(CharT{']'});
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
std::enable_if_t
<
std::ratio<N, D>::type::den == 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
>
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
}
template <class CharT>
constexpr
inline
auto
msl(std::atto) noexcept
{
return msl(CharT{'a'});
}
template <class CharT>
constexpr
inline
auto
msl(std::femto) noexcept
{
return msl(CharT{'f'});
}
template <class CharT>
constexpr
inline
auto
msl(std::pico) noexcept
{
return msl(CharT{'p'});
}
template <class CharT>
constexpr
inline
auto
msl(std::nano) noexcept
{
return msl(CharT{'n'});
}
template <class CharT>
constexpr
inline
std::enable_if_t
<
std::is_same<CharT, char>{},
string_literal<char, 3>
>
msl(std::micro) noexcept
{
return string_literal<char, 3>{"\xC2\xB5"};
}
template <class CharT>
constexpr
inline
std::enable_if_t
<
!std::is_same<CharT, char>{},
string_literal<CharT, 2>
>
msl(std::micro) noexcept
{
return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
}
template <class CharT>
constexpr
inline
auto
msl(std::milli) noexcept
{
return msl(CharT{'m'});
}
template <class CharT>
constexpr
inline
auto
msl(std::centi) noexcept
{
return msl(CharT{'c'});
}
template <class CharT>
constexpr
inline
auto
msl(std::deci) noexcept
{
return msl(CharT{'d'});
}
template <class CharT>
constexpr
inline
auto
msl(std::deca) noexcept
{
return string_literal<CharT, 3>{"da"};
}
template <class CharT>
constexpr
inline
auto
msl(std::hecto) noexcept
{
return msl(CharT{'h'});
}
template <class CharT>
constexpr
inline
auto
msl(std::kilo) noexcept
{
return msl(CharT{'k'});
}
template <class CharT>
constexpr
inline
auto
msl(std::mega) noexcept
{
return msl(CharT{'M'});
}
template <class CharT>
constexpr
inline
auto
msl(std::giga) noexcept
{
return msl(CharT{'G'});
}
template <class CharT>
constexpr
inline
auto
msl(std::tera) noexcept
{
return msl(CharT{'T'});
}
template <class CharT>
constexpr
inline
auto
msl(std::peta) noexcept
{
return msl(CharT{'P'});
}
template <class CharT>
constexpr
inline
auto
msl(std::exa) noexcept
{
return msl(CharT{'E'});
}
template <class CharT, class Period>
constexpr
auto
get_units(Period p)
{
return msl<CharT>(p) + string_literal<CharT, 2>{"s"};
}
template <class CharT>
constexpr
auto
get_units(std::ratio<1>)
{
return string_literal<CharT, 2>{"s"};
}
template <class CharT>
constexpr
auto
get_units(std::ratio<60>)
{
return string_literal<CharT, 4>{"min"};
}
template <class CharT>
constexpr
auto
get_units(std::ratio<3600>)
{
return string_literal<CharT, 2>{"h"};
}
#else // __cplusplus < 201402
inline
std::string
to_string(std::uint64_t x)
{
return std::to_string(x);
}
template <class CharT>
std::basic_string<CharT>
to_string(std::uint64_t x)
{
auto y = std::to_string(x);
return std::basic_string<CharT>(y.begin(), y.end());
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
typename std::enable_if
<
std::ratio<N, D>::type::den != 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
to_string<CharT>(R::den) + CharT{']'};
}
template <class CharT, std::intmax_t N, std::intmax_t D>
constexpr
inline
typename std::enable_if
<
std::ratio<N, D>::type::den == 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>) noexcept
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::atto) noexcept
{
return {'a'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::femto) noexcept
{
return {'f'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::pico) noexcept
{
return {'p'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::nano) noexcept
{
return {'n'};
}
template <class CharT>
constexpr
inline
typename std::enable_if
<
std::is_same<CharT, char>::value,
std::string
>::type
msl(std::micro) noexcept
{
return "\xC2\xB5";
}
template <class CharT>
constexpr
inline
typename std::enable_if
<
!std::is_same<CharT, char>::value,
std::basic_string<CharT>
>::type
msl(std::micro) noexcept
{
return {CharT(static_cast<unsigned char>('\xB5'))};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::milli) noexcept
{
return {'m'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::centi) noexcept
{
return {'c'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::deci) noexcept
{
return {'d'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::deca) noexcept
{
return {'d', 'a'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::hecto) noexcept
{
return {'h'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::kilo) noexcept
{
return {'k'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::mega) noexcept
{
return {'M'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::giga) noexcept
{
return {'G'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::tera) noexcept
{
return {'T'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::peta) noexcept
{
return {'P'};
}
template <class CharT>
constexpr
inline
std::basic_string<CharT>
msl(std::exa) noexcept
{
return {'E'};
}
template <class CharT, class Period>
std::basic_string<CharT>
get_units(Period p)
{
return msl<CharT>(p) + CharT{'s'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<1>)
{
return {'s'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<60>)
{
return {'m', 'i', 'n'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<3600>)
{
return {'h'};
}
#endif // __cplusplus >= 201402
} // namespace detail
template <class CharT, class Traits, class Rep, class Period>
inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::chrono::duration<Rep, Period>& d)
{
using namespace std;
return os << to_string(d.count()) + detail::get_units<CharT>(typename Period::type{});
}
} // namespace date
#endif // CHRONO_IO_H #endif // CHRONO_IO_H

672
date.h
View File

@ -35,6 +35,7 @@
#if !(__cplusplus >= 201402) #if !(__cplusplus >= 201402)
# include <cmath> # include <cmath>
#endif #endif
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
@ -6654,6 +6655,677 @@ parse(const CharT* format, Parsable& tp,
return {format, tp, &abbrev, &offset}; return {format, tp, &abbrev, &offset};
} }
// duration streaming
namespace detail
{
#if __cplusplus >= 201402
template <class CharT, std::size_t N>
class string_literal
{
CharT p_[N];
public:
using const_iterator = const CharT*;
string_literal(string_literal const&) = default;
string_literal& operator=(string_literal const&) = delete;
template <std::size_t N1 = 2,
class = std::enable_if_t<N1 == N>>
CONSTCD14 string_literal(CharT c) NOEXCEPT
: p_{c}
{
}
CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class U = CharT, class = std::enable_if_t<1 < sizeof(U)>>
CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <class CharT2, class = std::enable_if_t<!std::is_same<CharT2, CharT>{}>>
CONSTCD14 string_literal(string_literal<CharT2, N> const& a) NOEXCEPT
: p_{}
{
for (std::size_t i = 0; i < N; ++i)
p_[i] = a[i];
}
template <std::size_t N1, std::size_t N2,
class = std::enable_if_t<N1 + N2 - 1 == N>>
CONSTCD14 string_literal(const string_literal<CharT, N1>& x,
const string_literal<CharT, N2>& y) NOEXCEPT
: p_{}
{
std::size_t i = 0;
for (; i < N1-1; ++i)
p_[i] = x[i];
for (std::size_t j = 0; j < N2; ++j, ++i)
p_[i] = y[j];
}
CONSTCD14 const CharT* data() const NOEXCEPT {return p_;}
CONSTCD14 std::size_t size() const NOEXCEPT {return N-1;}
CONSTCD14 const_iterator begin() const NOEXCEPT {return p_;}
CONSTCD14 const_iterator end() const NOEXCEPT {return p_ + N-1;}
CONSTCD14 CharT const& operator[](std::size_t n) const NOEXCEPT
{
return p_[n];
}
template <class Traits>
friend
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
{
return os << s.p_;
}
};
template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
CONSTCD14
inline
string_literal<std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>,
N1 + N2 - 1>
operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT
{
using CharT = std::conditional_t<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>;
return string_literal<CharT, N1 + N2 - 1>{string_literal<CharT, N1>{x},
string_literal<CharT, N2>{y}};
}
template <class CharT, class Traits, class Alloc, std::size_t N>
inline
std::basic_string<CharT, Traits, Alloc>
operator+(std::basic_string<CharT, Traits, Alloc> x,
const string_literal<CharT, N>& y) NOEXCEPT
{
x.append(y.data(), y.size());
return x;
}
template <class CharT, std::size_t N>
CONSTCD14
inline
string_literal<CharT, N>
msl(const CharT(&a)[N]) NOEXCEPT
{
return string_literal<CharT, N>{a};
}
template <class CharT,
class = std::enable_if_t<std::is_same<CharT, char>{} ||
std::is_same<CharT, wchar_t>{} ||
std::is_same<CharT, char16_t>{} ||
std::is_same<CharT, char32_t>{}>>
CONSTCD14
inline
string_literal<CharT, 2>
msl(CharT c) NOEXCEPT
{
return string_literal<CharT, 2>{c};
}
CONSTCD14
std::size_t
to_string_len(std::intmax_t i)
{
std::size_t r = 0;
do
{
i /= 10;
++r;
} while (i > 0);
return r;
}
template <std::intmax_t N>
CONSTCD14
inline
std::enable_if_t
<
N < 10,
string_literal<char, to_string_len(N)+1>
>
msl() NOEXCEPT
{
return msl(char(N % 10 + '0'));
}
template <std::intmax_t N>
CONSTCD14
inline
std::enable_if_t
<
10 <= N,
string_literal<char, to_string_len(N)+1>
>
msl() NOEXCEPT
{
return msl<N/10>() + msl(char(N % 10 + '0'));
}
template <class CharT, std::intmax_t N, std::intmax_t D>
CONSTCD14
inline
std::enable_if_t
<
std::ratio<N, D>::type::den != 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
to_string_len(std::ratio<N, D>::type::den) + 4>
>
msl(std::ratio<N, D>) NOEXCEPT
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
msl<R::den>() + msl(CharT{']'});
}
template <class CharT, std::intmax_t N, std::intmax_t D>
CONSTCD14
inline
std::enable_if_t
<
std::ratio<N, D>::type::den == 1,
string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
>
msl(std::ratio<N, D>) NOEXCEPT
{
using R = typename std::ratio<N, D>::type;
return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::atto) NOEXCEPT
{
return msl(CharT{'a'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::femto) NOEXCEPT
{
return msl(CharT{'f'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::pico) NOEXCEPT
{
return msl(CharT{'p'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::nano) NOEXCEPT
{
return msl(CharT{'n'});
}
template <class CharT>
CONSTCD14
inline
std::enable_if_t
<
std::is_same<CharT, char>{},
string_literal<char, 3>
>
msl(std::micro) NOEXCEPT
{
return string_literal<char, 3>{"\xC2\xB5"};
}
template <class CharT>
CONSTCD14
inline
std::enable_if_t
<
!std::is_same<CharT, char>{},
string_literal<CharT, 2>
>
msl(std::micro) NOEXCEPT
{
return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::milli) NOEXCEPT
{
return msl(CharT{'m'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::centi) NOEXCEPT
{
return msl(CharT{'c'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::deci) NOEXCEPT
{
return msl(CharT{'d'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::deca) NOEXCEPT
{
return string_literal<CharT, 3>{"da"};
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::hecto) NOEXCEPT
{
return msl(CharT{'h'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::kilo) NOEXCEPT
{
return msl(CharT{'k'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::mega) NOEXCEPT
{
return msl(CharT{'M'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::giga) NOEXCEPT
{
return msl(CharT{'G'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::tera) NOEXCEPT
{
return msl(CharT{'T'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::peta) NOEXCEPT
{
return msl(CharT{'P'});
}
template <class CharT>
CONSTCD14
inline
auto
msl(std::exa) NOEXCEPT
{
return msl(CharT{'E'});
}
template <class CharT, class Period>
CONSTCD14
auto
get_units(Period p)
{
return msl<CharT>(p) + string_literal<CharT, 2>{"s"};
}
template <class CharT>
CONSTCD14
auto
get_units(std::ratio<1>)
{
return string_literal<CharT, 2>{"s"};
}
template <class CharT>
CONSTCD14
auto
get_units(std::ratio<60>)
{
return string_literal<CharT, 4>{"min"};
}
template <class CharT>
CONSTCD14
auto
get_units(std::ratio<3600>)
{
return string_literal<CharT, 2>{"h"};
}
#else // __cplusplus < 201402
inline
std::string
to_string(std::uint64_t x)
{
return std::to_string(x);
}
template <class CharT>
std::basic_string<CharT>
to_string(std::uint64_t x)
{
auto y = std::to_string(x);
return std::basic_string<CharT>(y.begin(), y.end());
}
template <class CharT, std::intmax_t N, std::intmax_t D>
inline
typename std::enable_if
<
std::ratio<N, D>::type::den != 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>)
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
to_string<CharT>(R::den) + CharT{']'};
}
template <class CharT, std::intmax_t N, std::intmax_t D>
inline
typename std::enable_if
<
std::ratio<N, D>::type::den == 1,
std::basic_string<CharT>
>::type
msl(std::ratio<N, D>)
{
using R = typename std::ratio<N, D>::type;
return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::atto)
{
return {'a'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::femto)
{
return {'f'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::pico)
{
return {'p'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::nano)
{
return {'n'};
}
template <class CharT>
inline
typename std::enable_if
<
std::is_same<CharT, char>::value,
std::string
>::type
msl(std::micro)
{
return "\xC2\xB5";
}
template <class CharT>
inline
typename std::enable_if
<
!std::is_same<CharT, char>::value,
std::basic_string<CharT>
>::type
msl(std::micro)
{
return {CharT(static_cast<unsigned char>('\xB5'))};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::milli)
{
return {'m'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::centi)
{
return {'c'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::deci)
{
return {'d'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::deca)
{
return {'d', 'a'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::hecto)
{
return {'h'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::kilo)
{
return {'k'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::mega)
{
return {'M'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::giga)
{
return {'G'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::tera)
{
return {'T'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::peta)
{
return {'P'};
}
template <class CharT>
inline
std::basic_string<CharT>
msl(std::exa)
{
return {'E'};
}
template <class CharT, class Period>
std::basic_string<CharT>
get_units(Period p)
{
return msl<CharT>(p) + CharT{'s'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<1>)
{
return {'s'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<60>)
{
return {'m', 'i', 'n'};
}
template <class CharT>
std::basic_string<CharT>
get_units(std::ratio<3600>)
{
return {'h'};
}
#endif // __cplusplus >= 201402
template <class CharT, class Traits = std::char_traits<CharT>>
struct make_string;
template <>
struct make_string<char>
{
template <class Rep>
static
std::string
from(Rep n)
{
return std::to_string(n);
}
};
template <class Traits>
struct make_string<char, Traits>
{
template <class Rep>
static
std::basic_string<char, Traits>
from(Rep n)
{
auto s = std::to_string(n);
return std::basic_string<char, Traits>(s.begin(), s.end());
}
};
template <>
struct make_string<wchar_t>
{
template <class Rep>
static
std::wstring
from(Rep n)
{
return std::to_wstring(n);
}
};
template <class Traits>
struct make_string<wchar_t, Traits>
{
template <class Rep>
static
std::wstring
from(Rep n)
{
auto s = std::to_wstring(n);
return std::basic_string<wchar_t, Traits>(s.begin(), s.end());
}
};
} // namespace detail
template <class CharT, class Traits, class Rep, class Period>
inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::chrono::duration<Rep, Period>& d)
{
using namespace detail;
return os << make_string<CharT, Traits>::from(d.count()) +
get_units<CharT>(typename Period::type{});
}
} // namespace date } // namespace date