// (C) Copyright Howard Hinnant // (C) Copyright 2010-2011 Vicente J. Botet Escriba // 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). //===-------------------------- locale ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // This code was adapted by Vicente from Howard Hinnant's experimental work // on chrono i/o to Boost and some functions from libc++/locale to emulate the missing time_get::get() #ifndef BOOST_CHRONO_IO_TIME_POINT_IO_HPP #define BOOST_CHRONO_IO_TIME_POINT_IO_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \ || (defined(sun) || defined(__sun)) \ || (defined __IBMCPP__) \ || defined __ANDROID__ \ || defined __QNXNTO__ \ || (defined(_AIX) && defined __GNUC__) #define BOOST_CHRONO_INTERNAL_TIMEGM #endif #if (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \ || ( (defined(sun) || defined(__sun)) && defined __GNUC__) \ || (defined __IBMCPP__) \ || defined __ANDROID__ \ || (defined(_AIX) && defined __GNUC__) #define BOOST_CHRONO_INTERNAL_GMTIME #endif #define BOOST_CHRONO_USES_INTERNAL_TIME_GET namespace boost { namespace chrono { typedef double fractional_seconds; namespace detail { template > struct time_get { std::time_get const &that_; time_get(std::time_get const& that) : that_(that) {} typedef std::time_get facet; typedef typename facet::iter_type iter_type; typedef typename facet::char_type char_type; typedef std::basic_string string_type; static int get_up_to_n_digits( InputIterator& b, InputIterator e, std::ios_base::iostate& err, const std::ctype& ct, int n) { // Precondition: n >= 1 if (b == e) { err |= std::ios_base::eofbit | std::ios_base::failbit; return 0; } // get first digit CharT c = *b; if (!ct.is(std::ctype_base::digit, c)) { err |= std::ios_base::failbit; return 0; } int r = ct.narrow(c, 0) - '0'; for (++b, --n; b != e && n > 0; ++b, --n) { // get next digit c = *b; if (!ct.is(std::ctype_base::digit, c)) return r; r = r * 10 + ct.narrow(c, 0) - '0'; } if (b == e) err |= std::ios_base::eofbit; return r; } void get_day( int& d, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && 1 <= t && t <= 31) d = t; else err |= std::ios_base::failbit; } void get_month( int& m, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12) m = --t; else err |= std::ios_base::failbit; } void get_year4(int& y, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 4); if (!(err & std::ios_base::failbit)) y = t - 1900; } void get_hour(int& h, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && t <= 23) h = t; else err |= std::ios_base::failbit; } void get_minute(int& m, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && t <= 59) m = t; else err |= std::ios_base::failbit; } void get_second(int& s, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && t <= 60) s = t; else err |= std::ios_base::failbit; } void get_white_space(iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { for (; b != e && ct.is(std::ctype_base::space, *b); ++b) ; if (b == e) err |= std::ios_base::eofbit; } void get_12_hour(int& h, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 2); if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12) h = t; else err |= std::ios_base::failbit; } void get_percent(iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { if (b == e) { err |= std::ios_base::eofbit | std::ios_base::failbit; return; } if (ct.narrow(*b, 0) != '%') err |= std::ios_base::failbit; else if(++b == e) err |= std::ios_base::eofbit; } void get_day_year_num(int& d, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 3); if (!(err & std::ios_base::failbit) && 1 <= t && t <= 366) d = --t; else err |= std::ios_base::failbit; } void get_weekday(int& w, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { int t = get_up_to_n_digits(b, e, err, ct, 1); if (!(err & std::ios_base::failbit) && t <= 6) w = t; else err |= std::ios_base::failbit; } #if 0 void get_am_pm(int& h, iter_type& b, iter_type e, std::ios_base::iostate& err, const std::ctype& ct) const { const string_type* ap = am_pm(); if (ap[0].size() + ap[1].size() == 0) { err |= ios_base::failbit; return; } ptrdiff_t i = detail::scan_keyword(b, e, ap, ap+2, ct, err, false) - ap; if (i == 0 && h == 12) h = 0; else if (i == 1 && h < 12) h += 12; } #endif InputIterator get( iter_type b, iter_type e, std::ios_base& iob, std::ios_base::iostate& err, std::tm* tm, char fmt, char) const { err = std::ios_base::goodbit; const std::ctype& ct = std::use_facet >(iob.getloc()); switch (fmt) { case 'a': case 'A': { std::tm tm2; std::memset(&tm2, 0, sizeof(std::tm)); that_.get_weekday(b, e, iob, err, &tm2); //tm->tm_wday = tm2.tm_wday; } break; case 'b': case 'B': case 'h': { std::tm tm2; std::memset(&tm2, 0, sizeof(std::tm)); that_.get_monthname(b, e, iob, err, &tm2); //tm->tm_mon = tm2.tm_mon; } break; // case 'c': // { // const string_type& fm = c(); // b = get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size()); // } // break; case 'd': case 'e': get_day(tm->tm_mday, b, e, err, ct); break; case 'D': { const char_type fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); } break; case 'F': { const char_type fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); } break; case 'H': get_hour(tm->tm_hour, b, e, err, ct); break; case 'I': get_12_hour(tm->tm_hour, b, e, err, ct); break; case 'j': get_day_year_num(tm->tm_yday, b, e, err, ct); break; case 'm': get_month(tm->tm_mon, b, e, err, ct); break; case 'M': get_minute(tm->tm_min, b, e, err, ct); break; case 'n': case 't': get_white_space(b, e, err, ct); break; // case 'p': // get_am_pm(tm->tm_hour, b, e, err, ct); // break; case 'r': { const char_type fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); } break; case 'R': { const char_type fm[] = {'%', 'H', ':', '%', 'M'}; b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); } break; case 'S': get_second(tm->tm_sec, b, e, err, ct); break; case 'T': { const char_type fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); } break; case 'w': { get_weekday(tm->tm_wday, b, e, err, ct); } break; case 'x': return that_.get_date(b, e, iob, err, tm); // case 'X': // return that_.get_time(b, e, iob, err, tm); // { // const string_type& fm = X(); // b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size()); // } // break; // case 'y': // get_year(tm->tm_year, b, e, err, ct); break; case 'Y': get_year4(tm->tm_year, b, e, err, ct); break; case '%': get_percent(b, e, err, ct); break; default: err |= std::ios_base::failbit; } return b; } InputIterator get( iter_type b, iter_type e, std::ios_base& iob, std::ios_base::iostate& err, std::tm* tm, const char_type* fmtb, const char_type* fmte) const { const std::ctype& ct = std::use_facet >(iob.getloc()); err = std::ios_base::goodbit; while (fmtb != fmte && err == std::ios_base::goodbit) { if (b == e) { err = std::ios_base::failbit; break; } if (ct.narrow(*fmtb, 0) == '%') { if (++fmtb == fmte) { err = std::ios_base::failbit; break; } char cmd = ct.narrow(*fmtb, 0); char opt = '\0'; if (cmd == 'E' || cmd == '0') { if (++fmtb == fmte) { err = std::ios_base::failbit; break; } opt = cmd; cmd = ct.narrow(*fmtb, 0); } b = get(b, e, iob, err, tm, cmd, opt); ++fmtb; } else if (ct.is(std::ctype_base::space, *fmtb)) { for (++fmtb; fmtb != fmte && ct.is(std::ctype_base::space, *fmtb); ++fmtb) ; for ( ; b != e && ct.is(std::ctype_base::space, *b); ++b) ; } else if (ct.toupper(*b) == ct.toupper(*fmtb)) { ++b; ++fmtb; } else err = std::ios_base::failbit; } if (b == e) err |= std::ios_base::eofbit; return b; } }; template class time_manip: public manip > { std::basic_string fmt_; timezone tz_; public: time_manip(timezone tz, std::basic_string fmt) // todo move semantics : fmt_(fmt), tz_(tz) { } /** * Change the timezone and time format ios state; */ void operator()(std::ios_base &ios) const { set_time_fmt (ios, fmt_); set_timezone(ios, tz_); } }; class time_man: public manip { timezone tz_; public: time_man(timezone tz) // todo move semantics : tz_(tz) { } /** * Change the timezone and time format ios state; */ void operator()(std::ios_base &ios) const { //set_time_fmt(ios, ""); set_timezone(ios, tz_); } }; } template inline detail::time_manip time_fmt(timezone tz, const CharT* fmt) { return detail::time_manip(tz, fmt); } template inline detail::time_manip time_fmt(timezone tz, std::basic_string fmt) { // todo move semantics return detail::time_manip(tz, fmt); } inline detail::time_man time_fmt(timezone f) { return detail::time_man(f); } /** * time_fmt_io_saver i/o saver. * * See Boost.IO i/o state savers for a motivating compression. */ template > struct time_fmt_io_saver { //! the type of the state to restore //typedef std::basic_ostream state_type; typedef std::ios_base state_type; //! the type of aspect to save typedef std::basic_string aspect_type; /** * Explicit construction from an i/o stream. * * Store a reference to the i/o stream and the value of the associated @c time format . */ explicit time_fmt_io_saver(state_type &s) : s_save_(s), a_save_(get_time_fmt(s_save_)) { } /** * Construction from an i/o stream and a @c time format to restore. * * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter. */ time_fmt_io_saver(state_type &s, aspect_type new_value) : s_save_(s), a_save_(get_time_fmt(s_save_)) { set_time_fmt(s_save_, new_value); } /** * Destructor. * * Restores the i/o stream with the format to be restored. */ ~time_fmt_io_saver() { this->restore(); } /** * Restores the i/o stream with the time format to be restored. */ void restore() { set_time_fmt(s_save_, a_save_); } private: state_type& s_save_; aspect_type a_save_; }; /** * timezone_io_saver i/o saver. * * See Boost.IO i/o state savers for a motivating compression. */ struct timezone_io_saver { //! the type of the state to restore typedef std::ios_base state_type; //! the type of aspect to save typedef timezone aspect_type; /** * Explicit construction from an i/o stream. * * Store a reference to the i/o stream and the value of the associated @c timezone. */ explicit timezone_io_saver(state_type &s) : s_save_(s), a_save_(get_timezone(s_save_)) { } /** * Construction from an i/o stream and a @c timezone to restore. * * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter. */ timezone_io_saver(state_type &s, aspect_type new_value) : s_save_(s), a_save_(get_timezone(s_save_)) { set_timezone(s_save_, new_value); } /** * Destructor. * * Restores the i/o stream with the format to be restored. */ ~timezone_io_saver() { this->restore(); } /** * Restores the i/o stream with the timezone to be restored. */ void restore() { set_timezone(s_save_, a_save_); } private: timezone_io_saver& operator=(timezone_io_saver const& rhs) ; state_type& s_save_; aspect_type a_save_; }; /** * * @param os * @param tp * @Effects Behaves as a formatted output function. After constructing a @c sentry object, if the @ sentry * converts to true, calls to @c facet.put(os,os,os.fill(),tp) where @c facet is the @c time_point_put * facet associated to @c os or a new created instance of the default @c time_point_put facet. * @return @c os. */ template std::basic_ostream& operator<<(std::basic_ostream& os, const time_point& tp) { bool failed = false; BOOST_TRY { std::ios_base::iostate err = std::ios_base::goodbit; BOOST_TRY { typename std::basic_ostream::sentry opfx(os); if (bool(opfx)) { if (!std::has_facet >(os.getloc())) { if (time_point_put ().put(os, os, os.fill(), tp) .failed()) { err = std::ios_base::badbit; } } else { if (std::use_facet >(os.getloc()) .put(os, os, os.fill(), tp).failed()) { err = std::ios_base::badbit; } } os.width(0); } } BOOST_CATCH (...) { bool flag = false; BOOST_TRY { os.setstate(std::ios_base::failbit); } BOOST_CATCH (const std::ios_base::failure& ) { flag = true; } BOOST_CATCH_END if (flag) throw; } BOOST_CATCH_END if (err) os.setstate(err); return os; } BOOST_CATCH (...) { failed = true; } BOOST_CATCH_END if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit); return os; } template std::basic_istream& operator>>(std::basic_istream& is, time_point& tp) { std::ios_base::iostate err = std::ios_base::goodbit; BOOST_TRY { typename std::basic_istream::sentry ipfx(is); if (bool(ipfx)) { if (!std::has_facet >(is.getloc())) { time_point_get ().get(is, std::istreambuf_iterator(), is, err, tp); } else { std::use_facet >(is.getloc()).get(is, std::istreambuf_iterator(), is, err, tp); } } } BOOST_CATCH (...) { bool flag = false; BOOST_TRY { is.setstate(std::ios_base::failbit); } BOOST_CATCH (const std::ios_base::failure& ) { flag = true; } BOOST_CATCH_END if (flag) throw; } BOOST_CATCH_END if (err) is.setstate(err); return is; } namespace detail { //#if defined BOOST_CHRONO_INTERNAL_TIMEGM inline int32_t is_leap(int32_t year) { if(year % 400 == 0) return 1; if(year % 100 == 0) return 0; if(year % 4 == 0) return 1; return 0; } inline int32_t days_from_0(int32_t year) { year--; return 365 * year + (year / 400) - (year/100) + (year / 4); } inline int32_t days_from_1970(int32_t year) { static const int32_t days_from_0_to_1970 = days_from_0(1970); return days_from_0(year) - days_from_0_to_1970; } inline int32_t days_from_1jan(int32_t year,int32_t month,int32_t day) { static const int32_t days[2][12] = { { 0,31,59,90,120,151,181,212,243,273,304,334}, { 0,31,60,91,121,152,182,213,244,274,305,335} }; return days[is_leap(year)][month-1] + day - 1; } inline time_t internal_timegm(std::tm const *t) { int year = t->tm_year + 1900; int month = t->tm_mon; if(month > 11) { year += month/12; month %= 12; } else if(month < 0) { int years_diff = (-month + 11)/12; year -= years_diff; month+=12 * years_diff; } month++; int day = t->tm_mday; int day_of_year = days_from_1jan(year,month,day); int days_since_epoch = days_from_1970(year) + day_of_year ; time_t seconds_in_day = 3600 * 24; time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec; return result; } //#endif /** * from_ymd could be made more efficient by using a table * day_count_table indexed by the y%400. * This table could contain the day_count * by*365 + by/4 - by/100 + by/400 * * from_ymd = (by/400)*days_by_400_years+day_count_table[by%400] + * days_in_year_before[is_leap_table[by%400]][m-1] + d; */ inline unsigned days_before_years(int32_t y) { return y * 365 + y / 4 - y / 100 + y / 400; } // Returns year/month/day triple in civil calendar // Preconditions: z is number of days since 1970-01-01 and is in the range: // [numeric_limits::min(), numeric_limits::max()-719468]. template //constexpr void inline civil_from_days(Int z, Int& y, unsigned& m, unsigned& d) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG(std::numeric_limits::digits >= 18, "This algorithm has not been ported to a 16 bit unsigned integer"); BOOST_STATIC_ASSERT_MSG(std::numeric_limits::digits >= 20, "This algorithm has not been ported to a 16 bit signed integer"); z += 719468; const Int era = (z >= 0 ? z : z - 146096) / 146097; const unsigned doe = static_cast(z - era * 146097); // [0, 146096] const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] y = static_cast(yoe) + era * 400; const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] const unsigned mp = (5*doy + 2)/153; // [0, 11] d = doy - (153*mp+2)/5 + 1; // [1, 31] m = mp + (mp < 10 ? 3 : -9); // [1, 12] y += (m <= 2); --m; } inline std::tm * internal_gmtime(std::time_t const* t, std::tm *tm) { if (t==0) return 0; if (tm==0) return 0; #if 0 static const unsigned char day_of_year_month[2][366] = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 } }; static const int32_t days_in_year_before[2][13] = { { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } }; #endif const time_t seconds_in_day = 3600 * 24; int32_t days_since_epoch = static_cast(*t / seconds_in_day); int32_t hms = static_cast(*t - seconds_in_day*days_since_epoch); if (hms < 0) { days_since_epoch-=1; hms = seconds_in_day+hms; } #if 0 int32_t x = days_since_epoch; int32_t y = static_cast (static_cast (x + 2) * 400 / 146097); const int32_t ym1 = y - 1; int32_t doy = x - days_before_years(y); const int32_t doy1 = x - days_before_years(ym1); const int32_t N = std::numeric_limits::digits - 1; const int32_t mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal const int32_t mask0 = ~mask1; doy = (doy & mask0) | (doy1 & mask1); y = (y & mask0) | (ym1 & mask1); //y -= 32767 + 2; y += 70; tm->tm_year=y; const int32_t leap = is_leap(y); tm->tm_mon = day_of_year_month[leap][doy]-1; tm->tm_mday = doy - days_in_year_before[leap][tm->tm_mon] ; #else int32_t y; unsigned m, d; civil_from_days(days_since_epoch, y, m, d); tm->tm_year=y-1900; tm->tm_mon=m; tm->tm_mday=d; #endif tm->tm_hour = hms / 3600; const int ms = hms % 3600; tm->tm_min = ms / 60; tm->tm_sec = ms % 60; tm->tm_isdst = -1; (void)mktime(tm); return tm; } } // detail #ifndef BOOST_CHRONO_NO_UTC_TIMEPOINT #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT template std::basic_ostream& operator<<(std::basic_ostream& os, const time_point& tp) { typename std::basic_ostream::sentry ok(os); if (bool(ok)) { bool failed = false; BOOST_TRY { const CharT* pb = 0; //nullptr; const CharT* pe = pb; std::basic_string fmt = get_time_fmt (os); pb = fmt.data(); pe = pb + fmt.size(); timezone tz = get_timezone(os); std::locale loc = os.getloc(); time_t t = system_clock::to_time_t(time_point_cast(tp)); std::tm tm; std::memset(&tm, 0, sizeof(std::tm)); if (tz == timezone::local) { #if defined BOOST_WINDOWS && ! defined(__CYGWIN__) #if BOOST_MSVC < 1400 // localtime_s doesn't exist in vc7.1 std::tm *tmp = 0; if ((tmp=localtime(&t)) == 0) failed = true; else tm =*tmp; # else if (localtime_s(&tm, &t) != 0) failed = true; # endif #else if (localtime_r(&t, &tm) == 0) failed = true; #endif } else { #if defined BOOST_CHRONO_INTERNAL_GMTIME if (detail::internal_gmtime(&t, &tm) == 0) failed = true; #elif defined BOOST_WINDOWS && ! defined(__CYGWIN__) std::tm *tmp = 0; if((tmp = gmtime(&t)) == 0) failed = true; else tm = *tmp; #else if (gmtime_r(&t, &tm) == 0) failed = true; tm.tm_isdst = -1; (void)mktime(&tm); #endif } if (!failed) { const std::time_put& tpf = std::use_facet >(loc); if (pb == pe) { CharT pattern[] = { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' }; pb = pattern; pe = pb + sizeof (pattern) / sizeof(CharT); failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); if (!failed) { duration d = tp - system_clock::from_time_t(t) + seconds(tm.tm_sec); if (d.count() < 10) os << CharT('0'); //if (! os.good()) { // throw "exception"; //} std::ios::fmtflags flgs = os.flags(); os.setf(std::ios::fixed, std::ios::floatfield); //if (! os.good()) { //throw "exception"; //} os.precision(9); os << d.count(); //if (! os.good()) { //throw "exception"; //} os.flags(flgs); if (tz == timezone::local) { CharT sub_pattern[] = { ' ', '%', 'z' }; pb = sub_pattern; pe = pb + +sizeof (sub_pattern) / sizeof(CharT); failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); } else { CharT sub_pattern[] = { ' ', '+', '0', '0', '0', '0', 0 }; os << sub_pattern; } } } else { failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); } } } BOOST_CATCH (...) { failed = true; } BOOST_CATCH_END if (failed) { os.setstate(std::ios_base::failbit | std::ios_base::badbit); } } return os; } #endif namespace detail { template minutes extract_z(InputIterator& b, InputIterator e, std::ios_base::iostate& err, const std::ctype& ct) { int min = 0; if (b != e) { char cn = ct.narrow(*b, 0); if (cn != '+' && cn != '-') { err |= std::ios_base::failbit; return minutes(0); } int sn = cn == '-' ? -1 : 1; int hr = 0; for (int i = 0; i < 2; ++i) { if (++b == e) { err |= std::ios_base::eofbit | std::ios_base::failbit; return minutes(0); } cn = ct.narrow(*b, 0); if (! ('0' <= cn && cn <= '9')) { err |= std::ios_base::failbit; return minutes(0); } hr = hr * 10 + cn - '0'; } for (int i = 0; i < 2; ++i) { if (++b == e) { err |= std::ios_base::eofbit | std::ios_base::failbit; return minutes(0); } cn = ct.narrow(*b, 0); if (! ('0' <= cn && cn <= '9')) { err |= std::ios_base::failbit; return minutes(0); } min = min * 10 + cn - '0'; } if (++b == e) { err |= std::ios_base::eofbit; } min += hr * 60; min *= sn; } else { err |= std::ios_base::eofbit | std::ios_base::failbit; } return minutes(min); } } // detail #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT template std::basic_istream& operator>>(std::basic_istream& is, time_point& tp) { typename std::basic_istream::sentry ok(is); if (bool(ok)) { std::ios_base::iostate err = std::ios_base::goodbit; BOOST_TRY { const CharT* pb = 0; //nullptr; const CharT* pe = pb; std::basic_string fmt = get_time_fmt (is); pb = fmt.data(); pe = pb + fmt.size(); timezone tz = get_timezone(is); std::locale loc = is.getloc(); const std::time_get& tg = std::use_facet >(loc); const std::ctype& ct = std::use_facet >(loc); tm tm; // {0} std::memset(&tm, 0, sizeof(std::tm)); typedef std::istreambuf_iterator It; if (pb == pe) { CharT pattern[] = { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' }; pb = pattern; pe = pb + sizeof (pattern) / sizeof(CharT); #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET const detail::time_get& dtg(tg); dtg.get(is, 0, is, err, &tm, pb, pe); #else tg.get(is, 0, is, err, &tm, pb, pe); #endif if (err & std::ios_base::failbit) goto exit; fractional_seconds sec; CharT c = CharT(); std::ios::fmtflags flgs = is.flags(); is.setf(std::ios::fixed, std::ios::floatfield); is.precision(9); is >> sec; is.flags(flgs); if (is.fail()) { err |= std::ios_base::failbit; goto exit; } It i(is); It eof; c = *i; if (++i == eof || c != ' ') { err |= std::ios_base::failbit; goto exit; } minutes min = detail::extract_z(i, eof, err, ct); if (err & std::ios_base::failbit) goto exit; time_t t; #if defined BOOST_CHRONO_INTERNAL_TIMEGM t = detail::internal_timegm(&tm); #else t = timegm(&tm); #endif tp = time_point_cast( system_clock::from_time_t(t) - min + round (duration (sec)) ); } else { const CharT z[2] = { '%', 'z' }; const CharT* fz = std::search(pb, pe, z, z + 2); #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET const detail::time_get& dtg(tg); dtg.get(is, 0, is, err, &tm, pb, fz); #else tg.get(is, 0, is, err, &tm, pb, fz); #endif minutes minu(0); if (fz != pe) { if (err != std::ios_base::goodbit) { err |= std::ios_base::failbit; goto exit; } It i(is); It eof; minu = detail::extract_z(i, eof, err, ct); if (err & std::ios_base::failbit) goto exit; if (fz + 2 != pe) { if (err != std::ios_base::goodbit) { err |= std::ios_base::failbit; goto exit; } #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET const detail::time_get& dtg(tg); dtg.get(is, 0, is, err, &tm, fz + 2, pe); #else tg.get(is, 0, is, err, &tm, fz + 2, pe); #endif if (err & std::ios_base::failbit) goto exit; } } tm.tm_isdst = -1; time_t t; if (tz == timezone::utc || fz != pe) { #if defined BOOST_CHRONO_INTERNAL_TIMEGM t = detail::internal_timegm(&tm); #else t = timegm(&tm); #endif } else { t = mktime(&tm); } tp = time_point_cast( system_clock::from_time_t(t) - minu ); } } BOOST_CATCH (...) { err |= std::ios_base::badbit | std::ios_base::failbit; } BOOST_CATCH_END exit: is.setstate(err); } return is; } #endif #endif //UTC } // chrono } #endif // header