//  chrono_io
//
//  (C) Copyright Howard Hinnant
//  Use, modification and distribution are subject to the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt).

#ifndef _CHRONO_IO
#define _CHRONO_IO

/*

    chrono_io synopsis

#include <chrono>
#include <ratio_io>

namespace std
{
namespace chrono
{

template <class CharT>
class durationpunct
    : public locale::facet
{
public:
    static locale::id id;

    typedef basic_string<CharT> string_type;
    enum {use_long, use_short};

    explicit durationpunct(int use = use_long);

    durationpunct(int use,
        const string_type& long_seconds, const string_type& long_minutes,
        const string_type& long_hours, const string_type& short_seconds,
        const string_type& short_minutes, const string_type& short_hours);

    durationpunct(int use, const durationpunct& d);

    template <class Period> string_type short_name() const;
    template <class Period> string_type  long_name() const;
    template <class Period> string_type       name() const;

    bool is_short_name() const;
    bool is_long_name() const;
};

template <class CharT, class Traits>
    basic_ostream<CharT, Traits>&
    duration_short(basic_ostream<CharT, Traits>& os);

template <class CharT, class Traits>
    basic_ostream<CharT, Traits>&
    duration_long(basic_ostream<CharT, Traits>& os);

template <class CharT, class Traits, class Rep, class Period>
    basic_ostream<CharT, Traits>&
    operator<<(basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d);

template <class CharT, class Traits, class Rep, class Period>
    basic_istream<CharT, Traits>&
    operator>>(basic_istream<CharT, Traits>& is, duration<Rep, Period>& d);

template <class CharT, class Traits, class Duration>
    basic_ostream<CharT, Traits>&
    operator<<(basic_ostream<CharT, Traits>& os,
               const time_point<steady_clock, Duration>& tp);

template <class CharT, class Traits, class Duration>
    basic_ostream<CharT, Traits>&
    operator<<(basic_ostream<CharT, Traits>& os,
               const time_point<high_resolution_clock, Duration>& tp);

template <class CharT, class Traits, class Duration>
    basic_ostream<CharT, Traits>&
    operator<<(basic_ostream<CharT, Traits>& os,
               const time_point<system_clock, Duration>& tp);

template <class CharT, class Traits, class Duration>
    basic_istream<CharT, Traits>&
    operator>>(basic_istream<CharT, Traits>& is,
               time_point<steady_clock, Duration>& tp);

template <class CharT, class Traits, class Duration>
    basic_istream<CharT, Traits>&
    operator>>(basic_istream<CharT, Traits>& is,
               time_point<high_resolution_clock, Duration>& tp);

template <class CharT, class Traits, class Duration>
    basic_istream<CharT, Traits>&
    operator>>(basic_istream<CharT, Traits>& is,
               time_point<system_clock, Duration>& tp);

template <class CharT>
class timepunct
    : public std::locale::facet
{
public:
    typedef std::basic_string<CharT> string_type;

    static std::locale::id id;

    explicit timepunct(std::size_t refs = 0,
                        const string_type& fmt = string_type(),
                        bool local = false);

    explicit timepunct(std::size_t refs,
                        string_type&& fmt,
                        bool local = false);

    const string_type& fmt() const {return fmt_;}
    bool             local() const {return local_;}
};

template<class CharT>
    unspecfiied
    local_fmt(std::basic_string<CharT> fmt = std::basic_string<CharT>());

template<class CharT>
    unspecfiied
    local_fmt(const CharT* fmt);

template<class CharT>
    unspecfiied
    utc_fmt(std::basic_string<CharT> fmt = std::basic_string<CharT>());

template<class CharT>
    unspecfiied
    utc_fmt(const CharT* fmt);

}  // chrono
}  // std

*/

#include <chrono>
#include "ratio_io"

_LIBCPP_BEGIN_NAMESPACE_STD

