]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/chrono/include/boost/chrono/io/time_point_io.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / chrono / include / boost / chrono / io / time_point_io.hpp
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).
6
7 //===-------------------------- locale ------------------------------------===//
8 //
9 // The LLVM Compiler Infrastructure
10 //
11 // This file is dual licensed under the MIT and the University of Illinois Open
12 // Source Licenses. See LICENSE.TXT for details.
13 //
14 //===----------------------------------------------------------------------===//
15
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()
18
19 #ifndef BOOST_CHRONO_IO_TIME_POINT_IO_HPP
20 #define BOOST_CHRONO_IO_TIME_POINT_IO_HPP
21
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>
33 #include <cstring>
34 #include <locale>
35 #include <ctime>
36
37 #define BOOST_CHRONO_INTERNAL_TIMEGM \
38 ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \
39 || (defined(sun) || defined(__sun)) \
40 || (defined __IBMCPP__) \
41 || defined __ANDROID__ \
42 || defined __QNXNTO__ \
43 || (defined(_AIX) && defined __GNUC__)
44
45 #define BOOST_CHRONO_INTERNAL_GMTIME \
46 (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \
47 || ( (defined(sun) || defined(__sun)) && defined __GNUC__) \
48 || (defined __IBMCPP__) \
49 || defined __ANDROID__ \
50 || (defined(_AIX) && defined __GNUC__)
51
52 #define BOOST_CHRONO_USES_INTERNAL_TIME_GET
53
54 namespace boost
55 {
56 namespace chrono
57 {
58 typedef double fractional_seconds;
59 namespace detail
60 {
61
62
63 template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> >
64 struct time_get
65 {
66 std::time_get<CharT> const &that_;
67 time_get(std::time_get<CharT> const& that) : that_(that) {}
68
69 typedef std::time_get<CharT> facet;
70 typedef typename facet::iter_type iter_type;
71 typedef typename facet::char_type char_type;
72 typedef std::basic_string<char_type> string_type;
73
74 static int
75 get_up_to_n_digits(
76 InputIterator& b, InputIterator e,
77 std::ios_base::iostate& err,
78 const std::ctype<CharT>& ct,
79 int n)
80 {
81 // Precondition: n >= 1
82 if (b == e)
83 {
84 err |= std::ios_base::eofbit | std::ios_base::failbit;
85 return 0;
86 }
87 // get first digit
88 CharT c = *b;
89 if (!ct.is(std::ctype_base::digit, c))
90 {
91 err |= std::ios_base::failbit;
92 return 0;
93 }
94 int r = ct.narrow(c, 0) - '0';
95 for (++b, --n; b != e && n > 0; ++b, --n)
96 {
97 // get next digit
98 c = *b;
99 if (!ct.is(std::ctype_base::digit, c))
100 return r;
101 r = r * 10 + ct.narrow(c, 0) - '0';
102 }
103 if (b == e)
104 err |= std::ios_base::eofbit;
105 return r;
106 }
107
108
109 void get_day(
110 int& d,
111 iter_type& b, iter_type e,
112 std::ios_base::iostate& err,
113 const std::ctype<char_type>& ct) const
114 {
115 int t = get_up_to_n_digits(b, e, err, ct, 2);
116 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 31)
117 d = t;
118 else
119 err |= std::ios_base::failbit;
120 }
121
122 void get_month(
123 int& m,
124 iter_type& b, iter_type e,
125 std::ios_base::iostate& err,
126 const std::ctype<char_type>& ct) const
127 {
128 int t = get_up_to_n_digits(b, e, err, ct, 2);
129 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12)
130 m = --t;
131 else
132 err |= std::ios_base::failbit;
133 }
134
135
136 void get_year4(int& y,
137 iter_type& b, iter_type e,
138 std::ios_base::iostate& err,
139 const std::ctype<char_type>& ct) const
140 {
141 int t = get_up_to_n_digits(b, e, err, ct, 4);
142 if (!(err & std::ios_base::failbit))
143 y = t - 1900;
144 }
145
146 void
147 get_hour(int& h,
148 iter_type& b, iter_type e,
149 std::ios_base::iostate& err,
150 const std::ctype<char_type>& ct) const
151 {
152 int t = get_up_to_n_digits(b, e, err, ct, 2);
153 if (!(err & std::ios_base::failbit) && t <= 23)
154 h = t;
155 else
156 err |= std::ios_base::failbit;
157 }
158
159 void
160 get_minute(int& m,
161 iter_type& b, iter_type e,
162 std::ios_base::iostate& err,
163 const std::ctype<char_type>& ct) const
164 {
165 int t = get_up_to_n_digits(b, e, err, ct, 2);
166 if (!(err & std::ios_base::failbit) && t <= 59)
167 m = t;
168 else
169 err |= std::ios_base::failbit;
170 }
171
172 void get_second(int& s,
173 iter_type& b, iter_type e,
174 std::ios_base::iostate& err,
175 const std::ctype<char_type>& ct) const
176 {
177 int t = get_up_to_n_digits(b, e, err, ct, 2);
178 if (!(err & std::ios_base::failbit) && t <= 60)
179 s = t;
180 else
181 err |= std::ios_base::failbit;
182 }
183
184 void get_white_space(iter_type& b, iter_type e,
185 std::ios_base::iostate& err,
186 const std::ctype<char_type>& ct) const
187 {
188 for (; b != e && ct.is(std::ctype_base::space, *b); ++b)
189 ;
190 if (b == e)
191 err |= std::ios_base::eofbit;
192 }
193
194 void get_12_hour(int& h,
195 iter_type& b, iter_type e,
196 std::ios_base::iostate& err,
197 const std::ctype<char_type>& ct) const
198 {
199 int t = get_up_to_n_digits(b, e, err, ct, 2);
200 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12)
201 h = t;
202 else
203 err |= std::ios_base::failbit;
204 }
205
206 void get_percent(iter_type& b, iter_type e,
207 std::ios_base::iostate& err,
208 const std::ctype<char_type>& ct) const
209 {
210 if (b == e)
211 {
212 err |= std::ios_base::eofbit | std::ios_base::failbit;
213 return;
214 }
215 if (ct.narrow(*b, 0) != '%')
216 err |= std::ios_base::failbit;
217 else if(++b == e)
218 err |= std::ios_base::eofbit;
219 }
220
221 void get_day_year_num(int& d,
222 iter_type& b, iter_type e,
223 std::ios_base::iostate& err,
224 const std::ctype<char_type>& ct) const
225 {
226 int t = get_up_to_n_digits(b, e, err, ct, 3);
227 if (!(err & std::ios_base::failbit) && 1 <= t && t <= 366)
228 d = --t;
229 else
230 err |= std::ios_base::failbit;
231 }
232
233 void
234 get_weekday(int& w,
235 iter_type& b, iter_type e,
236 std::ios_base::iostate& err,
237 const std::ctype<char_type>& ct) const
238 {
239 int t = get_up_to_n_digits(b, e, err, ct, 1);
240 if (!(err & std::ios_base::failbit) && t <= 6)
241 w = t;
242 else
243 err |= std::ios_base::failbit;
244 }
245 #if 0
246
247 void
248 get_am_pm(int& h,
249 iter_type& b, iter_type e,
250 std::ios_base::iostate& err,
251 const std::ctype<char_type>& ct) const
252 {
253 const string_type* ap = am_pm();
254 if (ap[0].size() + ap[1].size() == 0)
255 {
256 err |= ios_base::failbit;
257 return;
258 }
259 ptrdiff_t i = detail::scan_keyword(b, e, ap, ap+2, ct, err, false) - ap;
260 if (i == 0 && h == 12)
261 h = 0;
262 else if (i == 1 && h < 12)
263 h += 12;
264 }
265
266 #endif
267
268 InputIterator get(
269 iter_type b, iter_type e,
270 std::ios_base& iob,
271 std::ios_base::iostate& err,
272 std::tm* tm,
273 char fmt, char) const
274 {
275 err = std::ios_base::goodbit;
276 const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
277
278 switch (fmt)
279 {
280 case 'a':
281 case 'A':
282 {
283 std::tm tm2;
284 std::memset(&tm2, 0, sizeof(std::tm));
285 that_.get_weekday(b, e, iob, err, &tm2);
286 //tm->tm_wday = tm2.tm_wday;
287 }
288 break;
289 case 'b':
290 case 'B':
291 case 'h':
292 {
293 std::tm tm2;
294 std::memset(&tm2, 0, sizeof(std::tm));
295 that_.get_monthname(b, e, iob, err, &tm2);
296 //tm->tm_mon = tm2.tm_mon;
297 }
298 break;
299 // case 'c':
300 // {
301 // const string_type& fm = c();
302 // b = get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
303 // }
304 // break;
305 case 'd':
306 case 'e':
307 get_day(tm->tm_mday, b, e, err, ct);
308 break;
309 case 'D':
310 {
311 const char_type fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
312 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
313 }
314 break;
315 case 'F':
316 {
317 const char_type fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
318 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
319 }
320 break;
321 case 'H':
322 get_hour(tm->tm_hour, b, e, err, ct);
323 break;
324 case 'I':
325 get_12_hour(tm->tm_hour, b, e, err, ct);
326 break;
327 case 'j':
328 get_day_year_num(tm->tm_yday, b, e, err, ct);
329 break;
330 case 'm':
331 get_month(tm->tm_mon, b, e, err, ct);
332 break;
333 case 'M':
334 get_minute(tm->tm_min, b, e, err, ct);
335 break;
336 case 'n':
337 case 't':
338 get_white_space(b, e, err, ct);
339 break;
340 // case 'p':
341 // get_am_pm(tm->tm_hour, b, e, err, ct);
342 // break;
343 case 'r':
344 {
345 const char_type fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
346 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
347 }
348 break;
349 case 'R':
350 {
351 const char_type fm[] = {'%', 'H', ':', '%', 'M'};
352 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
353 }
354 break;
355 case 'S':
356 get_second(tm->tm_sec, b, e, err, ct);
357 break;
358 case 'T':
359 {
360 const char_type fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
361 b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0]));
362 }
363 break;
364 case 'w':
365 {
366 get_weekday(tm->tm_wday, b, e, err, ct);
367 }
368 break;
369 case 'x':
370 return that_.get_date(b, e, iob, err, tm);
371 // case 'X':
372 // return that_.get_time(b, e, iob, err, tm);
373 // {
374 // const string_type& fm = X();
375 // b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size());
376 // }
377 // break;
378 // case 'y':
379 // get_year(tm->tm_year, b, e, err, ct);
380 break;
381 case 'Y':
382 get_year4(tm->tm_year, b, e, err, ct);
383 break;
384 case '%':
385 get_percent(b, e, err, ct);
386 break;
387 default:
388 err |= std::ios_base::failbit;
389 }
390 return b;
391 }
392
393
394 InputIterator get(
395 iter_type b, iter_type e,
396 std::ios_base& iob,
397 std::ios_base::iostate& err, std::tm* tm,
398 const char_type* fmtb, const char_type* fmte) const
399 {
400 const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc());
401 err = std::ios_base::goodbit;
402 while (fmtb != fmte && err == std::ios_base::goodbit)
403 {
404 if (b == e)
405 {
406 err = std::ios_base::failbit;
407 break;
408 }
409 if (ct.narrow(*fmtb, 0) == '%')
410 {
411 if (++fmtb == fmte)
412 {
413 err = std::ios_base::failbit;
414 break;
415 }
416 char cmd = ct.narrow(*fmtb, 0);
417 char opt = '\0';
418 if (cmd == 'E' || cmd == '0')
419 {
420 if (++fmtb == fmte)
421 {
422 err = std::ios_base::failbit;
423 break;
424 }
425 opt = cmd;
426 cmd = ct.narrow(*fmtb, 0);
427 }
428 b = get(b, e, iob, err, tm, cmd, opt);
429 ++fmtb;
430 }
431 else if (ct.is(std::ctype_base::space, *fmtb))
432 {
433 for (++fmtb; fmtb != fmte && ct.is(std::ctype_base::space, *fmtb); ++fmtb)
434 ;
435 for ( ; b != e && ct.is(std::ctype_base::space, *b); ++b)
436 ;
437 }
438 else if (ct.toupper(*b) == ct.toupper(*fmtb))
439 {
440 ++b;
441 ++fmtb;
442 }
443 else
444 err = std::ios_base::failbit;
445 }
446 if (b == e)
447 err |= std::ios_base::eofbit;
448 return b;
449 }
450
451 };
452
453
454 template <class CharT>
455 class time_manip: public manip<time_manip<CharT> >
456 {
457 std::basic_string<CharT> fmt_;
458 timezone tz_;
459 public:
460
461 time_manip(timezone tz, std::basic_string<CharT> fmt)
462 // todo move semantics
463 :
464 fmt_(fmt), tz_(tz)
465 {
466 }
467
468 /**
469 * Change the timezone and time format ios state;
470 */
471 void operator()(std::ios_base &ios) const
472 {
473 set_time_fmt<CharT> (ios, fmt_);
474 set_timezone(ios, tz_);
475 }
476 };
477
478 class time_man: public manip<time_man>
479 {
480 timezone tz_;
481 public:
482
483 time_man(timezone tz)
484 // todo move semantics
485 :
486 tz_(tz)
487 {
488 }
489
490 /**
491 * Change the timezone and time format ios state;
492 */
493 void operator()(std::ios_base &ios) const
494 {
495 //set_time_fmt<typename out_stream::char_type>(ios, "");
496 set_timezone(ios, tz_);
497 }
498 };
499
500 }
501
502 template <class CharT>
503 inline detail::time_manip<CharT> time_fmt(timezone tz, const CharT* fmt)
504 {
505 return detail::time_manip<CharT>(tz, fmt);
506 }
507
508 template <class CharT>
509 inline detail::time_manip<CharT> time_fmt(timezone tz, std::basic_string<CharT> fmt)
510 {
511 // todo move semantics
512 return detail::time_manip<CharT>(tz, fmt);
513 }
514
515 inline detail::time_man time_fmt(timezone f)
516 {
517 return detail::time_man(f);
518 }
519
520 /**
521 * time_fmt_io_saver i/o saver.
522 *
523 * See Boost.IO i/o state savers for a motivating compression.
524 */
525 template <typename CharT = char, typename Traits = std::char_traits<CharT> >
526 struct time_fmt_io_saver
527 {
528
529 //! the type of the state to restore
530 //typedef std::basic_ostream<CharT, Traits> state_type;
531 typedef std::ios_base state_type;
532
533 //! the type of aspect to save
534 typedef std::basic_string<CharT, Traits> aspect_type;
535
536 /**
537 * Explicit construction from an i/o stream.
538 *
539 * Store a reference to the i/o stream and the value of the associated @c time format .
540 */
541 explicit time_fmt_io_saver(state_type &s) :
542 s_save_(s), a_save_(get_time_fmt<CharT>(s_save_))
543 {
544 }
545
546 /**
547 * Construction from an i/o stream and a @c time format to restore.
548 *
549 * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter.
550 */
551 time_fmt_io_saver(state_type &s, aspect_type new_value) :
552 s_save_(s), a_save_(get_time_fmt<CharT>(s_save_))
553 {
554 set_time_fmt(s_save_, new_value);
555 }
556
557 /**
558 * Destructor.
559 *
560 * Restores the i/o stream with the format to be restored.
561 */
562 ~time_fmt_io_saver()
563 {
564 this->restore();
565 }
566
567 /**
568 * Restores the i/o stream with the time format to be restored.
569 */
570 void restore()
571 {
572 set_time_fmt(s_save_, a_save_);
573 }
574 private:
575 state_type& s_save_;
576 aspect_type a_save_;
577 };
578
579 /**
580 * timezone_io_saver i/o saver.
581 *
582 * See Boost.IO i/o state savers for a motivating compression.
583 */
584 struct timezone_io_saver
585 {
586
587 //! the type of the state to restore
588 typedef std::ios_base state_type;
589 //! the type of aspect to save
590 typedef timezone aspect_type;
591
592 /**
593 * Explicit construction from an i/o stream.
594 *
595 * Store a reference to the i/o stream and the value of the associated @c timezone.
596 */
597 explicit timezone_io_saver(state_type &s) :
598 s_save_(s), a_save_(get_timezone(s_save_))
599 {
600 }
601
602 /**
603 * Construction from an i/o stream and a @c timezone to restore.
604 *
605 * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter.
606 */
607 timezone_io_saver(state_type &s, aspect_type new_value) :
608 s_save_(s), a_save_(get_timezone(s_save_))
609 {
610 set_timezone(s_save_, new_value);
611 }
612
613 /**
614 * Destructor.
615 *
616 * Restores the i/o stream with the format to be restored.
617 */
618 ~timezone_io_saver()
619 {
620 this->restore();
621 }
622
623 /**
624 * Restores the i/o stream with the timezone to be restored.
625 */
626 void restore()
627 {
628 set_timezone(s_save_, a_save_);
629 }
630 private:
631 timezone_io_saver& operator=(timezone_io_saver const& rhs) ;
632
633 state_type& s_save_;
634 aspect_type a_save_;
635 };
636
637 /**
638 *
639 * @param os
640 * @param tp
641 * @Effects Behaves as a formatted output function. After constructing a @c sentry object, if the @ sentry
642 * converts to true, calls to @c facet.put(os,os,os.fill(),tp) where @c facet is the @c time_point_put<CharT>
643 * facet associated to @c os or a new created instance of the default @c time_point_put<CharT> facet.
644 * @return @c os.
645 */
646 template <class CharT, class Traits, class Clock, class Duration>
647 std::basic_ostream<CharT, Traits>&
648 operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<Clock, Duration>& tp)
649 {
650
651 bool failed = false;
652 BOOST_TRY
653 {
654 std::ios_base::iostate err = std::ios_base::goodbit;
655 BOOST_TRY
656 {
657 typename std::basic_ostream<CharT, Traits>::sentry opfx(os);
658 if (bool(opfx))
659 {
660 if (!std::has_facet<time_point_put<CharT> >(os.getloc()))
661 {
662 if (time_point_put<CharT> ().put(os, os, os.fill(), tp) .failed())
663 {
664 err = std::ios_base::badbit;
665 }
666 }
667 else
668 {
669 if (std::use_facet<time_point_put<CharT> >(os.getloc()) .put(os, os, os.fill(), tp).failed())
670 {
671 err = std::ios_base::badbit;
672 }
673 }
674 os.width(0);
675 }
676 }
677 BOOST_CATCH (...)
678 {
679 bool flag = false;
680 BOOST_TRY
681 {
682 os.setstate(std::ios_base::failbit);
683 }
684 BOOST_CATCH (std::ios_base::failure )
685 {
686 flag = true;
687 }
688 BOOST_CATCH_END
689 if (flag) throw;
690 }
691 BOOST_CATCH_END
692 if (err) os.setstate(err);
693 return os;
694 }
695 BOOST_CATCH (...)
696 {
697 failed = true;
698 }
699 BOOST_CATCH_END
700 if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit);
701 return os;
702 }
703
704 template <class CharT, class Traits, class Clock, class Duration>
705 std::basic_istream<CharT, Traits>&
706 operator>>(std::basic_istream<CharT, Traits>& is, time_point<Clock, Duration>& tp)
707 {
708 std::ios_base::iostate err = std::ios_base::goodbit;
709
710 BOOST_TRY
711 {
712 typename std::basic_istream<CharT, Traits>::sentry ipfx(is);
713 if (bool(ipfx))
714 {
715 if (!std::has_facet<time_point_get<CharT> >(is.getloc()))
716 {
717 time_point_get<CharT> ().get(is, std::istreambuf_iterator<CharT, Traits>(), is, err, tp);
718 }
719 else
720 {
721 std::use_facet<time_point_get<CharT> >(is.getloc()).get(is, std::istreambuf_iterator<CharT, Traits>(), is,
722 err, tp);
723 }
724 }
725 }
726 BOOST_CATCH (...)
727 {
728 bool flag = false;
729 BOOST_TRY
730 {
731 is.setstate(std::ios_base::failbit);
732 }
733 BOOST_CATCH (std::ios_base::failure )
734 {
735 flag = true;
736 }
737 BOOST_CATCH_END
738 if (flag) throw;
739 }
740 BOOST_CATCH_END
741 if (err) is.setstate(err);
742 return is;
743 }
744
745
746 namespace detail
747 {
748
749 //#if BOOST_CHRONO_INTERNAL_TIMEGM
750
751 inline int32_t is_leap(int32_t year)
752 {
753 if(year % 400 == 0)
754 return 1;
755 if(year % 100 == 0)
756 return 0;
757 if(year % 4 == 0)
758 return 1;
759 return 0;
760 }
761 inline int32_t days_from_0(int32_t year)
762 {
763 year--;
764 return 365 * year + (year / 400) - (year/100) + (year / 4);
765 }
766 inline int32_t days_from_1970(int32_t year)
767 {
768 static const int days_from_0_to_1970 = days_from_0(1970);
769 return days_from_0(year) - days_from_0_to_1970;
770 }
771 inline int32_t days_from_1jan(int32_t year,int32_t month,int32_t day)
772 {
773 static const int32_t days[2][12] =
774 {
775 { 0,31,59,90,120,151,181,212,243,273,304,334},
776 { 0,31,60,91,121,152,182,213,244,274,305,335}
777 };
778
779 return days[is_leap(year)][month-1] + day - 1;
780 }
781
782 inline time_t internal_timegm(std::tm const *t)
783 {
784 int year = t->tm_year + 1900;
785 int month = t->tm_mon;
786 if(month > 11)
787 {
788 year += month/12;
789 month %= 12;
790 }
791 else if(month < 0)
792 {
793 int years_diff = (-month + 11)/12;
794 year -= years_diff;
795 month+=12 * years_diff;
796 }
797 month++;
798 int day = t->tm_mday;
799 int day_of_year = days_from_1jan(year,month,day);
800 int days_since_epoch = days_from_1970(year) + day_of_year ;
801
802 time_t seconds_in_day = 3600 * 24;
803 time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;
804
805 return result;
806 }
807 //#endif
808
809 /**
810 * from_ymd could be made more efficient by using a table
811 * day_count_table indexed by the y%400.
812 * This table could contain the day_count
813 * by*365 + by/4 - by/100 + by/400
814 *
815 * from_ymd = (by/400)*days_by_400_years+day_count_table[by%400] +
816 * days_in_year_before[is_leap_table[by%400]][m-1] + d;
817 */
818 inline unsigned days_before_years(int32_t y)
819 {
820 return y * 365 + y / 4 - y / 100 + y / 400;
821 }
822
823 // Returns year/month/day triple in civil calendar
824 // Preconditions: z is number of days since 1970-01-01 and is in the range:
825 // [numeric_limits<Int>::min(), numeric_limits<Int>::max()-719468].
826 template <class Int>
827 //constexpr
828 void
829 inline civil_from_days(Int z, Int& y, unsigned& m, unsigned& d) BOOST_NOEXCEPT
830 {
831 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<unsigned>::digits >= 18,
832 "This algorithm has not been ported to a 16 bit unsigned integer");
833 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<Int>::digits >= 20,
834 "This algorithm has not been ported to a 16 bit signed integer");
835 z += 719468;
836 const Int era = (z >= 0 ? z : z - 146096) / 146097;
837 const unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
838 const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
839 y = static_cast<Int>(yoe) + era * 400;
840 const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
841 const unsigned mp = (5*doy + 2)/153; // [0, 11]
842 d = doy - (153*mp+2)/5 + 1; // [1, 31]
843 m = mp + (mp < 10 ? 3 : -9); // [1, 12]
844 y += (m <= 2);
845 --m;
846 }
847 inline std::tm * internal_gmtime(std::time_t const* t, std::tm *tm)
848 {
849 if (t==0) return 0;
850 if (tm==0) return 0;
851
852 #if 0
853 static const unsigned char
854 day_of_year_month[2][366] =
855 {
856 { 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 },
857
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, 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
859
860 } };
861
862 static const int32_t days_in_year_before[2][13] =
863 {
864 { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
865 { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }
866 };
867 #endif
868
869 const time_t seconds_in_day = 3600 * 24;
870 int32_t days_since_epoch = static_cast<int32_t>(*t / seconds_in_day);
871 int32_t hms = static_cast<int32_t>(*t - seconds_in_day*days_since_epoch);
872 if (hms < 0) {
873 days_since_epoch-=1;
874 hms = seconds_in_day+hms;
875 }
876
877 #if 0
878 int32_t x = days_since_epoch;
879 int32_t y = static_cast<int32_t> (static_cast<long long> (x + 2) * 400
880 / 146097);
881 const int32_t ym1 = y - 1;
882 int32_t doy = x - days_before_years(y);
883 const int32_t doy1 = x - days_before_years(ym1);
884 const int32_t N = std::numeric_limits<int>::digits - 1;
885 const int32_t mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal
886 const int32_t mask0 = ~mask1;
887 doy = (doy & mask0) | (doy1 & mask1);
888 y = (y & mask0) | (ym1 & mask1);
889 //y -= 32767 + 2;
890 y += 70;
891 tm->tm_year=y;
892 const int32_t leap = is_leap(y);
893 tm->tm_mon = day_of_year_month[leap][doy]-1;
894 tm->tm_mday = doy - days_in_year_before[leap][tm->tm_mon] ;
895 #else
896 int32_t y;
897 unsigned m, d;
898 civil_from_days(days_since_epoch, y, m, d);
899 tm->tm_year=y-1900; tm->tm_mon=m; tm->tm_mday=d;
900 #endif
901
902 tm->tm_hour = hms / 3600;
903 const int ms = hms % 3600;
904 tm->tm_min = ms / 60;
905 tm->tm_sec = ms % 60;
906
907 tm->tm_isdst = -1;
908 (void)mktime(tm);
909 return tm;
910 }
911
912 } // detail
913 #ifndef BOOST_CHRONO_NO_UTC_TIMEPOINT
914
915 #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT
916
917 template <class CharT, class Traits, class Duration>
918 std::basic_ostream<CharT, Traits>&
919 operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<system_clock, Duration>& tp)
920 {
921 typename std::basic_ostream<CharT, Traits>::sentry ok(os);
922 if (bool(ok))
923 {
924 bool failed = false;
925 BOOST_TRY
926 {
927 const CharT* pb = 0; //nullptr;
928 const CharT* pe = pb;
929 std::basic_string<CharT> fmt = get_time_fmt<CharT> (os);
930 pb = fmt.data();
931 pe = pb + fmt.size();
932
933 timezone tz = get_timezone(os);
934 std::locale loc = os.getloc();
935 time_t t = system_clock::to_time_t(time_point_cast<system_clock::duration>(tp));
936 std::tm tm;
937 std::memset(&tm, 0, sizeof(std::tm));
938 if (tz == timezone::local)
939 {
940 #if defined BOOST_WINDOWS && ! defined(__CYGWIN__)
941 std::tm *tmp = 0;
942 if ((tmp=localtime(&t)) == 0)
943 failed = true;
944 else
945 tm =*tmp;
946 #else
947 if (localtime_r(&t, &tm) == 0) failed = true;
948 #endif
949 }
950 else
951 {
952 #if BOOST_CHRONO_INTERNAL_GMTIME
953 if (detail::internal_gmtime(&t, &tm) == 0) failed = true;
954
955 #elif defined BOOST_WINDOWS && ! defined(__CYGWIN__)
956 std::tm *tmp = 0;
957 if((tmp = gmtime(&t)) == 0)
958 failed = true;
959 else
960 tm = *tmp;
961 #else
962 if (gmtime_r(&t, &tm) == 0) failed = true;
963 tm.tm_isdst = -1;
964 (void)mktime(&tm);
965
966 #endif
967
968 }
969 if (!failed)
970 {
971 const std::time_put<CharT>& tpf = std::use_facet<std::time_put<CharT> >(loc);
972 if (pb == pe)
973 {
974 CharT pattern[] =
975 { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' };
976 pb = pattern;
977 pe = pb + sizeof (pattern) / sizeof(CharT);
978 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
979 if (!failed)
980 {
981 duration<fractional_seconds> d = tp - system_clock::from_time_t(t) + seconds(tm.tm_sec);
982 if (d.count() < 10) os << CharT('0');
983 //if (! os.good()) {
984 // throw "exception";
985 //}
986 std::ios::fmtflags flgs = os.flags();
987 os.setf(std::ios::fixed, std::ios::floatfield);
988 //if (! os.good()) {
989 //throw "exception";
990 //}
991 os.precision(9);
992 os << d.count();
993 //if (! os.good()) {
994 //throw "exception";
995 //}
996 os.flags(flgs);
997 if (tz == timezone::local)
998 {
999 CharT sub_pattern[] =
1000 { ' ', '%', 'z' };
1001 pb = sub_pattern;
1002 pe = pb + +sizeof (sub_pattern) / sizeof(CharT);
1003 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
1004 }
1005 else
1006 {
1007 CharT sub_pattern[] =
1008 { ' ', '+', '0', '0', '0', '0', 0 };
1009 os << sub_pattern;
1010 }
1011 }
1012 }
1013 else
1014 {
1015 failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed();
1016 }
1017 }
1018 }
1019 BOOST_CATCH (...)
1020 {
1021 failed = true;
1022 }
1023 BOOST_CATCH_END
1024 if (failed)
1025 {
1026 os.setstate(std::ios_base::failbit | std::ios_base::badbit);
1027 }
1028 }
1029 return os;
1030 }
1031 #endif
1032
1033 namespace detail
1034 {
1035
1036 template <class CharT, class InputIterator>
1037 minutes extract_z(InputIterator& b, InputIterator e, std::ios_base::iostate& err, const std::ctype<CharT>& ct)
1038 {
1039 int min = 0;
1040 if (b != e)
1041 {
1042 char cn = ct.narrow(*b, 0);
1043 if (cn != '+' && cn != '-')
1044 {
1045 err |= std::ios_base::failbit;
1046 return minutes(0);
1047 }
1048 int sn = cn == '-' ? -1 : 1;
1049 int hr = 0;
1050 for (int i = 0; i < 2; ++i)
1051 {
1052 if (++b == e)
1053 {
1054 err |= std::ios_base::eofbit | std::ios_base::failbit;
1055 return minutes(0);
1056 }
1057 cn = ct.narrow(*b, 0);
1058 if (! ('0' <= cn && cn <= '9'))
1059 {
1060 err |= std::ios_base::failbit;
1061 return minutes(0);
1062 }
1063 hr = hr * 10 + cn - '0';
1064 }
1065 for (int i = 0; i < 2; ++i)
1066 {
1067 if (++b == e)
1068 {
1069 err |= std::ios_base::eofbit | std::ios_base::failbit;
1070 return minutes(0);
1071 }
1072 cn = ct.narrow(*b, 0);
1073 if (! ('0' <= cn && cn <= '9'))
1074 {
1075 err |= std::ios_base::failbit;
1076 return minutes(0);
1077 }
1078 min = min * 10 + cn - '0';
1079 }
1080 if (++b == e) {
1081 err |= std::ios_base::eofbit;
1082 }
1083 min += hr * 60;
1084 min *= sn;
1085 }
1086 else
1087 {
1088 err |= std::ios_base::eofbit | std::ios_base::failbit;
1089 }
1090 return minutes(min);
1091 }
1092
1093 } // detail
1094
1095 #if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT
1096
1097 template <class CharT, class Traits, class Duration>
1098 std::basic_istream<CharT, Traits>&
1099 operator>>(std::basic_istream<CharT, Traits>& is, time_point<system_clock, Duration>& tp)
1100 {
1101 typename std::basic_istream<CharT, Traits>::sentry ok(is);
1102 if (bool(ok))
1103 {
1104 std::ios_base::iostate err = std::ios_base::goodbit;
1105 BOOST_TRY
1106 {
1107 const CharT* pb = 0; //nullptr;
1108 const CharT* pe = pb;
1109 std::basic_string<CharT> fmt = get_time_fmt<CharT> (is);
1110 pb = fmt.data();
1111 pe = pb + fmt.size();
1112
1113 timezone tz = get_timezone(is);
1114 std::locale loc = is.getloc();
1115 const std::time_get<CharT>& tg = std::use_facet<std::time_get<CharT> >(loc);
1116 const std::ctype<CharT>& ct = std::use_facet<std::ctype<CharT> >(loc);
1117 tm tm; // {0}
1118 std::memset(&tm, 0, sizeof(std::tm));
1119
1120 typedef std::istreambuf_iterator<CharT, Traits> It;
1121 if (pb == pe)
1122 {
1123 CharT pattern[] =
1124 { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' };
1125 pb = pattern;
1126 pe = pb + sizeof (pattern) / sizeof(CharT);
1127
1128 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1129 const detail::time_get<CharT>& dtg(tg);
1130 dtg.get(is, 0, is, err, &tm, pb, pe);
1131 #else
1132 tg.get(is, 0, is, err, &tm, pb, pe);
1133 #endif
1134 if (err & std::ios_base::failbit) goto exit;
1135 fractional_seconds sec;
1136 CharT c = CharT();
1137 std::ios::fmtflags flgs = is.flags();
1138 is.setf(std::ios::fixed, std::ios::floatfield);
1139 is.precision(9);
1140 is >> sec;
1141 is.flags(flgs);
1142 if (is.fail())
1143 {
1144 err |= std::ios_base::failbit;
1145 goto exit;
1146 }
1147 It i(is);
1148 It eof;
1149 c = *i;
1150 if (++i == eof || c != ' ')
1151 {
1152 err |= std::ios_base::failbit;
1153 goto exit;
1154 }
1155 minutes min = detail::extract_z(i, eof, err, ct);
1156
1157 if (err & std::ios_base::failbit) goto exit;
1158 time_t t;
1159
1160 #if BOOST_CHRONO_INTERNAL_TIMEGM
1161 t = detail::internal_timegm(&tm);
1162 #else
1163 t = timegm(&tm);
1164 #endif
1165 tp = time_point_cast<Duration>(
1166 system_clock::from_time_t(t) - min + round<system_clock::duration> (duration<fractional_seconds> (sec))
1167 );
1168 }
1169 else
1170 {
1171 const CharT z[2] =
1172 { '%', 'z' };
1173 const CharT* fz = std::search(pb, pe, z, z + 2);
1174 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1175 const detail::time_get<CharT>& dtg(tg);
1176 dtg.get(is, 0, is, err, &tm, pb, fz);
1177 #else
1178 tg.get(is, 0, is, err, &tm, pb, fz);
1179 #endif
1180 minutes minu(0);
1181 if (fz != pe)
1182 {
1183 if (err != std::ios_base::goodbit)
1184 {
1185 err |= std::ios_base::failbit;
1186 goto exit;
1187 }
1188 It i(is);
1189 It eof;
1190 minu = detail::extract_z(i, eof, err, ct);
1191 if (err & std::ios_base::failbit) goto exit;
1192 if (fz + 2 != pe)
1193 {
1194 if (err != std::ios_base::goodbit)
1195 {
1196 err |= std::ios_base::failbit;
1197 goto exit;
1198 }
1199 #if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET
1200 const detail::time_get<CharT>& dtg(tg);
1201 dtg.get(is, 0, is, err, &tm, fz + 2, pe);
1202 #else
1203 tg.get(is, 0, is, err, &tm, fz + 2, pe);
1204 #endif
1205 if (err & std::ios_base::failbit) goto exit;
1206 }
1207 }
1208 tm.tm_isdst = -1;
1209 time_t t;
1210 if (tz == timezone::utc || fz != pe)
1211 {
1212 #if BOOST_CHRONO_INTERNAL_TIMEGM
1213 t = detail::internal_timegm(&tm);
1214 #else
1215 t = timegm(&tm);
1216 #endif
1217 }
1218 else
1219 {
1220 t = mktime(&tm);
1221 }
1222 tp = time_point_cast<Duration>(
1223 system_clock::from_time_t(t) - minu
1224 );
1225 }
1226 }
1227 BOOST_CATCH (...)
1228 {
1229 err |= std::ios_base::badbit | std::ios_base::failbit;
1230 }
1231 BOOST_CATCH_END
1232 exit: is.setstate(err);
1233 }
1234 return is;
1235 }
1236
1237 #endif
1238 #endif //UTC
1239 } // chrono
1240
1241 }
1242
1243 #endif // header