1 // (C) Copyright Howard Hinnant
2 // (C) Copyright 2010-2011 Vicente J. Botet Escriba
3 // Use, modification and distribution are subject to the Boost Software License,
4 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt).
7 //===-------------------------- locale ------------------------------------===//
9 // The LLVM Compiler Infrastructure
11 // This file is dual licensed under the MIT and the University of Illinois Open
12 // Source Licenses. See LICENSE.TXT for details.
14 //===----------------------------------------------------------------------===//
16 // This code was adapted by Vicente from Howard Hinnant's experimental work
17 // on chrono i/o to Boost and some functions from libc++/locale to emulate the missing time_get::get()
19 #ifndef BOOST_CHRONO_IO_TIME_POINT_IO_HPP
20 #define BOOST_CHRONO_IO_TIME_POINT_IO_HPP
22 #include <boost/chrono/io/time_point_put.hpp>
23 #include <boost/chrono/io/time_point_get.hpp>
24 #include <boost/chrono/io/duration_io.hpp>
25 #include <boost/chrono/io/ios_base_state.hpp>
26 #include <boost/chrono/io/utility/manip_base.hpp>
27 #include <boost/chrono/time_point.hpp>
28 #include <boost/chrono/clock_string.hpp>
29 #include <boost/chrono/round.hpp>
30 #include <boost/chrono/detail/scan_keyword.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/detail/no_exceptions_support.hpp>
37 #if ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \
38 || (defined(sun) || defined(__sun)) \
39 || (defined __IBMCPP__) \
40 || defined __ANDROID__ \
41 || defined __QNXNTO__ \
42 || (defined(_AIX) && defined __GNUC__)
43 #define BOOST_CHRONO_INTERNAL_TIMEGM
46 #if (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \
47 || ( (defined(sun) || defined(__sun)) && defined __GNUC__) \
48 || (defined __IBMCPP__) \
49 || defined __ANDROID__ \
50 || (defined(_AIX) && defined __GNUC__)
51 #define BOOST_CHRONO_INTERNAL_GMTIME
54 #define BOOST_CHRONO_USES_INTERNAL_TIME_GET
60 typedef double fractional_seconds;
65 template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> >
68 std::time_get<CharT> const &that_;
69 time_get(std::time_get<CharT> const& that) : that_(that) {}
71 typedef std::time_get<CharT> facet;
72 typedef typename facet::iter_type iter_type;
73 typedef typename facet::char_type char_type;
74 typedef std::basic_string<char_type> string_type;
78 InputIterator& b, InputIterator e,
79 std::ios_base::iostate& err,
80 const std::ctype<CharT>& ct,
83 // Precondition: n >= 1
86 err |= std::ios_base::eofbit | std::ios_base::failbit;
91 if (!ct.is(std::ctype_base::digit, c))
93 err |= std::ios_base::failbit;
96 int r = ct.narrow(c, 0) - '0';
97 for (++b, --n; b != e && n > 0; ++b, --n)
101 if (!ct.is(std::ctype_base::digit, c))
103 r = r * 10 + ct.narrow(c, 0) - '0';
106 err |= std::ios_base::eofbit;
113 iter_type& b, iter_type e,
114 std::ios_base::iostate& err,
115 const std::ctype<char_type>& ct) const
117 int t = get_up_to_n_digits(b, e, err, ct, 2);
118 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 31)
121 err |= std::ios_base::failbit;
126 iter_type& b, iter_type e,
127 std::ios_base::iostate& err,
128 const std::ctype<char_type>& ct) const
130 int t = get_up_to_n_digits(b, e, err, ct, 2);
131 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12)
134 err |= std::ios_base::failbit;
138 void get_year4(int& y,
139 iter_type& b, iter_type e,
140 std::ios_base::iostate& err,
141 const std::ctype<char_type>& ct) const
143 int t = get_up_to_n_digits(b, e, err, ct, 4);
144 if (!(err & std::ios_base::failbit))
150 iter_type& b, iter_type e,
151 std::ios_base::iostate& err,
152 const std::ctype<char_type>& ct) const
154 int t = get_up_to_n_digits(b, e, err, ct, 2);
155 if (!(err & std::ios_base::failbit) && t <= 23)
158 err |= std::ios_base::failbit;
163 iter_type& b, iter_type e,
164 std::ios_base::iostate& err,
165 const std::ctype<char_type>& ct) const
167 int t = get_up_to_n_digits(b, e, err, ct, 2);
168 if (!(err & std::ios_base::failbit) && t <= 59)
171 err |= std::ios_base::failbit;
174 void get_second(int& s,
175 iter_type& b, iter_type e,
176 std::ios_base::iostate& err,
177 const std::ctype<char_type>& ct) const
179 int t = get_up_to_n_digits(b, e, err, ct, 2);
180 if (!(err & std::ios_base::failbit) && t <= 60)
183 err |= std::ios_base::failbit;
186 void get_white_space(iter_type& b, iter_type e,
187 std::ios_base::iostate& err,
188 const std::ctype<char_type>& ct) const
190 for (; b != e && ct.is(std::ctype_base::space, *b); ++b)
193 err |= std::ios_base::eofbit;
196 void get_12_hour(int& h,
197 iter_type& b, iter_type e,
198 std::ios_base::iostate& err,
199 const std::ctype<char_type>& ct) const
201 int t = get_up_to_n_digits(b, e, err, ct, 2);
202 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12)
205 err |= std::ios_base::failbit;
208 void get_percent(iter_type& b, iter_type e,
209 std::ios_base::iostate& err,
210 const std::ctype<char_type>& ct) const
214 err |= std::ios_base::eofbit | std::ios_base::failbit;
217 if (ct.narrow(*b, 0) != '%')
218 err |= std::ios_base::failbit;
220 err |= std::ios_base::eofbit;
223 void get_day_year_num(int& d,
224 iter_type& b, iter_type e,
225 std::ios_base::iostate& err,
226 const std::ctype<char_type>& ct) const
228 int t = get_up_to_n_digits(b, e, err, ct, 3);
229 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 366)
232 err |= std::ios_base::failbit;
237 iter_type& b, iter_type e,
238 std::ios_base::iostate& err,
239 const std::ctype<char_type>& ct) const
241 int t = get_up_to_n_digits(b, e, err, ct, 1);
242 if (!(err & std::ios_base::failbit) && t <= 6)
245 err |= std::ios_base::failbit;
251 iter_type& b, iter_type e,
252 std::ios_base::iostate& err,
253 const std::ctype<char_type>& ct) const
255 const string_type* ap = am_pm();
256 if (ap[0].size() + ap[1].size() == 0)
258 err |= ios_base::failbit;
261 ptrdiff_t i = detail::scan_keyword(b, e, ap, ap+2, ct, err, false) - ap;
262 if (i == 0 && h == 12)
264 else if (i == 1 && h < 12)
271 iter_type b, iter_type e,
273 std::ios_base::iostate& err,
275 char fmt, char) const
277 err = std::ios_base::goodbit;
278 const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
286 std::memset(&tm2, 0, sizeof(std::tm));
287 that_.get_weekday(b, e, iob, err, &tm2);
288 //tm->tm_wday = tm2.tm_wday;
296 std::memset(&tm2, 0, sizeof(std::tm));
297 that_.get_monthname(b, e, iob, err, &tm2);
298 //tm->tm_mon = tm2.tm_mon;
303 // const string_type& fm = c();
304 // b = get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
309 get_day(tm->tm_mday, b, e, err, ct);
313 const char_type fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
314 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
319 const char_type fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
320 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
324 get_hour(tm->tm_hour, b, e, err, ct);
327 get_12_hour(tm->tm_hour, b, e, err, ct);
330 get_day_year_num(tm->tm_yday, b, e, err, ct);
333 get_month(tm->tm_mon, b, e, err, ct);
336 get_minute(tm->tm_min, b, e, err, ct);
340 get_white_space(b, e, err, ct);
343 // get_am_pm(tm->tm_hour, b, e, err, ct);
347 const char_type fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
348 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
353 const char_type fm[] = {'%', 'H', ':', '%', 'M'};
354 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
358 get_second(tm->tm_sec, b, e, err, ct);
362 const char_type fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
363 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
368 get_weekday(tm->tm_wday, b, e, err, ct);
372 return that_.get_date(b, e, iob, err, tm);
374 // return that_.get_time(b, e, iob, err, tm);
376 // const string_type& fm = X();
377 // b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
381 // get_year(tm->tm_year, b, e, err, ct);
384 get_year4(tm->tm_year, b, e, err, ct);
387 get_percent(b, e, err, ct);
390 err |= std::ios_base::failbit;
397 iter_type b, iter_type e,
399 std::ios_base::iostate& err, std::tm* tm,
400 const char_type* fmtb, const char_type* fmte) const
402 const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
403 err = std::ios_base::goodbit;
404 while (fmtb != fmte && err == std::ios_base::goodbit)
408 err = std::ios_base::failbit;
411 if (ct.narrow(*fmtb, 0) == '%')
415 err = std::ios_base::failbit;
418 char cmd = ct.narrow(*fmtb, 0);
420 if (cmd == 'E' || cmd == '0')
424 err = std::ios_base::failbit;
428 cmd = ct.narrow(*fmtb, 0);
430 b = get(b, e, iob, err, tm, cmd, opt);
433 else if (ct.is(std::ctype_base::space, *fmtb))
435 for (++fmtb; fmtb != fmte && ct.is(std::ctype_base::space, *fmtb); ++fmtb)
437 for ( ; b != e && ct.is(std::ctype_base::space, *b); ++b)
440 else if (ct.toupper(*b) == ct.toupper(*fmtb))
446 err = std::ios_base::failbit;
449 err |= std::ios_base::eofbit;
456 template <class CharT>
457 class time_manip: public manip<time_manip<CharT> >
459 std::basic_string<CharT> fmt_;
463 time_manip(timezone tz, std::basic_string<CharT> fmt)
464 // todo move semantics
471 * Change the timezone and time format ios state;
473 void operator()(std::ios_base &ios) const
475 set_time_fmt<CharT> (ios, fmt_);
476 set_timezone(ios, tz_);
480 class time_man: public manip<time_man>
485 time_man(timezone tz)
486 // todo move semantics
493 * Change the timezone and time format ios state;
495 void operator()(std::ios_base &ios) const
497 //set_time_fmt<typename out_stream::char_type>(ios, "");
498 set_timezone(ios, tz_);
504 template <class CharT>
505 inline detail::time_manip<CharT> time_fmt(timezone tz, const CharT* fmt)
507 return detail::time_manip<CharT>(tz, fmt);
510 template <class CharT>
511 inline detail::time_manip<CharT> time_fmt(timezone tz, std::basic_string<CharT> fmt)
513 // todo move semantics
514 return detail::time_manip<CharT>(tz, fmt);
517 inline detail::time_man time_fmt(timezone f)
519 return detail::time_man(f);
523 * time_fmt_io_saver i/o saver.
525 * See Boost.IO i/o state savers for a motivating compression.
527 template <typename CharT = char, typename Traits = std::char_traits<CharT> >
528 struct time_fmt_io_saver
531 //! the type of the state to restore
532 //typedef std::basic_ostream<CharT, Traits> state_type;
533 typedef std::ios_base state_type;
535 //! the type of aspect to save
536 typedef std::basic_string<CharT, Traits> aspect_type;
539 * Explicit construction from an i/o stream.
541 * Store a reference to the i/o stream and the value of the associated @c time format .
543 explicit time_fmt_io_saver(state_type &s) :
544 s_save_(s), a_save_(get_time_fmt<CharT>(s_save_))
549 * Construction from an i/o stream and a @c time format to restore.
551 * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter.
553 time_fmt_io_saver(state_type &s, aspect_type new_value) :
554 s_save_(s), a_save_(get_time_fmt<CharT>(s_save_))
556 set_time_fmt(s_save_, new_value);
562 * Restores the i/o stream with the format to be restored.
570 * Restores the i/o stream with the time format to be restored.
574 set_time_fmt(s_save_, a_save_);
582 * timezone_io_saver i/o saver.
584 * See Boost.IO i/o state savers for a motivating compression.
586 struct timezone_io_saver
589 //! the type of the state to restore
590 typedef std::ios_base state_type;
591 //! the type of aspect to save
592 typedef timezone aspect_type;
595 * Explicit construction from an i/o stream.
597 * Store a reference to the i/o stream and the value of the associated @c timezone.
599 explicit timezone_io_saver(state_type &s) :
600 s_save_(s), a_save_(get_timezone(s_save_))
605 * Construction from an i/o stream and a @c timezone to restore.
607 * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter.
609 timezone_io_saver(state_type &s, aspect_type new_value) :
610 s_save_(s), a_save_(get_timezone(s_save_))
612 set_timezone(s_save_, new_value);
618 * Restores the i/o stream with the format to be restored.
626 * Restores the i/o stream with the timezone to be restored.
630 set_timezone(s_save_, a_save_);
633 timezone_io_saver& operator=(timezone_io_saver const& rhs) ;
643 * @Effects Behaves as a formatted output function. After constructing a @c sentry object, if the @ sentry
644 * converts to true, calls to @c facet.put(os,os,os.fill(),tp) where @c facet is the @c time_point_put<CharT>
645 * facet associated to @c os or a new created instance of the default @c time_point_put<CharT> facet.
648 template <class CharT, class Traits, class Clock, class Duration>
649 std::basic_ostream<CharT, Traits>&
650 operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<Clock, Duration>& tp)
656 std::ios_base::iostate err = std::ios_base::goodbit;
659 typename std::basic_ostream<CharT, Traits>::sentry opfx(os);
662 if (!std::has_facet<time_point_put<CharT> >(os.getloc()))
664 if (time_point_put<CharT> ().put(os, os, os.fill(), tp) .failed())
666 err = std::ios_base::badbit;
671 if (std::use_facet<time_point_put<CharT> >(os.getloc()) .put(os, os, os.fill(), tp).failed())
673 err = std::ios_base::badbit;
684 os.setstate(std::ios_base::failbit);
686 BOOST_CATCH (std::ios_base::failure )
694 if (err) os.setstate(err);
702 if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit);
706 template <class CharT, class Traits, class Clock, class Duration>
707 std::basic_istream<CharT, Traits>&
708 operator>>(std::basic_istream<CharT, Traits>& is, time_point<Clock, Duration>& tp)
710 std::ios_base::iostate err = std::ios_base::goodbit;
714 typename std::basic_istream<CharT, Traits>::sentry ipfx(is);
717 if (!std::has_facet<time_point_get<CharT> >(is.getloc()))
719 time_point_get<CharT> ().get(is, std::istreambuf_iterator<CharT, Traits>(), is, err, tp);
723 std::use_facet<time_point_get<CharT> >(is.getloc()).get(is, std::istreambuf_iterator<CharT, Traits>(), is,
733 is.setstate(std::ios_base::failbit);
735 BOOST_CATCH (std::ios_base::failure )
743 if (err) is.setstate(err);
751 //#if defined BOOST_CHRONO_INTERNAL_TIMEGM
753 inline int32_t is_leap(int32_t year)
763 inline int32_t days_from_0(int32_t year)
766 return 365 * year + (year / 400) - (year/100) + (year / 4);
768 inline int32_t days_from_1970(int32_t year)
770 static const int days_from_0_to_1970 = days_from_0(1970);
771 return days_from_0(year) - days_from_0_to_1970;
773 inline int32_t days_from_1jan(int32_t year,int32_t month,int32_t day)
775 static const int32_t days[2][12] =
777 { 0,31,59,90,120,151,181,212,243,273,304,334},
778 { 0,31,60,91,121,152,182,213,244,274,305,335}
781 return days[is_leap(year)][month-1] + day - 1;
784 inline time_t internal_timegm(std::tm const *t)
786 int year = t->tm_year + 1900;
787 int month = t->tm_mon;
795 int years_diff = (-month + 11)/12;
797 month+=12 * years_diff;
800 int day = t->tm_mday;
801 int day_of_year = days_from_1jan(year,month,day);
802 int days_since_epoch = days_from_1970(year) + day_of_year ;
804 time_t seconds_in_day = 3600 * 24;
805 time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;
812 * from_ymd could be made more efficient by using a table
813 * day_count_table indexed by the y%400.
814 * This table could contain the day_count
815 * by*365 + by/4 - by/100 + by/400
817 * from_ymd = (by/400)*days_by_400_years+day_count_table[by%400] +
818 * days_in_year_before[is_leap_table[by%400]][m-1] + d;
820 inline unsigned days_before_years(int32_t y)
822 return y * 365 + y / 4 - y / 100 + y / 400;
825 // Returns year/month/day triple in civil calendar
826 // Preconditions: z is number of days since 1970-01-01 and is in the range:
827 // [numeric_limits<Int>::min(), numeric_limits<Int>::max()-719468].
831 inline civil_from_days(Int z, Int& y, unsigned& m, unsigned& d) BOOST_NOEXCEPT
833 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<unsigned>::digits >= 18,
834 "This algorithm has not been ported to a 16 bit unsigned integer");
835 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<Int>::digits >= 20,
836 "This algorithm has not been ported to a 16 bit signed integer");
838 const Int era = (z >= 0 ? z : z - 146096) / 146097;
839 const unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
840 const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
841 y = static_cast<Int>(yoe) + era * 400;
842 const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
843 const unsigned mp = (5*doy + 2)/153; // [0, 11]
844 d = doy - (153*mp+2)/5 + 1; // [1, 31]
845 m = mp + (mp < 10 ? 3 : -9); // [1, 12]
849 inline std::tm * internal_gmtime(std::time_t const* t, std::tm *tm)
855 static const unsigned char
856 day_of_year_month[2][366] =
858 { 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 },
860 { 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
864 static const int32_t days_in_year_before[2][13] =
866 { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
867 { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }
871 const time_t seconds_in_day = 3600 * 24;
872 int32_t days_since_epoch = static_cast<int32_t>(*t / seconds_in_day);
873 int32_t hms = static_cast<int32_t>(*t - seconds_in_day*days_since_epoch);
876 hms = seconds_in_day+hms;
880 int32_t x = days_since_epoch;
881 int32_t y = static_cast<int32_t> (static_cast<long long> (x + 2) * 400
883 const int32_t ym1 = y - 1;
884 int32_t doy = x - days_before_years(y);
885 const int32_t doy1 = x - days_before_years(ym1);
886 const int32_t N = std::numeric_limits<int>::digits - 1;
887 const int32_t mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal
888 const int32_t mask0 = ~mask1;
889 doy = (doy & mask0) | (doy1 & mask1);
890 y = (y & mask0) | (ym1 & mask1);
894 const int32_t leap = is_leap(y);
895 tm->tm_mon = day_of_year_month[leap][doy]-1;
896 tm->tm_mday = doy - days_in_year_before[leap][tm->tm_mon] ;
900 civil_from_days(days_since_epoch, y, m, d);
901 tm->tm_year=y-1900; tm->tm_mon=m; tm->tm_mday=d;
904 tm->tm_hour = hms / 3600;
905 const int ms = hms % 3600;
906 tm->tm_min = ms / 60;
907 tm->tm_sec = ms % 60;
915 #ifndef BOOST_CHRONO_NO_UTC_TIMEPOINT
917 #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT
919 template <class CharT, class Traits, class Duration>
920 std::basic_ostream<CharT, Traits>&
921 operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<system_clock, Duration>& tp)
923 typename std::basic_ostream<CharT, Traits>::sentry ok(os);
929 const CharT* pb = 0; //nullptr;
930 const CharT* pe = pb;
931 std::basic_string<CharT> fmt = get_time_fmt<CharT> (os);
933 pe = pb + fmt.size();
935 timezone tz = get_timezone(os);
936 std::locale loc = os.getloc();
937 time_t t = system_clock::to_time_t(time_point_cast<system_clock::duration>(tp));
939 std::memset(&tm, 0, sizeof(std::tm));
940 if (tz == timezone::local)
942 #if defined BOOST_WINDOWS && ! defined(__CYGWIN__)
943 #if BOOST_MSVC < 1400 // localtime_s doesn't exist in vc7.1
945 if ((tmp=localtime(&t)) == 0)
950 if (localtime_s(&tm, &t) != 0) failed = true;
953 if (localtime_r(&t, &tm) == 0) failed = true;
958 #if defined BOOST_CHRONO_INTERNAL_GMTIME
959 if (detail::internal_gmtime(&t, &tm) == 0) failed = true;
961 #elif defined BOOST_WINDOWS && ! defined(__CYGWIN__)
963 if((tmp = gmtime(&t)) == 0)
968 if (gmtime_r(&t, &tm) == 0) failed = true;
977 const std::time_put<CharT>& tpf = std::use_facet<std::time_put<CharT> >(loc);
981 { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' };
983 pe = pb + sizeof (pattern) / sizeof(CharT);
984 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
987 duration<fractional_seconds> d = tp - system_clock::from_time_t(t) + seconds(tm.tm_sec);
988 if (d.count() < 10) os << CharT('0');
990 // throw "exception";
992 std::ios::fmtflags flgs = os.flags();
993 os.setf(std::ios::fixed, std::ios::floatfield);
1000 //throw "exception";
1003 if (tz == timezone::local)
1005 CharT sub_pattern[] =
1008 pe = pb + +sizeof (sub_pattern) / sizeof(CharT);
1009 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
1013 CharT sub_pattern[] =
1014 { ' ', '+', '0', '0', '0', '0', 0 };
1021 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
1032 os.setstate(std::ios_base::failbit | std::ios_base::badbit);
1042 template <class CharT, class InputIterator>
1043 minutes extract_z(InputIterator& b, InputIterator e, std::ios_base::iostate& err, const std::ctype<CharT>& ct)
1048 char cn = ct.narrow(*b, 0);
1049 if (cn != '+' && cn != '-')
1051 err |= std::ios_base::failbit;
1054 int sn = cn == '-' ? -1 : 1;
1056 for (int i = 0; i < 2; ++i)
1060 err |= std::ios_base::eofbit | std::ios_base::failbit;
1063 cn = ct.narrow(*b, 0);
1064 if (! ('0' <= cn && cn <= '9'))
1066 err |= std::ios_base::failbit;
1069 hr = hr * 10 + cn - '0';
1071 for (int i = 0; i < 2; ++i)
1075 err |= std::ios_base::eofbit | std::ios_base::failbit;
1078 cn = ct.narrow(*b, 0);
1079 if (! ('0' <= cn && cn <= '9'))
1081 err |= std::ios_base::failbit;
1084 min = min * 10 + cn - '0';
1087 err |= std::ios_base::eofbit;
1094 err |= std::ios_base::eofbit | std::ios_base::failbit;
1096 return minutes(min);
1101 #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT
1103 template <class CharT, class Traits, class Duration>
1104 std::basic_istream<CharT, Traits>&
1105 operator>>(std::basic_istream<CharT, Traits>& is, time_point<system_clock, Duration>& tp)
1107 typename std::basic_istream<CharT, Traits>::sentry ok(is);
1110 std::ios_base::iostate err = std::ios_base::goodbit;
1113 const CharT* pb = 0; //nullptr;
1114 const CharT* pe = pb;
1115 std::basic_string<CharT> fmt = get_time_fmt<CharT> (is);
1117 pe = pb + fmt.size();
1119 timezone tz = get_timezone(is);
1120 std::locale loc = is.getloc();
1121 const std::time_get<CharT>& tg = std::use_facet<std::time_get<CharT> >(loc);
1122 const std::ctype<CharT>& ct = std::use_facet<std::ctype<CharT> >(loc);
1124 std::memset(&tm, 0, sizeof(std::tm));
1126 typedef std::istreambuf_iterator<CharT, Traits> It;
1130 { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' };
1132 pe = pb + sizeof (pattern) / sizeof(CharT);
1134 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1135 const detail::time_get<CharT>& dtg(tg);
1136 dtg.get(is, 0, is, err, &tm, pb, pe);
1138 tg.get(is, 0, is, err, &tm, pb, pe);
1140 if (err & std::ios_base::failbit) goto exit;
1141 fractional_seconds sec;
1143 std::ios::fmtflags flgs = is.flags();
1144 is.setf(std::ios::fixed, std::ios::floatfield);
1150 err |= std::ios_base::failbit;
1156 if (++i == eof || c != ' ')
1158 err |= std::ios_base::failbit;
1161 minutes min = detail::extract_z(i, eof, err, ct);
1163 if (err & std::ios_base::failbit) goto exit;
1166 #if defined BOOST_CHRONO_INTERNAL_TIMEGM
1167 t = detail::internal_timegm(&tm);
1171 tp = time_point_cast<Duration>(
1172 system_clock::from_time_t(t) - min + round<system_clock::duration> (duration<fractional_seconds> (sec))
1179 const CharT* fz = std::search(pb, pe, z, z + 2);
1180 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1181 const detail::time_get<CharT>& dtg(tg);
1182 dtg.get(is, 0, is, err, &tm, pb, fz);
1184 tg.get(is, 0, is, err, &tm, pb, fz);
1189 if (err != std::ios_base::goodbit)
1191 err |= std::ios_base::failbit;
1196 minu = detail::extract_z(i, eof, err, ct);
1197 if (err & std::ios_base::failbit) goto exit;
1200 if (err != std::ios_base::goodbit)
1202 err |= std::ios_base::failbit;
1205 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1206 const detail::time_get<CharT>& dtg(tg);
1207 dtg.get(is, 0, is, err, &tm, fz + 2, pe);
1209 tg.get(is, 0, is, err, &tm, fz + 2, pe);
1211 if (err & std::ios_base::failbit) goto exit;
1216 if (tz == timezone::utc || fz != pe)
1218 #if defined BOOST_CHRONO_INTERNAL_TIMEGM
1219 t = detail::internal_timegm(&tm);
1228 tp = time_point_cast<Duration>(
1229 system_clock::from_time_t(t) - minu
1235 err |= std::ios_base::badbit | std::ios_base::failbit;
1238 exit: is.setstate(err);