namespace chrono
{

template <class To, class Rep, class Period>
To
round(const duration<Rep, Period>& d)
{
    To t0 = duration_cast<To>(d);
    To t1 = t0;
    ++t1;
    typedef typename common_type<To, duration<Rep, Period> >::type _D;
    _D diff0 = d - t0;
    _D diff1 = t1 - d;
    if (diff0 == diff1)
    {
        if (t0.count() & 1)
            return t1;
        return t0;
    }
    else if (diff0 < diff1)
        return t0;
    return t1;
}

template <class _CharT>
class durationpunct
    : public locale::facet
{
public:
    typedef basic_string<_CharT> string_type;
    enum {use_long, use_short};

private:
    bool __use_short_;
    string_type __seconds_;
    string_type __minutes_;
    string_type __hours_;
public:
    static locale::id id;

    explicit durationpunct(size_t refs = 0,
                            int __use = use_long)
        : locale::facet(refs), __use_short_(__use) {}

    durationpunct(size_t refs, int __use,
        string_type __seconds, string_type __minutes,
        string_type __hours)
        : locale::facet(refs), __use_short_(__use),
          __seconds_(std::move(__seconds)),
          __minutes_(std::move(__minutes)),
          __hours_(std::move(__hours)) {}

    bool is_short_name() const {return __use_short_;}
    bool is_long_name() const {return !__use_short_;}

    string_type seconds() const {return __seconds_;}
    string_type minutes() const {return __minutes_;}
    string_type hours() const {return __hours_;}
};

template <class _CharT>
locale::id
durationpunct<_CharT>::id;

enum {prefix, symbol};
enum {utc, local};

template<class _CharT>
struct __duration_manip
{
    bool __use_short_;
    basic_string<_CharT> __seconds_;
    basic_string<_CharT> __minutes_;
    basic_string<_CharT> __hours_;

    __duration_manip(bool __use_short, basic_string<_CharT> __seconds,
                     basic_string<_CharT> __minutes, basic_string<_CharT> __hours)
        : __use_short_(__use_short),
#if __has_feature(cxx_rvalue_references)
          __seconds_(std::move(__seconds)),
          __minutes_(std::move(__minutes)),
          __hours_(std::move(__hours)) {}
#else
          __seconds_(__seconds),
          __minutes_(__minutes),
          __hours_(__hours) {}
#endif
};

class duration_fmt
{
    int form_;
public:
    explicit duration_fmt(int f) : form_(f) {}
    // explicit
        operator int() const {return form_;}
};

template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, duration_fmt d)
{
    os.imbue(std::locale(os.getloc(), new durationpunct<charT>(0, d == symbol)));
    return os;
}

template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, duration_fmt d)
{
    is.imbue(std::locale(is.getloc(), new durationpunct<charT>(0, d == symbol)));
    return is;
}

template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __duration_manip<charT> m)
{
    os.imbue(std::locale(os.getloc(), new durationpunct<charT>(0, m.__use_short_,
             std::move(m.__seconds_), std::move(m.__minutes_), std::move(m.__hours_))));
    return os;
}

template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __duration_manip<charT> m)
{
    is.imbue(std::locale(is.getloc(), new durationpunct<charT>(0, m.__use_short_,
             std::move(m.__seconds_), std::move(m.__minutes_), std::move(m.__hours_))));
    return is;
}

inline
__duration_manip<char>
duration_short()
{
    return __duration_manip<char>(durationpunct<char>::use_short, "", "", "");
}

template <class _CharT>
inline
__duration_manip<_CharT>
duration_short(basic_string<_CharT> __seconds,
               basic_string<_CharT> __minutes,
               basic_string<_CharT> __hours)
{
    return __duration_manip<_CharT>(durationpunct<_CharT>::use_short,
                                   std::move(__seconds), std::move(__minutes),
                                   std::move(__hours));
}

inline
__duration_manip<char>
duration_long()
{
    return __duration_manip<char>(durationpunct<char>::use_long, "", "", "");
}

