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