template <class _CharT, class _T2, class _T3>
inline
typename enable_if
<
    is_convertible<_T2, basic_string<_CharT> >::value &&
    is_convertible<_T3, basic_string<_CharT> >::value,
    __duration_manip<_CharT>
>::type
duration_long(basic_string<_CharT> __seconds,
              _T2 __minutes,
              _T3 __hours)
{
    typedef basic_string<_CharT> string_type;
    return __duration_manip<_CharT>(durationpunct<_CharT>::use_long,
                                   std::move(__seconds),
                                   string_type(std::move(__minutes)),
                                   string_type(std::move(__hours)));
}

template <class _CharT, class _T2, class _T3>
inline
typename enable_if
<
    is_convertible<_T2, basic_string<_CharT> >::value &&
    is_convertible<_T3, basic_string<_CharT> >::value,
    __duration_manip<_CharT>
>::type
duration_long(const _CharT* __seconds,
              _T2 __minutes,
              _T3 __hours)
{
    typedef basic_string<_CharT> string_type;
    return __duration_manip<_CharT>(durationpunct<_CharT>::use_long,
                                   string_type(__seconds),
                                   string_type(std::move(__minutes)),
                                   string_type(std::move(__hours)));
}

template <class _CharT, class _Period>
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>& __seconds,
           const basic_string<_CharT>&, const basic_string<_CharT>&, _Period)
{
    if (__is_long)
    {
        if (__seconds.empty())
        {
            _CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's', 0};
            return ratio_string<_Period, _CharT>::prefix() + __p;
        }
        return ratio_string<_Period, _CharT>::prefix() + __seconds;
    }
    if (__seconds.empty())
        return ratio_string<_Period, _CharT>::symbol() + 's';
    return ratio_string<_Period, _CharT>::symbol() + __seconds;
}

template <class _CharT>
inline
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>& __seconds,
           const basic_string<_CharT>&, const basic_string<_CharT>&, ratio<1>)
{
    if (__seconds.empty())
    {
        if (__is_long)
        {
            _CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
            return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
        }
        else
            return basic_string<_CharT>(1, 's');
    }
    return __seconds;
}

template <class _CharT>
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>&,
           const basic_string<_CharT>& __minutes,
           const basic_string<_CharT>&, ratio<60>)
{
    if (__minutes.empty())
    {
        if (__is_long)
        {
            _CharT __p[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
            return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
        }
        else
            return basic_string<_CharT>(1, 'm');
    }
    return __minutes;
}

template <class _CharT>
inline
basic_string<_CharT>
__get_unit(bool __is_long, const basic_string<_CharT>&,
           const basic_string<_CharT>&,
           const basic_string<_CharT>& __hours, ratio<3600>)
{
    if (__hours.empty())
    {
        if (__is_long)
        {
            _CharT __p[] = {'h', 'o', 'u', 'r', 's'};
            return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
        }
        else
            return basic_string<_CharT>(1, 'h');
    }
    return __hours;
}

template <class _CharT, class _Traits, class _Rep, class _Period>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d)
{
    typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
    if (ok)
    {
        typedef durationpunct<_CharT> _F;
        typedef basic_string<_CharT> string_type;
        bool failed = false;
        try
        {
            bool __is_long = true;
            string_type __seconds;
            string_type __minutes;
            string_type __hours;
            locale __loc = __os.getloc();
            if (has_facet<_F>(__loc))
            {
                const _F& f = use_facet<_F>(__loc);
                __is_long = f.is_long_name();
                __seconds = f.seconds();
                __minutes = f.minutes();
                __hours = f.hours();
            }
            string_type __unit = __get_unit(__is_long, __seconds, __minutes,
                                            __hours, typename _Period::type());
            __os << __d.count() << ' ' << __unit;
        }
        catch (...)
        {
            failed = true;
        }
        if (failed)
            __os.setstate(ios_base::failbit | ios_base::badbit);
    }
    return __os;
}

template <class _Rep, bool = is_scalar<_Rep>::value>
struct __duration_io_intermediate
{
    typedef _Rep type;
};

template <class _Rep>
struct __duration_io_intermediate<_Rep, true>
{
    typedef typename conditional
    <
        is_floating_point<_Rep>::value,
            long double,
            typename conditional
            <
                is_signed<_Rep>::value,
                    long long,
                    unsigned long long
            >::type
    >::type type;
};

template <class T>
T
__gcd(T x, T y)
{
    while (y != 0)
    {
        T old_x = x;
        x = y;
        y = old_x % y;
    }
    return x;
}

template <>
long double
inline
__gcd(long double x, long double y)
{
    return 1;
}

template <class _CharT, class _Traits, class _Rep, class _Period>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, duration<_Rep, _Period>& __d)
{
    typedef basic_string<_CharT> string_type;
    typedef durationpunct<_CharT> _F;
    typedef typename __duration_io_intermediate<_Rep>::type _IR;
    _IR __r;
    // read value into __r
    __is >> __r;
    if (__is.good())
    {
        // now determine unit
        typedef istreambuf_iterator<_CharT, _Traits> _I;
        _I __i(__is);
        _I __e;
        if (__i != __e && *__i == ' ')  // mandatory ' ' after value
        {
            ++__i;
            if (__i != __e)
            {
                string_type __seconds;
                string_type __minutes;
                string_type __hours;
                locale __loc = __is.getloc();
                if (has_facet<_F>(__loc))
                {
                    const _F& f = use_facet<_F>(__loc);
                    __seconds = f.seconds();
                    __minutes = f.minutes();
                    __hours = f.hours();
                }
                // unit is num / den (yet to be determined)
                unsigned long long num = 0;
                unsigned long long den = 0;
                if (*__i == '[')
                {
                    // parse [N/D]s or [N/D]seconds format
                    ++__i;
                    _CharT __x;
                    __is >> num >> __x >> den;
                    if (!__is.good() || __x != '/')
                    {
                        __is.setstate(__is.failbit);
                        return __is;
                    }
                    __i = _I(__is);
                    if (*__i != ']')
                    {
                        __is.setstate(__is.failbit);
                        return __is;
                    }
                    ++__i;
                    const basic_string<_CharT> __units[] =
                    {
                        __get_unit(true, __seconds, __minutes, __hours, ratio<1>()),
                        __get_unit(false, __seconds, __minutes, __hours, ratio<1>())
                    };
                    ios_base::iostate __err = ios_base::goodbit;
                    const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
                                  __units, __units + sizeof(__units)/sizeof(__units[0]),
                                  use_facet<ctype<_CharT> >(__loc),
                                  __err);
                    switch ((__k - __units) / 2)
                    {
                    case 0:
                        break;
                    default:
                        __is.setstate(__err);
                        return __is;
                    }
                }
                else
                {
                    // parse SI name, short or long
                    const basic_string<_CharT> __units[] =
                    {
                        __get_unit(true, __seconds, __minutes, __hours, atto()),
                        __get_unit(false, __seconds, __minutes, __hours, atto()),
                        __get_unit(true, __seconds, __minutes, __hours, femto()),
                        __get_unit(false, __seconds, __minutes, __hours, femto()),
                        __get_unit(true, __seconds, __minutes, __hours, pico()),
                        __get_unit(false, __seconds, __minutes, __hours, pico()),
                        __get_unit(true, __seconds, __minutes, __hours, nano()),
                        __get_unit(false, __seconds, __minutes, __hours, nano()),
                        __get_unit(true, __seconds, __minutes, __hours, micro()),
                        __get_unit(false, __seconds, __minutes, __hours, micro()),
                        __get_unit(true, __seconds, __minutes, __hours, milli()),
                        __get_unit(false, __seconds, __minutes, __hours, milli()),
                        __get_unit(true, __seconds, __minutes, __hours, centi()),
                        __get_unit(false, __seconds, __minutes, __hours, centi()),
                        __get_unit(true, __seconds, __minutes, __hours, deci()),
                        __get_unit(false, __seconds, __minutes, __hours, deci()),
                        __get_unit(true, __seconds, __minutes, __hours, deca()),
                        __get_unit(false, __seconds, __minutes, __hours, deca()),
                        __get_unit(true, __seconds, __minutes, __hours, hecto()),
                        __get_unit(false, __seconds, __minutes, __hours, hecto()),
                        __get_unit(true, __seconds, __minutes, __hours, kilo()),
                        __get_unit(false, __seconds, __minutes, __hours, kilo()),
                        __get_unit(true, __seconds, __minutes, __hours, mega()),
                        __get_unit(false, __seconds, __minutes, __hours, mega()),
                        __get_unit(true, __seconds, __minutes, __hours, giga()),
                        __get_unit(false, __seconds, __minutes, __hours, giga()),
                        __get_unit(true, __seconds, __minutes, __hours, tera()),
                        __get_unit(false, __seconds, __minutes, __hours, tera()),
                        __get_unit(true, __seconds, __minutes, __hours, peta()),
                        __get_unit(false, __seconds, __minutes, __hours, peta()),
                        __get_unit(true, __seconds, __minutes, __hours, exa()),
                        __get_unit(false, __seconds, __minutes, __hours, exa()),
                        __get_unit(true, __seconds, __minutes, __hours, ratio<1>()),
                        __get_unit(false, __seconds, __minutes, __hours, ratio<1>()),
                        __get_unit(true, __seconds, __minutes, __hours, ratio<60>()),
                        __get_unit(false, __seconds, __minutes, __hours, ratio<60>()),
                        __get_unit(true, __seconds, __minutes, __hours, ratio<3600>()),
                        __get_unit(false, __seconds, __minutes, __hours, ratio<3600>())
                    };
                    ios_base::iostate __err = ios_base::goodbit;
                    const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
                                  __units, __units + sizeof(__units)/sizeof(__units[0]),
                                  use_facet<ctype<_CharT> >(__loc),
                                  __err);
                    switch ((__k - __units) / 2)
                    {
                    case 0:
                        num = 1ULL;
                        den = 1000000000000000000ULL;
                        break;
                    case 1:
                        num = 1ULL;
                        den = 1000000000000000ULL;
                        break;
                    case 2:
                        num = 1ULL;
                        den = 1000000000000ULL;
                        break;
                    case 3:
                        num = 1ULL;
                        den = 1000000000ULL;
                        break;
                    case 4:
                        num = 1ULL;
                        den = 1000000ULL;
                        break;
                    case 5:
                        num = 1ULL;
                        den = 1000ULL;
                        break;
                    case 6:
                        num = 1ULL;
                        den = 100ULL;
                        break;
                    case 7:
                        num = 1ULL;
                        den = 10ULL;
                        break;
                    case 8:
                        num = 10ULL;
                        den = 1ULL;
                        break;
                    case 9:
                        num = 100ULL;
                        den = 1ULL;
                        break;
                    case 10:
                        num = 1000ULL;
                        den = 1ULL;
                        break;
                    case 11:
                        num = 1000000ULL;
                        den = 1ULL;
                        break;
                    case 12:
                        num = 1000000000ULL;
                        den = 1ULL;
                        break;
                    case 13:
                        num = 1000000000000ULL;
                        den = 1ULL;
                        break;
                    case 14:
                        num = 1000000000000000ULL;
                        den = 1ULL;
                        break;
                    case 15:
                        num = 1000000000000000000ULL;
                        den = 1ULL;
                        break;
                    case 16:
                        num = 1;
                        den = 1;
                        break;
                    case 17:
                        num = 60;
                        den = 1;
                        break;
                    case 18:
                        num = 3600;
                        den = 1;
                        break;
                    default:
                        __is.setstate(__err);
                        return __is;
                    }
                }
                // unit is num/den
                // __r should be multiplied by (num/den) / _Period
                // Reduce (num/den) / _Period to lowest terms
                unsigned long long __gcd_n1_n2 = __gcd<unsigned long long>(num, _Period::num);
                unsigned long long __gcd_d1_d2 = __gcd<unsigned long long>(den, _Period::den);
                num /= __gcd_n1_n2;
                den /= __gcd_d1_d2;
                unsigned long long __n2 = _Period::num / __gcd_n1_n2;
                unsigned long long __d2 = _Period::den / __gcd_d1_d2;
                if (num > numeric_limits<unsigned long long>::max() / __d2 ||
                    den > numeric_limits<unsigned long long>::max() / __n2)
                {
                    // (num/den) / _Period overflows
                    __is.setstate(__is.failbit);
                    return __is;
                }
                num *= __d2;
                den *= __n2;
                // num / den is now factor to multiply by __r
                typedef typename common_type<_IR, unsigned long long>::type _CT;
                if (is_integral<_IR>::value)
                {
                    // Reduce __r * num / den
                    _CT __t = __gcd<_CT>(__r, den);
                    __r /= __t;
                    den /= __t;
                    if (den != 1)
                    {
                        // Conversion to _Period is integral and not exact
                        __is.setstate(__is.failbit);
                        return __is;
                    }
                }
                if (__r > duration_values<_CT>::max() / num)
                {
                    // Conversion to _Period overflowed
                    __is.setstate(__is.failbit);
                    return __is;
                }
                _CT __t = __r * num;
                __t /= den;
                if (duration_values<_Rep>::max() < __t)
                {
                    // Conversion to _Period overflowed
                    __is.setstate(__is.failbit);
                    return __is;
                }
                // Success!  Store it.
                __r = _Rep(__t);
                __d = duration<_Rep, _Period>(__r);
            }
            else
                __is.setstate(__is.failbit | __is.eofbit);
        }
        else
        {
            if (__i == __e)
                __is.setstate(__is.eofbit);
            __is.setstate(__is.failbit);
        }
    }
    else
        __is.setstate(__is.failbit);
    return __is;
}

template <class charT>
class timepunct
    : public std::locale::facet
{
public:
    typedef std::basic_string<charT> string_type;

private:
    string_type fmt_;
    bool        local_;

public:
    static std::locale::id id;

    explicit timepunct(std::size_t refs = 0,
                        const string_type& fmt = string_type(),
                        bool local = false)
        : std::locale::facet(refs),
          fmt_(fmt),
          local_(local) {}

#if __has_feature(cxx_rvalue_references)
    explicit timepunct(std::size_t refs,
                        string_type&& fmt,
                        bool local = false)
        : std::locale::facet(refs),
          fmt_(std::move(fmt)),
          local_(local) {}
#endif

    const string_type& fmt() const {return fmt_;}
    bool             local() const {return local_;}
};

template <class CharT>
std::locale::id
timepunct<CharT>::id;

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
           const time_point<steady_clock, _Duration>& __tp)
{
    return __os << __tp.time_since_epoch() << " since boot";
}

template<class charT>
struct __time_manip
{
    std::basic_string<charT> fmt_;
    bool local_;

    __time_manip(std::basic_string<charT> fmt, bool local)
#if __has_feature(cxx_rvalue_references)
        : fmt_(std::move(fmt)),
#else
        : fmt_(fmt),
#endif
          local_(local) {}
};

template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __time_manip<charT> m)
{
#if __has_feature(cxx_rvalue_references)
    os.imbue(std::locale(os.getloc(), new timepunct<charT>(0, std::move(m.fmt_), m.local_)));
#else
    os.imbue(std::locale(os.getloc(), new timepunct<charT>(0, m.fmt_, m.local_)));
#endif
    return os;
}

template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __time_manip<charT> m)
{
#if __has_feature(cxx_rvalue_references)
    is.imbue(std::locale(is.getloc(), new timepunct<charT>(0, std::move(m.fmt_), m.local_)));
#else
    is.imbue(std::locale(is.getloc(), new timepunct<charT>(0, m.fmt_, m.local_)));
#endif
    return is;
}

template<class charT>
inline
__time_manip<charT>
local_fmt(std::basic_string<charT> fmt)
{
#if __has_feature(cxx_rvalue_references)
    return __time_manip<charT>(std::move(fmt), true);
#else
    return __time_manip<charT>(fmt, true);
#endif
}

template<class charT>
inline
__time_manip<charT>
local_fmt(const charT* fmt)
{
    return __time_manip<charT>(fmt, true);
}

inline
__time_manip<char>
local_fmt()
{
    return __time_manip<char>("", true);
}

template<class charT>
inline
__time_manip<charT>
utc_fmt(std::basic_string<charT> fmt)
{
#if __has_feature(cxx_rvalue_references)
    return __time_manip<charT>(std::move(fmt), false);
#else
    return __time_manip<charT>(fmt, false);
#endif
}

template<class charT>
inline
__time_manip<charT>
utc_fmt(const charT* fmt)
{
    return __time_manip<charT>(fmt, false);
}

inline
__time_manip<char>
utc_fmt()
{
    return __time_manip<char>("", false);
}

class __time_man
{
    int form_;
public:
    explicit __time_man(int f) : form_(f) {}
    // explicit
        operator int() const {return form_;}
};

template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT, traits>& os, __time_man m)
{
    os.imbue(std::locale(os.getloc(), new timepunct<charT>(0, basic_string<charT>(), m == local)));
    return os;
}

template<class charT, class traits>
std::basic_istream<charT, traits>&
operator >>(std::basic_istream<charT, traits>& is, __time_man m)
{
    is.imbue(std::locale(is.getloc(), new timepunct<charT>(0, basic_string<charT>(), m == local)));
    return is;
}


inline
__time_man
time_fmt(int f)
{
    return __time_man(f);
}

template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
           time_point<steady_clock, _Duration>& __tp)
{
    _Duration __d;
    __is >> __d;
    if (__is.good())
    {
        const _CharT __u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'};
        const basic_string<_CharT> __units(__u, __u + sizeof(__u)/sizeof(__u[0]));
        ios_base::iostate __err = ios_base::goodbit;
        typedef istreambuf_iterator<_CharT, _Traits> _I;
        _I __i(__is);
        _I __e;
        ptrdiff_t __k = __scan_keyword(__i, __e,
                      &__units, &__units + 1,
                      use_facet<ctype<_CharT> >(__is.getloc()),
                      __err) - &__units;
        if (__k == 1)
        {
            // failed to read epoch string
            __is.setstate(__err);
            return __is;
        }
        __tp = time_point<steady_clock, _Duration>(__d);
    }
    else
        __is.setstate(__is.failbit);
    return __is;
}

template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
           const time_point<system_clock, _Duration>& __tp)
{
    typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
    if (ok)
    {
        bool failed = false;
        try
        {
            const _CharT* pb = nullptr;
            const _CharT* pe = pb;
            bool __local = false;
            typedef timepunct<_CharT> F;
            locale loc = __os.getloc();
            if (has_facet<F>(loc))
            {
                const F& f = use_facet<F>(loc);
                pb = f.fmt().data();
                pe = pb + f.fmt().size();
                __local = f.local();
            }
            time_t __t = system_clock::to_time_t(__tp);
            tm __tm;
            if (__local)
            {
                if (localtime_r(&__t, &__tm) == 0)
                    failed = true;
            }
            else
            {
                if (gmtime_r(&__t, &__tm) == 0)
                    failed = true;
            }
            if (!failed)
            {
                const time_put<_CharT>& tp = use_facet<time_put<_CharT> >(loc);
                if (pb == pe)
                {
                    _CharT pattern[] = {'%', 'F', ' ', '%', 'H', ':', '%', 'M', ':'};
                    pb = pattern;
                    pe = pb + sizeof(pattern) / sizeof(_CharT);
                    failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
                    if (!failed)
                    {
                        duration<double> __d = __tp - system_clock::from_time_t(__t) +
                                  seconds(__tm.tm_sec);
                        if (__d.count() < 10)
                            __os << _CharT('0');
                        ios::fmtflags __flgs = __os.flags();
                        __os.setf(ios::fixed, ios::floatfield);
                        __os << __d.count();
                        __os.flags(__flgs);
                        if (__local)
                        {
                            _CharT sub_pattern[] = {' ', '%', 'z'};
                            pb = sub_pattern;
                            pe = pb + + sizeof(sub_pattern) / sizeof(_CharT);
                            failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
                        }
                        else
                        {
                            _CharT sub_pattern[] = {' ', '+', '0', '0', '0', '0', 0};
                            __os << sub_pattern;
                        }
                    }
                }
                else
                    failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
            }
        }
        catch (...)
        {
            failed = true;
        }
        if (failed)
            __os.setstate(ios_base::failbit | ios_base::badbit);
    }
    return __os;
}

template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
           time_point<system_clock, _Duration>& __tp)
{
    typename basic_istream<_CharT,_Traits>::sentry ok(__is);
    if (ok)
    {
        ios_base::iostate err = ios_base::goodbit;
        try
        {
            const _CharT* pb = nullptr;
            const _CharT* pe = pb;
            bool __local = false;
            typedef timepunct<_CharT> F;
            locale loc = __is.getloc();
            if (has_facet<F>(loc))
            {
                const F& f = use_facet<F>(loc);
                pb = f.fmt().data();
                pe = pb + f.fmt().size();
                __local = f.local();
            }
            const time_get<_CharT>& tg = use_facet<time_get<_CharT> >(loc);
            tm __tm = {0};
            if (pb == pe)
            {
                _CharT pattern[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd',
                                    ' ', '%', 'H', ':', '%', 'M', ':'};
                pb = pattern;
                pe = pb + sizeof(pattern) / sizeof(_CharT);
                tg.get(__is, 0, __is, err, &__tm, pb, pe);
                if (err & ios_base::failbit)
                    goto __exit;
                typedef istreambuf_iterator<_CharT, _Traits> _I;
                double __sec;
                _CharT __c = _CharT();
                __is >> __sec;
                if (__is.fail())
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                _I __i(__is);
                _I __eof;
                __c = *__i;
                if (++__i == __eof || __c != ' ')
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                __c = *__i;
                if (++__i == __eof || (__c != '+' && __c != '-'))
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                int __n = __c == '-' ? 1 : -1;
                __c = *__i;
                if (++__i == __eof || !isdigit(__c))
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                int __min = (__c - '0') * 600;
                __c = *__i;
                if (++__i == __eof || !isdigit(__c))
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                __min += (__c - '0') * 60;
                __c = *__i;
                if (++__i == __eof || !isdigit(__c))
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                __min += (__c - '0') * 10;
                __c = *__i;
                if (!isdigit(__c))
                {
                    err |= ios_base::failbit;
                    goto __exit;
                }
                ++__i;
                __min += __c - '0';
                __min *= __n;
                time_t __t;
                __t = timegm(&__tm);
                __tp = system_clock::from_time_t(__t) + minutes(__min)
                                 + round<microseconds>(duration<double>(__sec));
            }
            else
            {
                tg.get(__is, 0, __is, err, &__tm, pb, pe);
            }
        }
        catch (...)
        {
            err |= ios_base::badbit | ios_base::failbit;
        }
    __exit:
        __is.setstate(err);
    }
    return __is;
}

}  // chrono

_LIBCPP_END_NAMESPACE_STD

#endif  // _CHRONO_IO
