Dynalib Utils
tz.h
Go to the documentation of this file.
1 #ifndef TZ_H
2 #define TZ_H
3 
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2015, 2016, 2017 Howard Hinnant
7 // Copyright (c) 2017 Jiangang Zhuang
8 // Copyright (c) 2017 Aaron Bishop
9 // Copyright (c) 2017 Tomasz KamiƄski
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in all
19 // copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 // SOFTWARE.
28 //
29 // Our apologies. When the previous paragraph was written, lowercase had not yet
30 // been invented (that would involve another several millennia of evolution).
31 // We did not mean to shout.
32 
33 // Get more recent database at http://www.iana.org/time-zones
34 
35 // The notion of "current timezone" is something the operating system is expected to "just
36 // know". How it knows this is system specific. It's often a value set by the user at OS
37 // installation time and recorded by the OS somewhere. On Linux and Mac systems the current
38 // timezone name is obtained by looking at the name or contents of a particular file on
39 // disk. On Windows the current timezone name comes from the registry. In either method,
40 // there is no guarantee that the "native" current timezone name obtained will match any
41 // of the "Standard" names in this library's "database". On Linux, the names usually do
42 // seem to match so mapping functions to map from native to "Standard" are typically not
43 // required. On Windows, the names are never "Standard" so mapping is always required.
44 // Technically any OS may use the mapping process but currently only Windows does use it.
45 
46 #ifndef USE_OS_TZDB
47 # define USE_OS_TZDB 0
48 #endif
49 
50 #ifndef HAS_REMOTE_API
51 # if USE_OS_TZDB == 0
52 # ifdef _WIN32
53 # define HAS_REMOTE_API 0
54 # else
55 # define HAS_REMOTE_API 1
56 # endif
57 # else // HAS_REMOTE_API makes no since when using the OS timezone database
58 # define HAS_REMOTE_API 0
59 # endif
60 #endif
61 
62 #ifdef __clang__
63 # pragma clang diagnostic push
64 # pragma clang diagnostic ignored "-Wconstant-logical-operand"
65 #endif
66 
67 static_assert(!(USE_OS_TZDB && HAS_REMOTE_API),
68  "USE_OS_TZDB and HAS_REMOTE_API can not be used together");
69 
70 #ifdef __clang__
71 # pragma clang diagnostic pop
72 #endif
73 
74 #ifndef AUTO_DOWNLOAD
75 # define AUTO_DOWNLOAD HAS_REMOTE_API
76 #endif
77 
78 static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true,
79  "AUTO_DOWNLOAD can not be turned on without HAS_REMOTE_API");
80 
81 #ifndef USE_SHELL_API
82 # define USE_SHELL_API 1
83 #endif
84 
85 #if USE_OS_TZDB
86 # ifdef _WIN32
87 # error "USE_OS_TZDB can not be used on Windows"
88 # endif
89 # ifndef MISSING_LEAP_SECONDS
90 # ifdef __APPLE__
91 # define MISSING_LEAP_SECONDS 1
92 # else
93 # define MISSING_LEAP_SECONDS 0
94 # endif
95 # endif
96 #else
97 # define MISSING_LEAP_SECONDS 0
98 #endif
99 
100 #ifndef HAS_DEDUCTION_GUIDES
101 # if __cplusplus >= 201703
102 # define HAS_DEDUCTION_GUIDES 1
103 # else
104 # define HAS_DEDUCTION_GUIDES 0
105 # endif
106 #endif // HAS_DEDUCTION_GUIDES
107 
108 #include "date.h"
109 
110 #if defined(_MSC_VER) && (_MSC_VER < 1900)
111 #include "tz_private.h"
112 #endif
113 
114 #include <algorithm>
115 #include <atomic>
116 #include <cassert>
117 #include <chrono>
118 #include <istream>
119 #include <locale>
120 #include <memory>
121 #include <mutex>
122 #include <ostream>
123 #include <sstream>
124 #include <stdexcept>
125 #include <string>
126 #include <type_traits>
127 #include <utility>
128 #include <vector>
129 
130 #ifdef _WIN32
131 # ifdef DATE_BUILD_DLL
132 # define DATE_API __declspec(dllexport)
133 # elif defined(DATE_USE_DLL)
134 # define DATE_API __declspec(dllimport)
135 # else
136 # define DATE_API
137 # endif
138 #else
139 # ifdef DATE_BUILD_DLL
140 # define DATE_API __attribute__ ((visibility ("default")))
141 # else
142 # define DATE_API
143 # endif
144 #endif
145 
146 namespace date
147 {
148 
149 enum class choose {earliest, latest};
150 
151 namespace detail
152 {
153  struct undocumented;
154 }
155 
156 struct sys_info
157 {
160  std::chrono::seconds offset;
161  std::chrono::minutes save;
162  std::string abbrev;
163 };
164 
165 template<class CharT, class Traits>
166 std::basic_ostream<CharT, Traits>&
167 operator<<(std::basic_ostream<CharT, Traits>& os, const sys_info& r)
168 {
169  os << r.begin << '\n';
170  os << r.end << '\n';
171  os << make_time(r.offset) << "\n";
172  os << make_time(r.save) << "\n";
173  os << r.abbrev << '\n';
174  return os;
175 }
176 
178 {
179  enum {unique, nonexistent, ambiguous} result;
182 };
183 
184 template<class CharT, class Traits>
185 std::basic_ostream<CharT, Traits>&
186 operator<<(std::basic_ostream<CharT, Traits>& os, const local_info& r)
187 {
188  if (r.result == local_info::nonexistent)
189  os << "nonexistent between\n";
190  else if (r.result == local_info::ambiguous)
191  os << "ambiguous between\n";
192  os << r.first;
193  if (r.result != local_info::unique)
194  {
195  os << "and\n";
196  os << r.second;
197  }
198  return os;
199 }
200 
202  : public std::runtime_error
203 {
204 public:
205  template <class Duration>
207 
208 private:
209  template <class Duration>
210  static
211  std::string
212  make_msg(local_time<Duration> tp, const local_info& i);
213 };
214 
215 template <class Duration>
216 inline
218  const local_info& i)
219  : std::runtime_error(make_msg(tp, i))
220 {
221 }
222 
223 template <class Duration>
224 std::string
225 nonexistent_local_time::make_msg(local_time<Duration> tp, const local_info& i)
226 {
227  assert(i.result == local_info::nonexistent);
228  std::ostringstream os;
229  os << tp << " is in a gap between\n"
230  << local_seconds{i.first.end.time_since_epoch()} + i.first.offset << ' '
231  << i.first.abbrev << " and\n"
232  << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' '
233  << i.second.abbrev
234  << " which are both equivalent to\n"
235  << i.first.end << " UTC";
236  return os.str();
237 }
238 
240  : public std::runtime_error
241 {
242 public:
243  template <class Duration>
245 
246 private:
247  template <class Duration>
248  static
249  std::string
250  make_msg(local_time<Duration> tp, const local_info& i);
251 };
252 
253 template <class Duration>
254 inline
256  : std::runtime_error(make_msg(tp, i))
257 {
258 }
259 
260 template <class Duration>
261 std::string
262 ambiguous_local_time::make_msg(local_time<Duration> tp, const local_info& i)
263 {
264  assert(i.result == local_info::ambiguous);
265  std::ostringstream os;
266  os << tp << " is ambiguous. It could be\n"
267  << tp << ' ' << i.first.abbrev << " == "
268  << tp - i.first.offset << " UTC or\n"
269  << tp << ' ' << i.second.abbrev << " == "
270  << tp - i.second.offset << " UTC";
271  return os.str();
272 }
273 
274 class time_zone;
275 
276 #if HAS_STRING_VIEW
277 DATE_API const time_zone* locate_zone(std::string_view tz_name);
278 #else
279 DATE_API const time_zone* locate_zone(const std::string& tz_name);
280 #endif
281 
283 
284 template <class T>
286 {
287 };
288 
289 template <>
290 struct zoned_traits<const time_zone*>
291 {
292  static
293  const time_zone*
295  {
296  return date::locate_zone("Etc/UTC");
297  }
298 
299 #if HAS_STRING_VIEW
300 
301  static
302  const time_zone*
303  locate_zone(std::string_view name)
304  {
305  return date::locate_zone(name);
306  }
307 
308 #else // !HAS_STRING_VIEW
309 
310  static
311  const time_zone*
312  locate_zone(const std::string& name)
313  {
314  return date::locate_zone(name);
315  }
316 
317  static
318  const time_zone*
319  locate_zone(const char* name)
320  {
321  return date::locate_zone(name);
322  }
323 
324 #endif // !HAS_STRING_VIEW
325 };
326 
327 template <class Duration, class TimeZonePtr>
329 
330 template <class Duration1, class Duration2, class TimeZonePtr>
331 bool
334 
335 template <class Duration, class TimeZonePtr = const time_zone*>
336 class zoned_time
337 {
338 public:
339  using duration = typename std::common_type<Duration, std::chrono::seconds>::type;
340 
341 private:
342  TimeZonePtr zone_;
343  sys_time<duration> tp_;
344 
345 public:
346 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
347  template <class T = TimeZonePtr,
348  class = decltype(zoned_traits<T>::default_zone())>
349 #endif
350  zoned_time();
351 
352 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
353  template <class T = TimeZonePtr,
354  class = decltype(zoned_traits<T>::default_zone())>
355 #endif
356  zoned_time(const sys_time<Duration>& st);
357  explicit zoned_time(TimeZonePtr z);
358 
359 #if HAS_STRING_VIEW
360  template <class T = TimeZonePtr,
361  class = typename std::enable_if
362  <
363  std::is_constructible
364  <
365  zoned_time,
366  decltype(zoned_traits<T>::locate_zone(std::string_view()))
367  >::value
368  >::type>
369  explicit zoned_time(std::string_view name);
370 #else
371 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
372  template <class T = TimeZonePtr,
373  class = typename std::enable_if
374  <
375  std::is_constructible
376  <
377  zoned_time,
378  decltype(zoned_traits<T>::locate_zone(std::string()))
379  >::value
380  >::type>
381 #endif
382  explicit zoned_time(const std::string& name);
383 #endif
384 
385  template <class Duration2,
386  class = typename std::enable_if
387  <
388  std::is_convertible<sys_time<Duration2>,
390  >::type>
391  zoned_time(const zoned_time<Duration2, TimeZonePtr>& zt) NOEXCEPT;
392 
393  zoned_time(TimeZonePtr z, const sys_time<Duration>& st);
394 
395 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
396  template <class T = TimeZonePtr,
397  class = typename std::enable_if
398  <
399  std::is_convertible
400  <
401  decltype(std::declval<T&>()->to_sys(local_time<Duration>{})),
403  >::value
404  >::type>
405 #endif
406  zoned_time(TimeZonePtr z, const local_time<Duration>& tp);
407 
408 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
409  template <class T = TimeZonePtr,
410  class = typename std::enable_if
411  <
412  std::is_convertible
413  <
414  decltype(std::declval<T&>()->to_sys(local_time<Duration>{},
417  >::value
418  >::type>
419 #endif
420  zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c);
421 
422  template <class Duration2, class TimeZonePtr2,
423  class = typename std::enable_if
424  <
425  std::is_convertible<sys_time<Duration2>,
427  >::type>
428  zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt);
429 
430  template <class Duration2, class TimeZonePtr2,
431  class = typename std::enable_if
432  <
433  std::is_convertible<sys_time<Duration2>,
435  >::type>
436  zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt, choose);
437 
438 #if HAS_STRING_VIEW
439 
440  template <class T = TimeZonePtr,
441  class = typename std::enable_if
442  <
443  std::is_constructible
444  <
445  zoned_time,
446  decltype(zoned_traits<T>::locate_zone(std::string_view())),
448  >::value
449  >::type>
450  zoned_time(std::string_view name, const sys_time<Duration>& st);
451 
452  template <class T = TimeZonePtr,
453  class = typename std::enable_if
454  <
455  std::is_constructible
456  <
457  zoned_time,
458  decltype(zoned_traits<T>::locate_zone(std::string_view())),
460  >::value
461  >::type>
462  zoned_time(std::string_view name, const local_time<Duration>& tp);
463 
464  template <class T = TimeZonePtr,
465  class = typename std::enable_if
466  <
467  std::is_constructible
468  <
469  zoned_time,
470  decltype(zoned_traits<T>::locate_zone(std::string_view())),
472  choose
473  >::value
474  >::type>
475  zoned_time(std::string_view name, const local_time<Duration>& tp, choose c);
476 
477  template <class T = TimeZonePtr,
478  class = typename std::enable_if
479  <
480  std::is_constructible
481  <
482  zoned_time,
483  decltype(zoned_traits<T>::locate_zone(std::string_view())),
484  zoned_time
485  >::value
486  >::type>
487  zoned_time(std::string_view name, const zoned_time& zt);
488 
489  template <class T = TimeZonePtr,
490  class = typename std::enable_if
491  <
492  std::is_constructible
493  <
494  zoned_time,
495  decltype(zoned_traits<T>::locate_zone(std::string_view())),
496  zoned_time,
497  choose
498  >::value
499  >::type>
500  zoned_time(std::string_view name, const zoned_time& zt, choose);
501 
502 #else // !HAS_STRING_VIEW
503 
504 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
505  template <class T = TimeZonePtr,
506  class = typename std::enable_if
507  <
508  std::is_constructible
509  <
510  zoned_time,
511  decltype(zoned_traits<T>::locate_zone(std::string())),
513  >::value
514  >::type>
515 #endif
516  zoned_time(const std::string& name, const sys_time<Duration>& st);
517 
518 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
519  template <class T = TimeZonePtr,
520  class = typename std::enable_if
521  <
522  std::is_constructible
523  <
524  zoned_time,
525  decltype(zoned_traits<T>::locate_zone(std::string())),
527  >::value
528  >::type>
529 #endif
530  zoned_time(const char* name, const sys_time<Duration>& st);
531 
532 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
533  template <class T = TimeZonePtr,
534  class = typename std::enable_if
535  <
536  std::is_constructible
537  <
538  zoned_time,
539  decltype(zoned_traits<T>::locate_zone(std::string())),
540  local_time<Duration>
541  >::value
542  >::type>
543 #endif
544  zoned_time(const std::string& name, const local_time<Duration>& tp);
545 
546 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
547  template <class T = TimeZonePtr,
548  class = typename std::enable_if
549  <
550  std::is_constructible
551  <
552  zoned_time,
553  decltype(zoned_traits<T>::locate_zone(std::string())),
554  local_time<Duration>
555  >::value
556  >::type>
557 #endif
558  zoned_time(const char* name, const local_time<Duration>& tp);
559 
560 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
561  template <class T = TimeZonePtr,
562  class = typename std::enable_if
563  <
564  std::is_constructible
565  <
566  zoned_time,
567  decltype(zoned_traits<T>::locate_zone(std::string())),
568  local_time<Duration>,
569  choose
570  >::value
571  >::type>
572 #endif
573  zoned_time(const std::string& name, const local_time<Duration>& tp, choose c);
574 
575 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
576  template <class T = TimeZonePtr,
577  class = typename std::enable_if
578  <
579  std::is_constructible
580  <
581  zoned_time,
582  decltype(zoned_traits<T>::locate_zone(std::string())),
583  local_time<Duration>,
584  choose
585  >::value
586  >::type>
587 #endif
588  zoned_time(const char* name, const local_time<Duration>& tp, choose c);
589 
590 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
591  template <class T = TimeZonePtr,
592  class = typename std::enable_if
593  <
594  std::is_constructible
595  <
596  zoned_time,
597  decltype(zoned_traits<T>::locate_zone(std::string())),
598  zoned_time
599  >::value
600  >::type>
601 #endif
602  zoned_time(const std::string& name, const zoned_time& zt);
603 
604 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
605  template <class T = TimeZonePtr,
606  class = typename std::enable_if
607  <
608  std::is_constructible
609  <
610  zoned_time,
611  decltype(zoned_traits<T>::locate_zone(std::string())),
612  zoned_time
613  >::value
614  >::type>
615 #endif
616  zoned_time(const char* name, const zoned_time& zt);
617 
618 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
619  template <class T = TimeZonePtr,
620  class = typename std::enable_if
621  <
622  std::is_constructible
623  <
624  zoned_time,
625  decltype(zoned_traits<T>::locate_zone(std::string())),
626  zoned_time,
627  choose
628  >::value
629  >::type>
630 #endif
631  zoned_time(const std::string& name, const zoned_time& zt, choose);
632 
633 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
634  template <class T = TimeZonePtr,
635  class = typename std::enable_if
636  <
637  std::is_constructible
638  <
639  zoned_time,
640  decltype(zoned_traits<T>::locate_zone(std::string())),
641  zoned_time,
642  choose
643  >::value
644  >::type>
645 #endif
646  zoned_time(const char* name, const zoned_time& zt, choose);
647 
648 #endif // !HAS_STRING_VIEW
649 
650  zoned_time& operator=(const sys_time<Duration>& st);
651  zoned_time& operator=(const local_time<Duration>& ut);
652 
653  explicit operator sys_time<duration>() const;
654  explicit operator local_time<duration>() const;
655 
656  TimeZonePtr get_time_zone() const;
657  local_time<duration> get_local_time() const;
658  sys_time<duration> get_sys_time() const;
659  sys_info get_info() const;
660 
661  template <class Duration1, class Duration2, class TimeZonePtr1>
662  friend
663  bool
666 
667  template <class CharT, class Traits, class Duration1, class TimeZonePtr1>
668  friend
669  std::basic_ostream<CharT, Traits>&
670  operator<<(std::basic_ostream<CharT, Traits>& os,
672 
673 private:
674  template <class D, class T> friend class zoned_time;
675 };
676 
678 
679 #if HAS_DEDUCTION_GUIDES
680 
681 zoned_time()
683 
684 template <class Duration>
685 zoned_time(sys_time<Duration>)
687 
688 template <class TimeZonePtr>
689 zoned_time(TimeZonePtr)
691 
692 template <class TimeZonePtr, class Duration>
693 zoned_time(TimeZonePtr, sys_time<Duration>)
695 
696 template <class TimeZonePtr, class Duration>
697 zoned_time(TimeZonePtr, local_time<Duration>, choose = choose::earliest)
699 
700 #if HAS_STRING_VIEW
701 
702 zoned_time(std::string_view)
704 
705 template <class Duration>
706 zoned_time(std::string_view, sys_time<Duration>)
708 
709 template <class Duration>
710 zoned_time(std::string_view, local_time<Duration>, choose = choose::earliest)
712 
713 #else // !HAS_STRING_VIEW
714 
715 zoned_time(std::string)
717 
718 template <class Duration>
719 zoned_time(std::string, sys_time<Duration>)
721 
722 template <class Duration>
723 zoned_time(std::string, local_time<Duration>, choose = choose::earliest)
725 
726 #endif // !HAS_STRING_VIEW
727 
728 template <class Duration>
729 zoned_time(const char*, sys_time<Duration>)
731 
732 template <class Duration>
733 zoned_time(const char*, local_time<Duration>, choose = choose::earliest)
735 
736 template <class Duration, class TimeZonePtr, class TimeZonePtr2>
737 zoned_time(TimeZonePtr, zoned_time<Duration, TimeZonePtr2>)
739 
740 template <class Duration, class TimeZonePtr, class TimeZonePtr2>
741 zoned_time(TimeZonePtr, zoned_time<Duration, TimeZonePtr2>, choose)
743 
744 #endif // HAS_DEDUCTION_GUIDES
745 
746 template <class Duration1, class Duration2, class TimeZonePtr>
747 inline
748 bool
751 {
752  return x.zone_ == y.zone_ && x.tp_ == y.tp_;
753 }
754 
755 template <class Duration1, class Duration2, class TimeZonePtr>
756 inline
757 bool
760 {
761  return !(x == y);
762 }
763 
764 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
765 
766 namespace detail
767 {
768 # if USE_OS_TZDB
769  struct transition;
770  struct expanded_ttinfo;
771 # else // !USE_OS_TZDB
772  struct zonelet;
773  class Rule;
774 # endif // !USE_OS_TZDB
775 }
776 
777 #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
778 
780 {
781 private:
782  std::string name_;
783 #if USE_OS_TZDB
784  std::vector<detail::transition> transitions_;
785  std::vector<detail::expanded_ttinfo> ttinfos_;
786 #else // !USE_OS_TZDB
787  std::vector<detail::zonelet> zonelets_;
788 #endif // !USE_OS_TZDB
789  std::unique_ptr<std::once_flag> adjusted_;
790 
791 public:
792 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
793  time_zone(time_zone&&) = default;
794  time_zone& operator=(time_zone&&) = default;
795 #else // defined(_MSC_VER) && (_MSC_VER < 1900)
796  time_zone(time_zone&& src);
797  time_zone& operator=(time_zone&& src);
798 #endif // defined(_MSC_VER) && (_MSC_VER < 1900)
799 
800  DATE_API explicit time_zone(const std::string& s, detail::undocumented);
801 
802  const std::string& name() const NOEXCEPT;
803 
804  template <class Duration> sys_info get_info(sys_time<Duration> st) const;
805  template <class Duration> local_info get_info(local_time<Duration> tp) const;
806 
807  template <class Duration>
809  to_sys(local_time<Duration> tp) const;
810 
811  template <class Duration>
813  to_sys(local_time<Duration> tp, choose z) const;
814 
815  template <class Duration>
817  to_local(sys_time<Duration> tp) const;
818 
819  friend bool operator==(const time_zone& x, const time_zone& y) NOEXCEPT;
820  friend bool operator< (const time_zone& x, const time_zone& y) NOEXCEPT;
821  friend DATE_API std::ostream& operator<<(std::ostream& os, const time_zone& z);
822 
823 #if !USE_OS_TZDB
824  DATE_API void add(const std::string& s);
825 #endif // !USE_OS_TZDB
826 
827 private:
828  DATE_API sys_info get_info_impl(sys_seconds tp) const;
829  DATE_API local_info get_info_impl(local_seconds tp) const;
830 
831  template <class Duration>
833  to_sys_impl(local_time<Duration> tp, choose z, std::false_type) const;
834  template <class Duration>
836  to_sys_impl(local_time<Duration> tp, choose, std::true_type) const;
837 
838 #if USE_OS_TZDB
839  DATE_API void init() const;
840  DATE_API void init_impl();
842  load_sys_info(std::vector<detail::transition>::const_iterator i) const;
843 
844  template <class TimeType>
845  DATE_API void
846  load_data(std::istream& inf, std::int32_t tzh_leapcnt, std::int32_t tzh_timecnt,
847  std::int32_t tzh_typecnt, std::int32_t tzh_charcnt);
848 #else // !USE_OS_TZDB
849  DATE_API sys_info get_info_impl(sys_seconds tp, int timezone) const;
850  DATE_API void adjust_infos(const std::vector<detail::Rule>& rules);
851  DATE_API void parse_info(std::istream& in);
852 #endif // !USE_OS_TZDB
853 };
854 
855 #if defined(_MSC_VER) && (_MSC_VER < 1900)
856 
857 inline
859  : name_(std::move(src.name_))
860  , zonelets_(std::move(src.zonelets_))
861  , adjusted_(std::move(src.adjusted_))
862  {}
863 
864 inline
865 time_zone&
867 {
868  name_ = std::move(src.name_);
869  zonelets_ = std::move(src.zonelets_);
870  adjusted_ = std::move(src.adjusted_);
871  return *this;
872 }
873 
874 #endif // defined(_MSC_VER) && (_MSC_VER < 1900)
875 
876 inline
877 const std::string&
878 time_zone::name() const NOEXCEPT
879 {
880  return name_;
881 }
882 
883 template <class Duration>
884 inline
885 sys_info
887 {
888  using namespace std::chrono;
889  return get_info_impl(date::floor<seconds>(st));
890 }
891 
892 template <class Duration>
893 inline
895 time_zone::get_info(local_time<Duration> tp) const
896 {
897  using namespace std::chrono;
898  return get_info_impl(date::floor<seconds>(tp));
899 }
900 
901 template <class Duration>
902 inline
904 time_zone::to_sys(local_time<Duration> tp) const
905 {
906  return to_sys_impl(tp, choose{}, std::true_type{});
907 }
908 
909 template <class Duration>
910 inline
912 time_zone::to_sys(local_time<Duration> tp, choose z) const
913 {
914  return to_sys_impl(tp, z, std::false_type{});
915 }
916 
917 template <class Duration>
918 inline
921 {
923  auto i = get_info(tp);
924  return LT{(tp + i.offset).time_since_epoch()};
925 }
926 
927 inline bool operator==(const time_zone& x, const time_zone& y) NOEXCEPT {return x.name_ == y.name_;}
928 inline bool operator< (const time_zone& x, const time_zone& y) NOEXCEPT {return x.name_ < y.name_;}
929 
930 inline bool operator!=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(x == y);}
931 inline bool operator> (const time_zone& x, const time_zone& y) NOEXCEPT {return y < x;}
932 inline bool operator<=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(y < x);}
933 inline bool operator>=(const time_zone& x, const time_zone& y) NOEXCEPT {return !(x < y);}
934 
935 template <class Duration>
937 time_zone::to_sys_impl(local_time<Duration> tp, choose z, std::false_type) const
938 {
939  using namespace date;
940  using namespace std::chrono;
941  auto i = get_info(tp);
943  {
944  return i.first.end;
945  }
946  else if (i.result == local_info::ambiguous)
947  {
948  if (z == choose::latest)
949  return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
950  }
951  return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
952 }
953 
954 template <class Duration>
956 time_zone::to_sys_impl(local_time<Duration> tp, choose, std::true_type) const
957 {
958  using namespace date;
959  using namespace std::chrono;
960  auto i = get_info(tp);
962  throw nonexistent_local_time(tp, i);
963  else if (i.result == local_info::ambiguous)
964  throw ambiguous_local_time(tp, i);
965  return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
966 }
967 
968 #if !USE_OS_TZDB
969 
970 class link
971 {
972 private:
973  std::string name_;
974  std::string target_;
975 public:
976  DATE_API explicit link(const std::string& s);
977 
978  const std::string& name() const {return name_;}
979  const std::string& target() const {return target_;}
980 
981  friend bool operator==(const link& x, const link& y) {return x.name_ == y.name_;}
982  friend bool operator< (const link& x, const link& y) {return x.name_ < y.name_;}
983 
984  friend DATE_API std::ostream& operator<<(std::ostream& os, const link& x);
985 };
986 
987 inline bool operator!=(const link& x, const link& y) {return !(x == y);}
988 inline bool operator> (const link& x, const link& y) {return y < x;}
989 inline bool operator<=(const link& x, const link& y) {return !(y < x);}
990 inline bool operator>=(const link& x, const link& y) {return !(x < y);}
991 
992 #endif // !USE_OS_TZDB
993 
994 #if !MISSING_LEAP_SECONDS
995 
996 class leap
997 {
998 private:
999  sys_seconds date_;
1000 
1001 public:
1002 #if USE_OS_TZDB
1003  DATE_API explicit leap(const sys_seconds& s, detail::undocumented);
1004 #else
1005  DATE_API explicit leap(const std::string& s, detail::undocumented);
1006 #endif
1007 
1008  sys_seconds date() const {return date_;}
1009 
1010  friend bool operator==(const leap& x, const leap& y) {return x.date_ == y.date_;}
1011  friend bool operator< (const leap& x, const leap& y) {return x.date_ < y.date_;}
1012 
1013  template <class Duration>
1014  friend
1015  bool
1016  operator==(const leap& x, const sys_time<Duration>& y)
1017  {
1018  return x.date_ == y;
1019  }
1020 
1021  template <class Duration>
1022  friend
1023  bool
1024  operator< (const leap& x, const sys_time<Duration>& y)
1025  {
1026  return x.date_ < y;
1027  }
1028 
1029  template <class Duration>
1030  friend
1031  bool
1032  operator< (const sys_time<Duration>& x, const leap& y)
1033  {
1034  return x < y.date_;
1035  }
1036 
1037  friend DATE_API std::ostream& operator<<(std::ostream& os, const leap& x);
1038 };
1039 
1040 inline bool operator!=(const leap& x, const leap& y) {return !(x == y);}
1041 inline bool operator> (const leap& x, const leap& y) {return y < x;}
1042 inline bool operator<=(const leap& x, const leap& y) {return !(y < x);}
1043 inline bool operator>=(const leap& x, const leap& y) {return !(x < y);}
1044 
1045 template <class Duration>
1046 inline
1047 bool
1049 {
1050  return y == x;
1051 }
1052 
1053 template <class Duration>
1054 inline
1055 bool
1057 {
1058  return !(x == y);
1059 }
1060 
1061 template <class Duration>
1062 inline
1063 bool
1065 {
1066  return !(x == y);
1067 }
1068 
1069 template <class Duration>
1070 inline
1071 bool
1073 {
1074  return y < x;
1075 }
1076 
1077 template <class Duration>
1078 inline
1079 bool
1081 {
1082  return y < x;
1083 }
1084 
1085 template <class Duration>
1086 inline
1087 bool
1088 operator<=(const leap& x, const sys_time<Duration>& y)
1089 {
1090  return !(y < x);
1091 }
1092 
1093 template <class Duration>
1094 inline
1095 bool
1096 operator<=(const sys_time<Duration>& x, const leap& y)
1097 {
1098  return !(y < x);
1099 }
1100 
1101 template <class Duration>
1102 inline
1103 bool
1105 {
1106  return !(x < y);
1107 }
1108 
1109 template <class Duration>
1110 inline
1111 bool
1113 {
1114  return !(x < y);
1115 }
1116 
1117 #endif // !MISSING_LEAP_SECONDS
1118 
1119 #ifdef _WIN32
1120 
1121 namespace detail
1122 {
1123 
1124 // The time zone mapping is modelled after this data file:
1125 // http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
1126 // and the field names match the element names from the mapZone element
1127 // of windowsZones.xml.
1128 // The website displays this file here:
1129 // http://www.unicode.org/cldr/charts/latest/supplemental/zone_tzid.html
1130 // The html view is sorted before being displayed but is otherwise the same
1131 // There is a mapping between the os centric view (in this case windows)
1132 // the html displays uses and the generic view the xml file.
1133 // That mapping is this:
1134 // display column "windows" -> xml field "other".
1135 // display column "region" -> xml field "territory".
1136 // display column "tzid" -> xml field "type".
1137 // This structure uses the generic terminology because it could be
1138 // used to to support other os/native name conversions, not just windows,
1139 // and using the same generic names helps retain the connection to the
1140 // origin of the data that we are using.
1141 struct timezone_mapping
1142 {
1143  timezone_mapping(const char* other, const char* territory, const char* type)
1144  : other(other), territory(territory), type(type)
1145  {
1146  }
1147  timezone_mapping() = default;
1148  std::string other;
1149  std::string territory;
1150  std::string type;
1151 };
1152 
1153 } // detail
1154 
1155 #endif // _WIN32
1156 
1157 struct tzdb
1158 {
1159  std::string version = "unknown";
1160  std::vector<time_zone> zones;
1161 #if !USE_OS_TZDB
1162  std::vector<link> links;
1163 #endif
1164 #if !MISSING_LEAP_SECONDS
1165  std::vector<leap> leaps;
1166 #endif
1167 #if !USE_OS_TZDB
1168  std::vector<detail::Rule> rules;
1169 #endif
1170 #ifdef _WIN32
1171  std::vector<detail::timezone_mapping> mappings;
1172 #endif
1173  tzdb* next = nullptr;
1174 
1175  tzdb() = default;
1176 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
1177  tzdb(tzdb&&) = default;
1178  tzdb& operator=(tzdb&&) = default;
1179 #else // defined(_MSC_VER) && (_MSC_VER < 1900)
1180  tzdb(tzdb&& src)
1181  : version(std::move(src.version))
1182  , zones(std::move(src.zones))
1183  , links(std::move(src.links))
1184  , leaps(std::move(src.leaps))
1185  , rules(std::move(src.rules))
1186  , mappings(std::move(src.mappings))
1187  {}
1188 
1189  tzdb& operator=(tzdb&& src)
1190  {
1191  version = std::move(src.version);
1192  zones = std::move(src.zones);
1193  links = std::move(src.links);
1194  leaps = std::move(src.leaps);
1195  rules = std::move(src.rules);
1196  mappings = std::move(src.mappings);
1197  return *this;
1198  }
1199 #endif // defined(_MSC_VER) && (_MSC_VER < 1900)
1200 
1201 #if HAS_STRING_VIEW
1202  const time_zone* locate_zone(std::string_view tz_name) const;
1203 #else
1204  const time_zone* locate_zone(const std::string& tz_name) const;
1205 #endif
1206  const time_zone* current_zone() const;
1207 };
1208 
1209 using TZ_DB = tzdb;
1210 
1211 DATE_API std::ostream&
1212 operator<<(std::ostream& os, const tzdb& db);
1213 
1214 DATE_API const tzdb& get_tzdb();
1215 
1217 {
1218  std::atomic<tzdb*> head_{nullptr};
1219 
1220 public:
1221  ~tzdb_list();
1222  tzdb_list() = default;
1223  tzdb_list(tzdb_list&& x) noexcept;
1224 
1225  const tzdb& front() const noexcept {return *head_;}
1226  tzdb& front() noexcept {return *head_;}
1227 
1228  class const_iterator;
1229 
1230  const_iterator begin() const noexcept;
1231  const_iterator end() const noexcept;
1232 
1233  const_iterator cbegin() const noexcept;
1234  const_iterator cend() const noexcept;
1235 
1236  const_iterator erase_after(const_iterator p) noexcept;
1237 
1238  struct undocumented_helper;
1239 private:
1240  void push_front(tzdb* tzdb) noexcept;
1241 };
1242 
1244 {
1245  tzdb* p_ = nullptr;
1246 
1247  explicit const_iterator(tzdb* p) noexcept : p_{p} {}
1248 public:
1249  const_iterator() = default;
1250 
1251  using iterator_category = std::forward_iterator_tag;
1252  using value_type = tzdb;
1253  using reference = const value_type&;
1254  using pointer = const value_type*;
1255  using difference_type = std::ptrdiff_t;
1256 
1257  reference operator*() const noexcept {return *p_;}
1258  pointer operator->() const noexcept {return p_;}
1259 
1260  const_iterator& operator++() noexcept {p_ = p_->next; return *this;}
1261  const_iterator operator++(int) noexcept {auto t = *this; ++(*this); return t;}
1262 
1263  friend
1264  bool
1265  operator==(const const_iterator& x, const const_iterator& y) noexcept
1266  {return x.p_ == y.p_;}
1267 
1268  friend
1269  bool
1270  operator!=(const const_iterator& x, const const_iterator& y) noexcept
1271  {return !(x == y);}
1272 
1273  friend class tzdb_list;
1274 };
1275 
1276 inline
1278 tzdb_list::begin() const noexcept
1279 {
1280  return const_iterator{head_};
1281 }
1282 
1283 inline
1285 tzdb_list::end() const noexcept
1286 {
1287  return const_iterator{nullptr};
1288 }
1289 
1290 inline
1292 tzdb_list::cbegin() const noexcept
1293 {
1294  return begin();
1295 }
1296 
1297 inline
1299 tzdb_list::cend() const noexcept
1300 {
1301  return end();
1302 }
1303 
1305 
1306 #if !USE_OS_TZDB
1307 
1308 DATE_API const tzdb& reload_tzdb();
1309 DATE_API void set_install(const std::string& install);
1310 
1311 #endif // !USE_OS_TZDB
1312 
1313 #if HAS_REMOTE_API
1314 
1315 DATE_API std::string remote_version();
1316 DATE_API bool remote_download(const std::string& version);
1317 DATE_API bool remote_install(const std::string& version);
1318 
1319 #endif
1320 
1321 // zoned_time
1322 
1323 namespace detail
1324 {
1325 
1326 template <class T>
1327 inline
1328 T*
1329 to_raw_pointer(T* p) noexcept
1330 {
1331  return p;
1332 }
1333 
1334 template <class Pointer>
1335 inline
1336 auto
1337 to_raw_pointer(Pointer p) noexcept
1338  -> decltype(detail::to_raw_pointer(p.operator->()))
1339 {
1340  return detail::to_raw_pointer(p.operator->());
1341 }
1342 
1343 } // namespace detail
1344 
1345 template <class Duration, class TimeZonePtr>
1346 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1347 template <class T, class>
1348 #endif
1349 inline
1351  : zone_(zoned_traits<TimeZonePtr>::default_zone())
1352  {}
1353 
1354 template <class Duration, class TimeZonePtr>
1355 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1356 template <class T, class>
1357 #endif
1358 inline
1360  : zone_(zoned_traits<TimeZonePtr>::default_zone())
1361  , tp_(st)
1362  {}
1363 
1364 template <class Duration, class TimeZonePtr>
1365 inline
1367  : zone_(std::move(z))
1368  {assert(detail::to_raw_pointer(zone_) != nullptr);}
1369 
1370 #if HAS_STRING_VIEW
1371 
1372 template <class Duration, class TimeZonePtr>
1373 template <class, class>
1374 inline
1375 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name)
1377  {}
1378 
1379 #else // !HAS_STRING_VIEW
1380 
1381 template <class Duration, class TimeZonePtr>
1382 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1383 template <class T, class>
1384 #endif
1385 inline
1387  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name))
1388  {}
1389 
1390 #endif // !HAS_STRING_VIEW
1391 
1392 template <class Duration, class TimeZonePtr>
1393 template <class Duration2, class>
1394 inline
1396  : zone_(zt.zone_)
1397  , tp_(zt.tp_)
1398  {}
1399 
1400 template <class Duration, class TimeZonePtr>
1401 inline
1403  : zone_(std::move(z))
1404  , tp_(st)
1405  {}
1406 
1407 template <class Duration, class TimeZonePtr>
1408 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1409 template <class T, class>
1410 #endif
1411 inline
1412 zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t)
1413  : zone_(std::move(z))
1414  , tp_(zone_->to_sys(t))
1415  {}
1416 
1417 template <class Duration, class TimeZonePtr>
1418 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1419 template <class T, class>
1420 #endif
1421 inline
1422 zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& t,
1423  choose c)
1424  : zone_(std::move(z))
1425  , tp_(zone_->to_sys(t, c))
1426  {}
1427 
1428 template <class Duration, class TimeZonePtr>
1429 template <class Duration2, class TimeZonePtr2, class>
1430 inline
1433  : zone_(std::move(z))
1434  , tp_(zt.tp_)
1435  {}
1436 
1437 template <class Duration, class TimeZonePtr>
1438 template <class Duration2, class TimeZonePtr2, class>
1439 inline
1442  : zoned_time(std::move(z), zt)
1443  {}
1444 
1445 #if HAS_STRING_VIEW
1446 
1447 template <class Duration, class TimeZonePtr>
1448 template <class, class>
1449 inline
1450 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
1451  const sys_time<Duration>& st)
1453  {}
1454 
1455 template <class Duration, class TimeZonePtr>
1456 template <class, class>
1457 inline
1458 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
1459  const local_time<Duration>& t)
1461  {}
1462 
1463 template <class Duration, class TimeZonePtr>
1464 template <class, class>
1465 inline
1466 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
1467  const local_time<Duration>& t, choose c)
1469  {}
1470 
1471 template <class Duration, class TimeZonePtr>
1472 template <class, class>
1473 inline
1474 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name, const zoned_time& zt)
1476  {}
1477 
1478 template <class Duration, class TimeZonePtr>
1479 template <class, class>
1480 inline
1481 zoned_time<Duration, TimeZonePtr>::zoned_time(std::string_view name,
1482  const zoned_time& zt, choose c)
1484  {}
1485 
1486 #else // !HAS_STRING_VIEW
1487 
1488 template <class Duration, class TimeZonePtr>
1489 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1490 template <class T, class>
1491 #endif
1492 inline
1494  const sys_time<Duration>& st)
1495  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), st)
1496  {}
1497 
1498 template <class Duration, class TimeZonePtr>
1499 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1500 template <class T, class>
1501 #endif
1502 inline
1504  const sys_time<Duration>& st)
1505  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), st)
1506  {}
1507 
1508 template <class Duration, class TimeZonePtr>
1509 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1510 template <class T, class>
1511 #endif
1512 inline
1514  const local_time<Duration>& t)
1515  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t)
1516  {}
1517 
1518 template <class Duration, class TimeZonePtr>
1519 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1520 template <class T, class>
1521 #endif
1522 inline
1524  const local_time<Duration>& t)
1525  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t)
1526  {}
1527 
1528 template <class Duration, class TimeZonePtr>
1529 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1530 template <class T, class>
1531 #endif
1532 inline
1534  const local_time<Duration>& t, choose c)
1535  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t, c)
1536  {}
1537 
1538 template <class Duration, class TimeZonePtr>
1539 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1540 template <class T, class>
1541 #endif
1542 inline
1544  const local_time<Duration>& t, choose c)
1545  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), t, c)
1546  {}
1547 
1548 template <class Duration, class TimeZonePtr>
1549 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1550 template <class T, class>
1551 #endif
1552 inline
1554  const zoned_time& zt)
1555  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt)
1556  {}
1557 
1558 template <class Duration, class TimeZonePtr>
1559 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1560 template <class T, class>
1561 #endif
1562 inline
1563 zoned_time<Duration, TimeZonePtr>::zoned_time(const char* name, const zoned_time& zt)
1564  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt)
1565  {}
1566 
1567 template <class Duration, class TimeZonePtr>
1568 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1569 template <class T, class>
1570 #endif
1571 inline
1573  const zoned_time& zt, choose c)
1574  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt, c)
1575  {}
1576 
1577 template <class Duration, class TimeZonePtr>
1578 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1579 template <class T, class>
1580 #endif
1581 inline
1583  const zoned_time& zt, choose c)
1584  : zoned_time(zoned_traits<TimeZonePtr>::locate_zone(name), zt, c)
1585  {}
1586 
1587 #endif // HAS_STRING_VIEW
1588 
1589 template <class Duration, class TimeZonePtr>
1590 inline
1593 {
1594  tp_ = st;
1595  return *this;
1596 }
1597 
1598 template <class Duration, class TimeZonePtr>
1599 inline
1601 zoned_time<Duration, TimeZonePtr>::operator=(const local_time<Duration>& ut)
1602 {
1603  tp_ = zone_->to_sys(ut);
1604  return *this;
1605 }
1606 
1607 template <class Duration, class TimeZonePtr>
1608 inline
1610 {
1611  return get_local_time();
1612 }
1613 
1614 template <class Duration, class TimeZonePtr>
1615 inline
1617 {
1618  return get_sys_time();
1619 }
1620 
1621 template <class Duration, class TimeZonePtr>
1622 inline
1623 TimeZonePtr
1625 {
1626  return zone_;
1627 }
1628 
1629 template <class Duration, class TimeZonePtr>
1630 inline
1633 {
1634  return zone_->to_local(tp_);
1635 }
1636 
1637 template <class Duration, class TimeZonePtr>
1638 inline
1641 {
1642  return tp_;
1643 }
1644 
1645 template <class Duration, class TimeZonePtr>
1646 inline
1647 sys_info
1649 {
1650  return zone_->get_info(tp_);
1651 }
1652 
1653 // make_zoned_time
1654 
1655 inline
1658 {
1660 }
1661 
1662 template <class Duration>
1663 inline
1666 {
1668 }
1669 
1670 template <class TimeZonePtr
1671 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1672  , class = typename std::enable_if
1673  <
1674  std::is_class
1675  <
1676  typename std::decay
1677  <
1678  decltype(*detail::to_raw_pointer(std::declval<TimeZonePtr&>()))
1679  >::type
1680  >{}
1681  >::type
1682 #endif
1683  >
1684 inline
1686 make_zoned(TimeZonePtr z)
1687 {
1688  return zoned_time<std::chrono::seconds, TimeZonePtr>(std::move(z));
1689 }
1690 
1691 inline
1693 make_zoned(const std::string& name)
1694 {
1695  return zoned_seconds(name);
1696 }
1697 
1698 template <class Duration, class TimeZonePtr
1699 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1700  , class = typename std::enable_if
1701  <
1702  std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
1703  >::type
1704 #endif
1705  >
1706 inline
1708 make_zoned(TimeZonePtr zone, const local_time<Duration>& tp)
1709 {
1710  return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
1711  TimeZonePtr>(std::move(zone), tp);
1712 }
1713 
1714 template <class Duration, class TimeZonePtr
1715 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1716  , class = typename std::enable_if
1717  <
1718  std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
1719  >::type
1720 #endif
1721  >
1722 inline
1723 zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type, TimeZonePtr>
1724 make_zoned(TimeZonePtr zone, const local_time<Duration>& tp, choose c)
1725 {
1726  return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
1727  TimeZonePtr>(std::move(zone), tp, c);
1728 }
1729 
1730 template <class Duration>
1731 inline
1732 zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
1733 make_zoned(const std::string& name, const local_time<Duration>& tp)
1734 {
1735  return zoned_time<typename std::common_type<Duration,
1736  std::chrono::seconds>::type>(name, tp);
1737 }
1738 
1739 template <class Duration>
1740 inline
1741 zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
1742 make_zoned(const std::string& name, const local_time<Duration>& tp, choose c)
1743 {
1744  return zoned_time<typename std::common_type<Duration,
1745  std::chrono::seconds>::type>(name, tp, c);
1746 }
1747 
1748 template <class Duration, class TimeZonePtr>
1749 inline
1751 make_zoned(TimeZonePtr zone, const zoned_time<Duration, TimeZonePtr>& zt)
1752 {
1753  return zoned_time<Duration, TimeZonePtr>(std::move(zone), zt);
1754 }
1755 
1756 template <class Duration, class TimeZonePtr>
1757 inline
1759 make_zoned(const std::string& name, const zoned_time<Duration, TimeZonePtr>& zt)
1760 {
1761  return zoned_time<Duration, TimeZonePtr>(name, zt);
1762 }
1763 
1764 template <class Duration, class TimeZonePtr>
1765 inline
1767 make_zoned(TimeZonePtr zone, const zoned_time<Duration, TimeZonePtr>& zt, choose c)
1768 {
1769  return zoned_time<Duration, TimeZonePtr>(std::move(zone), zt, c);
1770 }
1771 
1772 template <class Duration, class TimeZonePtr>
1773 inline
1775 make_zoned(const std::string& name, const zoned_time<Duration, TimeZonePtr>& zt, choose c)
1776 {
1777  return zoned_time<Duration, TimeZonePtr>(name, zt, c);
1778 }
1779 
1780 template <class Duration, class TimeZonePtr
1781 #if !defined(_MSC_VER) || (_MSC_VER > 1900)
1782  , class = typename std::enable_if
1783  <
1784  std::is_class<typename std::decay<decltype(*std::declval<TimeZonePtr&>())>::type>{}
1785  >::type
1786 #endif
1787  >
1788 inline
1789 zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type, TimeZonePtr>
1790 make_zoned(TimeZonePtr zone, const sys_time<Duration>& st)
1791 {
1792  return zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type,
1793  TimeZonePtr>(std::move(zone), st);
1794 }
1795 
1796 template <class Duration>
1797 inline
1798 zoned_time<typename std::common_type<Duration, std::chrono::seconds>::type>
1799 make_zoned(const std::string& name, const sys_time<Duration>& st)
1800 {
1801  return zoned_time<typename std::common_type<Duration,
1802  std::chrono::seconds>::type>(name, st);
1803 }
1804 
1805 template <class CharT, class Traits, class Duration, class TimeZonePtr>
1806 std::basic_ostream<CharT, Traits>&
1807 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
1809 {
1811  using LT = local_time<duration>;
1812  auto const tz = tp.get_time_zone();
1813  auto const st = tp.get_sys_time();
1814  auto const info = tz->get_info(st);
1815  return to_stream(os, fmt, LT{(st+info.offset).time_since_epoch()},
1816  &info.abbrev, &info.offset);
1817 }
1818 
1819 template <class CharT, class Traits, class Duration, class TimeZonePtr>
1820 inline
1821 std::basic_ostream<CharT, Traits>&
1822 operator<<(std::basic_ostream<CharT, Traits>& os, const zoned_time<Duration, TimeZonePtr>& t)
1823 {
1824  const CharT fmt[] = {'%', 'F', ' ', '%', 'T', ' ', '%', 'Z', CharT{}};
1825  return to_stream(os, fmt, t);
1826 }
1827 
1828 #if !MISSING_LEAP_SECONDS
1829 
1831 {
1832 public:
1833  using duration = std::chrono::system_clock::duration;
1834  using rep = duration::rep;
1835  using period = duration::period;
1836  using time_point = std::chrono::time_point<utc_clock>;
1837  static CONSTDATA bool is_steady = false;
1838 
1839  static time_point now();
1840 
1841  template<typename Duration>
1842  static
1843  std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
1844  to_sys(const std::chrono::time_point<utc_clock, Duration>&);
1845 
1846  template<typename Duration>
1847  static
1848  std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
1849  from_sys(const std::chrono::time_point<std::chrono::system_clock, Duration>&);
1850 };
1851 
1852 template <class Duration>
1853  using utc_time = std::chrono::time_point<utc_clock, Duration>;
1854 
1856 
1857 template <class Duration>
1860 {
1861  using namespace std::chrono;
1862  using duration = typename std::common_type<Duration, seconds>::type;
1863  auto const& leaps = get_tzdb().leaps;
1864  auto const lt = std::upper_bound(leaps.begin(), leaps.end(), st);
1865  return utc_time<duration>{st.time_since_epoch() + seconds{lt-leaps.begin()}};
1866 }
1867 
1868 // Return pair<is_leap_second, seconds{number_of_leap_seconds_since_1970}>
1869 // first is true if ut is during a leap second insertion, otherwise false.
1870 // If ut is during a leap second insertion, that leap second is included in the count
1871 template <class Duration>
1872 std::pair<bool, std::chrono::seconds>
1874 {
1875  using namespace date;
1876  using namespace std::chrono;
1877  using duration = typename std::common_type<Duration, seconds>::type;
1878  auto const& leaps = get_tzdb().leaps;
1879  auto tp = sys_time<duration>{ut.time_since_epoch()};
1880  auto const lt = std::upper_bound(leaps.begin(), leaps.end(), tp);
1881  auto ds = seconds{lt-leaps.begin()};
1882  tp -= ds;
1883  auto ls = false;
1884  if (lt > leaps.begin())
1885  {
1886  if (tp < lt[-1])
1887  {
1888  if (tp >= lt[-1].date() - seconds{1})
1889  ls = true;
1890  else
1891  --ds;
1892  }
1893  }
1894  return {ls, ds};
1895 }
1896 
1897 template <class Duration>
1900 {
1901  using namespace std::chrono;
1902  using duration = typename std::common_type<Duration, seconds>::type;
1903  auto ls = is_leap_second(ut);
1904  auto tp = sys_time<duration>{ut.time_since_epoch() - ls.second};
1905  if (ls.first)
1906  tp = floor<seconds>(tp) + seconds{1} - duration{1};
1907  return tp;
1908 }
1909 
1910 inline
1913 {
1914  using namespace std::chrono;
1915  return from_sys(system_clock::now());
1916 }
1917 
1918 template <class CharT, class Traits, class Duration>
1919 std::basic_ostream<CharT, Traits>&
1920 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
1921  const utc_time<Duration>& t)
1922 {
1923  using namespace std;
1924  using namespace std::chrono;
1925  using CT = typename common_type<Duration, seconds>::type;
1926  const string abbrev("UTC");
1927  CONSTDATA seconds offset{0};
1928  auto ls = is_leap_second(t);
1929  auto tp = sys_time<CT>{t.time_since_epoch() - ls.second};
1930  auto const sd = floor<days>(tp);
1931  year_month_day ymd = sd;
1932  auto time = make_time(tp - sys_seconds{sd});
1933  time.seconds() += seconds{ls.first};
1934  fields<CT> fds{ymd, time};
1935  return to_stream(os, fmt, fds, &abbrev, &offset);
1936 }
1937 
1938 template <class CharT, class Traits, class Duration>
1939 std::basic_ostream<CharT, Traits>&
1940 operator<<(std::basic_ostream<CharT, Traits>& os, const utc_time<Duration>& t)
1941 {
1942  const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
1943  return to_stream(os, fmt, t);
1944 }
1945 
1946 template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
1947 std::basic_istream<CharT, Traits>&
1948 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
1949  utc_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
1950  std::chrono::minutes* offset = nullptr)
1951 {
1952  using namespace std;
1953  using namespace std::chrono;
1954  using CT = typename common_type<Duration, seconds>::type;
1955  minutes offset_local{};
1956  auto offptr = offset ? offset : &offset_local;
1957  fields<CT> fds{};
1958  from_stream(is, fmt, fds, abbrev, offptr);
1959  if (!fds.ymd.ok())
1960  is.setstate(ios::failbit);
1961  if (!is.fail())
1962  {
1963  bool is_60_sec = fds.tod.seconds() == seconds{60};
1964  if (is_60_sec)
1965  fds.tod.seconds() -= seconds{1};
1966  auto tmp = utc_clock::from_sys(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
1967  if (is_60_sec)
1968  tmp += seconds{1};
1969  if (is_60_sec != is_leap_second(tmp).first || !fds.tod.in_conventional_range())
1970  {
1971  is.setstate(ios::failbit);
1972  return is;
1973  }
1974  tp = time_point_cast<Duration>(tmp);
1975  }
1976  return is;
1977 }
1978 
1979 // tai_clock
1980 
1982 {
1983 public:
1984  using duration = std::chrono::system_clock::duration;
1985  using rep = duration::rep;
1986  using period = duration::period;
1987  using time_point = std::chrono::time_point<tai_clock>;
1988  static const bool is_steady = false;
1989 
1990  static time_point now();
1991 
1992  template<typename Duration>
1993  static
1994  std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
1995  to_utc(const std::chrono::time_point<tai_clock, Duration>&) NOEXCEPT;
1996 
1997  template<typename Duration>
1998  static
1999  std::chrono::time_point<tai_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
2000  from_utc(const std::chrono::time_point<utc_clock, Duration>&) NOEXCEPT;
2001 };
2002 
2003 template <class Duration>
2004  using tai_time = std::chrono::time_point<tai_clock, Duration>;
2005 
2007 
2008 template <class Duration>
2009 inline
2012 {
2013  using namespace std::chrono;
2014  using duration = typename std::common_type<Duration, seconds>::type;
2015  return utc_time<duration>{t.time_since_epoch()} -
2016  (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1) + seconds{10});
2017 }
2018 
2019 template <class Duration>
2020 inline
2023 {
2024  using namespace std::chrono;
2025  using duration = typename std::common_type<Duration, seconds>::type;
2026  return tai_time<duration>{t.time_since_epoch()} +
2027  (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1) + seconds{10});
2028 }
2029 
2030 inline
2033 {
2034  using namespace std::chrono;
2035  return from_utc(utc_clock::now());
2036 }
2037 
2038 template <class CharT, class Traits, class Duration>
2039 std::basic_ostream<CharT, Traits>&
2040 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
2041  const tai_time<Duration>& t)
2042 {
2043  using namespace std;
2044  using namespace std::chrono;
2045  using CT = typename common_type<Duration, seconds>::type;
2046  const string abbrev("TAI");
2047  CONSTDATA seconds offset{0};
2048  auto tp = sys_time<CT>{t.time_since_epoch()} -
2049  seconds(sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1));
2050  auto const sd = floor<days>(tp);
2051  year_month_day ymd = sd;
2052  auto time = make_time(tp - sys_seconds{sd});
2053  fields<CT> fds{ymd, time};
2054  return to_stream(os, fmt, fds, &abbrev, &offset);
2055 }
2056 
2057 template <class CharT, class Traits, class Duration>
2058 std::basic_ostream<CharT, Traits>&
2059 operator<<(std::basic_ostream<CharT, Traits>& os, const tai_time<Duration>& t)
2060 {
2061  const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
2062  return to_stream(os, fmt, t);
2063 }
2064 
2065 template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
2066 std::basic_istream<CharT, Traits>&
2067 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
2068  tai_time<Duration>& tp,
2069  std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
2070  std::chrono::minutes* offset = nullptr)
2071 {
2072  using namespace std;
2073  using namespace std::chrono;
2074  using CT = typename common_type<Duration, seconds>::type;
2075  minutes offset_local{};
2076  auto offptr = offset ? offset : &offset_local;
2077  fields<CT> fds{};
2078  from_stream(is, fmt, fds, abbrev, offptr);
2079  if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
2080  is.setstate(ios::failbit);
2081  if (!is.fail())
2082  tp = tai_time<Duration>{duration_cast<Duration>(
2083  (sys_days(fds.ymd) +
2084  (sys_days(year{1970}/jan/1) - sys_days(year{1958}/jan/1)) -
2085  *offptr + fds.tod.to_duration()).time_since_epoch())};
2086  return is;
2087 }
2088 
2089 // gps_clock
2090 
2092 {
2093 public:
2094  using duration = std::chrono::system_clock::duration;
2095  using rep = duration::rep;
2096  using period = duration::period;
2097  using time_point = std::chrono::time_point<gps_clock>;
2098  static const bool is_steady = false;
2099 
2100  static time_point now();
2101 
2102  template<typename Duration>
2103  static
2104  std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
2105  to_utc(const std::chrono::time_point<gps_clock, Duration>&) NOEXCEPT;
2106 
2107  template<typename Duration>
2108  static
2109  std::chrono::time_point<gps_clock, typename std::common_type<Duration, std::chrono::seconds>::type>
2110  from_utc(const std::chrono::time_point<utc_clock, Duration>&) NOEXCEPT;
2111 
2112 };
2113 
2114 template <class Duration>
2115  using gps_time = std::chrono::time_point<gps_clock, Duration>;
2116 
2118 
2119 template <class Duration>
2120 inline
2123 {
2124  using namespace std::chrono;
2125  using duration = typename std::common_type<Duration, seconds>::type;
2126  return utc_time<duration>{t.time_since_epoch()} +
2127  (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1) + seconds{9});
2128 }
2129 
2130 template <class Duration>
2131 inline
2134 {
2135  using namespace std::chrono;
2136  using duration = typename std::common_type<Duration, seconds>::type;
2137  return gps_time<duration>{t.time_since_epoch()} -
2138  (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1) + seconds{9});
2139 }
2140 
2141 inline
2144 {
2145  using namespace std::chrono;
2146  return from_utc(utc_clock::now());
2147 }
2148 
2149 template <class CharT, class Traits, class Duration>
2150 std::basic_ostream<CharT, Traits>&
2151 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
2152  const gps_time<Duration>& t)
2153 {
2154  using namespace std;
2155  using namespace std::chrono;
2156  using CT = typename common_type<Duration, seconds>::type;
2157  const string abbrev("GPS");
2158  CONSTDATA seconds offset{0};
2159  auto tp = sys_time<CT>{t.time_since_epoch()} +
2160  seconds(sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1));
2161  auto const sd = floor<days>(tp);
2162  year_month_day ymd = sd;
2163  auto time = make_time(tp - sys_seconds{sd});
2164  fields<CT> fds{ymd, time};
2165  return to_stream(os, fmt, fds, &abbrev, &offset);
2166 }
2167 
2168 template <class CharT, class Traits, class Duration>
2169 std::basic_ostream<CharT, Traits>&
2170 operator<<(std::basic_ostream<CharT, Traits>& os, const gps_time<Duration>& t)
2171 {
2172  const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}};
2173  return to_stream(os, fmt, t);
2174 }
2175 
2176 template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
2177 std::basic_istream<CharT, Traits>&
2178 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
2179  gps_time<Duration>& tp,
2180  std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
2181  std::chrono::minutes* offset = nullptr)
2182 {
2183  using namespace std;
2184  using namespace std::chrono;
2185  using CT = typename common_type<Duration, seconds>::type;
2186  minutes offset_local{};
2187  auto offptr = offset ? offset : &offset_local;
2188  fields<CT> fds{};
2189  from_stream(is, fmt, fds, abbrev, offptr);
2190  if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
2191  is.setstate(ios::failbit);
2192  if (!is.fail())
2193  tp = gps_time<Duration>{duration_cast<Duration>(
2194  (sys_days(fds.ymd) -
2195  (sys_days(year{1980}/jan/sun[1]) - sys_days(year{1970}/jan/1)) -
2196  *offptr + fds.tod.to_duration()).time_since_epoch())};
2197  return is;
2198 }
2199 
2200 // clock_time_conversion
2201 
2202 template <class DstClock, class SrcClock>
2204 {};
2205 
2206 template <>
2207 struct clock_time_conversion<std::chrono::system_clock, std::chrono::system_clock>
2208 {
2209  template <class Duration>
2212  {
2213  return st;
2214  }
2215 };
2216 
2217 template <>
2219 {
2220  template <class Duration>
2223  {
2224  return ut;
2225  }
2226 };
2227 
2228 template <>
2229 struct clock_time_conversion<utc_clock, std::chrono::system_clock>
2230 {
2231  template <class Duration>
2234  {
2235  return utc_clock::from_sys(st);
2236  }
2237 };
2238 
2239 template <>
2240 struct clock_time_conversion<std::chrono::system_clock, utc_clock>
2241 {
2242  template <class Duration>
2245  {
2246  return utc_clock::to_sys(ut);
2247  }
2248 };
2249 
2250 template <class Clock>
2251 struct clock_time_conversion<Clock, Clock>
2252 {
2253  template <class Duration>
2254  std::chrono::time_point<Clock, Duration>
2255  operator()(const std::chrono::time_point<Clock, Duration>& tp) const
2256  {
2257  return tp;
2258  }
2259 };
2260 
2261 namespace ctc_detail
2262 {
2263 
2264 template <class Clock, class Duration>
2265  using time_point = std::chrono::time_point<Clock, Duration>;
2266 
2267 using std::declval;
2268 using std::chrono::system_clock;
2269 
2270 //Check if TimePoint is time for given clock,
2271 //if not emits hard error
2272 template <class Clock, class TimePoint>
2274 {
2276  using type = TimePoint;
2277 
2279  "time point with appropariate clock shall be returned");
2280 };
2281 
2282 // Check if Clock has to_sys method accepting TimePoint with given duration const& and
2283 // returning sys_time. If so has nested type member equal to return type to_sys.
2284 template <class Clock, class Duration, class = void>
2286 {};
2287 
2288 template <class Clock, class Duration>
2290  <
2291  Clock, Duration,
2292  decltype(Clock::to_sys(declval<time_point<Clock, Duration> const&>()), void())
2293  >
2295  <
2296  system_clock,
2297  decltype(Clock::to_sys(declval<time_point<Clock, Duration> const&>()))
2298  >
2299 {};
2300 
2301 // Similiar to above
2302 template <class Clock, class Duration, class = void>
2304 {};
2305 
2306 template <class Clock, class Duration>
2308  <
2309  Clock, Duration,
2310  decltype(Clock::from_sys(declval<time_point<system_clock, Duration> const&>()),
2311  void())
2312  >
2314  <
2315  Clock,
2316  decltype(Clock::from_sys(declval<time_point<system_clock, Duration> const&>()))
2317  >
2318 {};
2319 
2320 // Similiar to above
2321 template <class Clock, class Duration, class = void>
2323 {};
2324 
2325 template <class Clock, class Duration>
2327  <
2328  Clock, Duration,
2329  decltype(Clock::to_utc(declval<time_point<Clock, Duration> const&>()), void())
2330  >
2332  <
2333  utc_clock,
2334  decltype(Clock::to_utc(declval<time_point<Clock, Duration> const&>()))>
2335 {};
2336 
2337 // Similiar to above
2338 template <class Clock, class Duration, class = void>
2340 {};
2341 
2342 template <class Clock, class Duration>
2344  <
2345  Clock, Duration,
2346  decltype(Clock::from_utc(declval<time_point<utc_clock, Duration> const&>()),
2347  void())
2348  >
2350  <
2351  Clock,
2352  decltype(Clock::from_utc(declval<time_point<utc_clock, Duration> const&>()))
2353  >
2354 {};
2355 
2356 } // namespace ctc_detail
2357 
2358 template <class SrcClock>
2359 struct clock_time_conversion<std::chrono::system_clock, SrcClock>
2360 {
2361  template <class Duration>
2363  operator()(const std::chrono::time_point<SrcClock, Duration>& tp) const
2364  {
2365  return SrcClock::to_sys(tp);
2366  }
2367 };
2368 
2369 template <class DstClock>
2370 struct clock_time_conversion<DstClock, std::chrono::system_clock>
2371 {
2372  template <class Duration>
2375  {
2376  return DstClock::from_sys(st);
2377  }
2378 };
2379 
2380 template <class SrcClock>
2382 {
2383  template <class Duration>
2385  operator()(const std::chrono::time_point<SrcClock, Duration>& tp) const
2386  {
2387  return SrcClock::to_utc(tp);
2388  }
2389 };
2390 
2391 template <class DstClock>
2393 {
2394  template <class Duration>
2397  {
2398  return DstClock::from_utc(ut);
2399  }
2400 };
2401 
2402 namespace clock_cast_detail
2403 {
2404 
2405 template <class Clock, class Duration>
2406  using time_point = std::chrono::time_point<Clock, Duration>;
2407 using std::chrono::system_clock;
2408 
2409 template <class DstClock, class SrcClock, class Duration>
2410 auto
2412  -> decltype(std::declval<clock_time_conversion<DstClock, SrcClock>>()(t))
2413 {
2415 }
2416 
2417 //direct trait conversion, 1st candidate
2418 template <class DstClock, class SrcClock, class Duration>
2419 auto
2421  -> decltype(conv_clock<DstClock>(t))
2422 {
2423  return conv_clock<DstClock>(t);
2424 }
2425 
2426 //conversion through sys, 2nd candidate
2427 template <class DstClock, class SrcClock, class Duration>
2428 auto
2430  -> decltype(conv_clock<DstClock>(conv_clock<system_clock>(t)))
2431 {
2432  return conv_clock<DstClock>(conv_clock<system_clock>(t));
2433 }
2434 
2435 //conversion through utc, 2nd candidate
2436 template <class DstClock, class SrcClock, class Duration>
2437 auto
2438 cc_impl(const time_point<SrcClock, Duration>& t, const void*)
2439  -> decltype(0, // MSVC_WORKAROUND
2440  conv_clock<DstClock>(conv_clock<utc_clock>(t)))
2441 {
2442  return conv_clock<DstClock>(conv_clock<utc_clock>(t));
2443 }
2444 
2445 //conversion through sys and utc, 3rd candidate
2446 template <class DstClock, class SrcClock, class Duration>
2447 auto
2449  -> decltype(conv_clock<DstClock>(conv_clock<utc_clock>(conv_clock<system_clock>(t))))
2450 {
2451  return conv_clock<DstClock>(conv_clock<utc_clock>(conv_clock<system_clock>(t)));
2452 }
2453 
2454 //conversion through utc and sys, 3rd candidate
2455 template <class DstClock, class SrcClock, class Duration>
2456 auto
2458  -> decltype(0, // MSVC_WORKAROUND
2459  conv_clock<DstClock>(conv_clock<system_clock>(conv_clock<utc_clock>(t))))
2460 {
2461  return conv_clock<DstClock>(conv_clock<system_clock>(conv_clock<utc_clock>(t)));
2462 }
2463 
2464 } // namespace clock_cast_detail
2465 
2466 template <class DstClock, class SrcClock, class Duration>
2467 auto
2468 clock_cast(const std::chrono::time_point<SrcClock, Duration>& tp)
2469  -> decltype(clock_cast_detail::cc_impl<DstClock>(tp, &tp))
2470 {
2471  return clock_cast_detail::cc_impl<DstClock>(tp, &tp);
2472 }
2473 
2474 // Deprecated API
2475 
2476 template <class Duration>
2477 inline
2480 {
2481  return utc_clock::to_sys(t);
2482 }
2483 
2484 template <class Duration>
2485 inline
2488 {
2490 }
2491 
2492 template <class Duration>
2493 inline
2496 {
2498 }
2499 
2500 
2501 template <class Duration>
2502 inline
2505 {
2506  return utc_clock::from_sys(t);
2507 }
2508 
2509 template <class Duration>
2510 inline
2513 {
2514  return tai_clock::to_utc(t);
2515 }
2516 
2517 template <class Duration>
2518 inline
2521 {
2522  return gps_clock::to_utc(t);
2523 }
2524 
2525 
2526 template <class Duration>
2527 inline
2530 {
2532 }
2533 
2534 template <class Duration>
2535 inline
2538 {
2539  return tai_clock::from_utc(t);
2540 }
2541 
2542 template <class Duration>
2543 inline
2546 {
2548 }
2549 
2550 
2551 template <class Duration>
2552 inline
2555 {
2557 }
2558 
2559 template <class Duration>
2560 inline
2563 {
2564  return gps_clock::from_utc(t);
2565 }
2566 
2567 template <class Duration>
2568 inline
2571 {
2573 }
2574 
2575 #endif // !MISSING_LEAP_SECONDS
2576 
2577 } // namespace date
2578 
2579 #endif // TZ_H
Definition: date.h:638
Definition: tz.h:2203
Definition: tz.h:779
Definition: tz.h:996
ctc_detail::return_to_utc< SrcClock, Duration >::type operator()(const std::chrono::time_point< SrcClock, Duration > &tp) const
Definition: tz.h:2385
CONSTDATA date::weekday sun
Definition: date.h:1849
CONSTCD11 bool operator==(const day &x, const day &y) NOEXCEPT
Definition: date.h:1274
ambiguous_local_time(local_time< Duration > tp, const local_info &i)
Definition: tz.h:255
time_zone & operator=(time_zone &&)=default
Definition: tz.h:1157
Definition: tz.h:239
std::chrono::time_point< gps_clock, Duration > gps_time
Definition: tz.h:2115
#define DATE_API
Definition: tz.h:142
static const time_zone * locate_zone(const std::string &name)
Definition: tz.h:312
#define NOEXCEPT
Definition: date.h:124
gps_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_gps_time(const sys_time< Duration > &t)
Definition: tz.h:2554
time_zone(time_zone &&)=default
sys_time< std::chrono::seconds > sys_seconds
Definition: date.h:164
static std::chrono::time_point< utc_clock, typename std::common_type< Duration, std::chrono::seconds >::type > to_utc(const std::chrono::time_point< gps_clock, Duration > &) NOEXCEPT
bool remote_download(const std::string &version)
Definition: tz.cpp:3248
zoned_time< std::chrono::seconds > zoned_seconds
Definition: tz.h:677
friend bool operator!=(const const_iterator &x, const const_iterator &y) noexcept
Definition: tz.h:1270
std::ptrdiff_t difference_type
Definition: tz.h:1255
static const time_zone * default_zone()
Definition: tz.h:294
duration::rep rep
Definition: tz.h:1834
duration::period period
Definition: tz.h:1986
local_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_local(sys_time< Duration > tp) const
Definition: tz.h:920
ctc_detail::return_to_sys< SrcClock, Duration >::type operator()(const std::chrono::time_point< SrcClock, Duration > &tp) const
Definition: tz.h:2363
reference operator*() const noexcept
Definition: tz.h:1257
Definition: tz.h:2091
std::chrono::time_point< gps_clock > time_point
Definition: tz.h:2097
std::basic_istream< CharT, Traits > & from_stream(std::basic_istream< CharT, Traits > &is, const CharT *fmt, fields< Duration > &fds, std::basic_string< CharT, Traits, Alloc > *abbrev=nullptr, std::chrono::minutes *offset=nullptr)
Definition: date.h:5951
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4005
Definition: tz.h:2322
std::chrono::time_point< Clock, Duration > time_point
Definition: tz.h:2265
auto clock_cast(const std::chrono::time_point< SrcClock, Duration > &tp) -> decltype(clock_cast_detail::cc_impl< DstClock >(tp, &tp))
Definition: tz.h:2468
Definition: tz.h:156
T * to_raw_pointer(T *p) noexcept
Definition: tz.h:1329
const_iterator operator++(int) noexcept
Definition: tz.h:1261
std::vector< detail::Rule > rules
Definition: tz.h:1168
sys_seconds begin
Definition: tz.h:158
sys_info get_info(sys_time< Duration > st) const
Definition: tz.h:886
ctc_detail::return_from_sys< DstClock, Duration >::type operator()(const sys_time< Duration > &st) const
Definition: tz.h:2374
sys_time< days > sys_days
Definition: date.h:163
std::chrono::minutes save
Definition: tz.h:161
sys_seconds end
Definition: tz.h:159
sys_seconds date() const
Definition: tz.h:1008
Definition: date.h:79
CONSTCD11 bool operator>(const day &x, const day &y) NOEXCEPT
Definition: date.h:1298
friend bool operator==(const const_iterator &x, const const_iterator &y) noexcept
Definition: tz.h:1265
Definition: date.h:365
sys_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_sys(local_time< Duration > tp) const
Definition: tz.h:904
utc_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_utc_time(const sys_time< Duration > &t)
Definition: tz.h:2504
Definition: tz.h:1981
std::pair< bool, std::chrono::seconds > is_leap_second(date::utc_time< Duration > const &ut)
Definition: tz.h:1873
const std::string & name() const NOEXCEPT
Definition: tz.h:878
tzdb & front() noexcept
Definition: tz.h:1226
local_time< duration > get_local_time() const
Definition: tz.h:1632
const tzdb & get_tzdb()
Definition: tz.cpp:3479
std::chrono::time_point< utc_clock > time_point
Definition: tz.h:1836
const_iterator end() const noexcept
Definition: tz.h:1285
sys_info second
Definition: tz.h:181
const_iterator & operator++() noexcept
Definition: tz.h:1260
tai_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_tai_time(const sys_time< Duration > &t)
Definition: tz.h:2529
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const day &d)
Definition: date.h:1355
sys_info first
Definition: tz.h:180
std::vector< leap > leaps
Definition: tz.h:1165
zoned_time< std::chrono::seconds > make_zoned()
Definition: tz.h:1657
Definition: tz.h:201
std::vector< link > links
Definition: tz.h:1162
utc_time< Duration > operator()(const utc_time< Duration > &ut) const
Definition: tz.h:2222
static time_point now()
Definition: tz.h:1912
std::chrono::system_clock::duration duration
Definition: tz.h:1984
std::string abbrev
Definition: tz.h:162
nonexistent_local_time(local_time< Duration > tp, const local_info &i)
Definition: tz.h:217
const time_zone * current_zone()
Definition: tz.cpp:3783
tzdb * next
Definition: tz.h:1173
tz
Definition: tz_private.h:45
Definition: tz.h:328
CONSTDATA date::month jan
Definition: date.h:1836
Definition: tz.h:1243
Definition: tz.h:179
CONSTCD11 time_of_day< std::chrono::duration< Rep, Period > > make_time(const std::chrono::duration< Rep, Period > &d)
Definition: date.h:4264
static time_point now()
Definition: tz.h:2143
#define CONSTDATA
Definition: date.h:121
pointer operator->() const noexcept
Definition: tz.h:1258
gps_time< std::chrono::seconds > gps_seconds
Definition: tz.h:2117
Definition: tz.h:2285
static std::chrono::time_point< utc_clock, typename std::common_type< Duration, std::chrono::seconds >::type > to_utc(const std::chrono::time_point< tai_clock, Duration > &) NOEXCEPT
const_iterator begin() const noexcept
Definition: tz.h:1278
static std::chrono::time_point< gps_clock, typename std::common_type< Duration, std::chrono::seconds >::type > from_utc(const std::chrono::time_point< utc_clock, Duration > &) NOEXCEPT
std::basic_ostream< CharT, Traits > & to_stream(std::basic_ostream< CharT, Traits > &os, const CharT *fmt, const fields< Duration > &fds, const std::string *abbrev=nullptr, const std::chrono::seconds *offset_sec=nullptr)
Definition: date.h:4598
enum date::local_info::@3 result
CONSTCD11 bool operator>=(const day &x, const day &y) NOEXCEPT
Definition: date.h:1314
Definition: tz.h:177
const time_zone * locate_zone(const std::string &tz_name)
Definition: tz.cpp:3532
zoned_time()
Definition: tz.h:1350
std::chrono::time_point< Clock, Duration > time_point
Definition: tz.h:2406
decltype(Clock::to_sys(declval< time_point< Clock, Duration > const &>())) type
Definition: tz.h:2276
std::chrono::time_point< std::chrono::system_clock, Duration > sys_time
Definition: date.h:161
ctc_detail::return_from_utc< DstClock, Duration >::type operator()(const utc_time< Duration > &ut) const
Definition: tz.h:2396
CONSTCD11 bool operator!=(const day &x, const day &y) NOEXCEPT
Definition: date.h:1282
std::chrono::time_point< tai_clock, Duration > tai_time
Definition: tz.h:2004
TimeZonePtr get_time_zone() const
Definition: tz.h:1624
friend bool operator==(const leap &x, const leap &y)
Definition: tz.h:1010
duration::rep rep
Definition: tz.h:1985
int add(int code, T value)
Definition: HashCoder.h:34
tzdb_list & get_tzdb_list()
Definition: tz.cpp:444
typename std::common_type< Duration, std::chrono::seconds >::type duration
Definition: tz.h:339
duration::period period
Definition: tz.h:1835
std::string remote_version()
Definition: tz.cpp:2852
bool remote_install(const std::string &version)
Definition: tz.cpp:3280
auto conv_clock(const time_point< SrcClock, Duration > &t) -> decltype(std::declval< clock_time_conversion< DstClock, SrcClock >>()(t))
Definition: tz.h:2411
Definition: tz_private.h:220
static time_point now()
Definition: tz.h:2032
local_time< std::chrono::seconds > local_seconds
Definition: date.h:171
static std::chrono::time_point< tai_clock, typename std::common_type< Duration, std::chrono::seconds >::type > from_utc(const std::chrono::time_point< utc_clock, Duration > &) NOEXCEPT
Definition: tz.h:179
auto cc_impl(const time_point< SrcClock, Duration > &t,...) -> decltype(conv_clock< DstClock >(conv_clock< utc_clock >(conv_clock< system_clock >(t))))
Definition: tz.h:2448
sys_time< duration > get_sys_time() const
Definition: tz.h:1640
Definition: tz.h:179
sys_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_sys_time(const utc_time< Duration > &t)
Definition: tz.h:2479
sys_time< Duration > operator()(const sys_time< Duration > &st) const
Definition: tz.h:2211
tai_time< std::chrono::seconds > tai_seconds
Definition: tz.h:2006
static std::chrono::time_point< utc_clock, typename std::common_type< Duration, std::chrono::seconds >::type > from_sys(const std::chrono::time_point< std::chrono::system_clock, Duration > &)
auto to_raw_pointer(Pointer p) noexcept -> decltype(detail::to_raw_pointer(p.operator->()))
Definition: tz.h:1337
Definition: tz.cpp:384
friend bool operator==(const leap &x, const sys_time< Duration > &y)
Definition: tz.h:1016
zoned_time & operator=(const sys_time< Duration > &st)
Definition: tz.h:1592
static std::chrono::time_point< std::chrono::system_clock, typename std::common_type< Duration, std::chrono::seconds >::type > to_sys(const std::chrono::time_point< utc_clock, Duration > &)
duration::rep rep
Definition: tz.h:2095
choose
Definition: tz.h:149
std::chrono::system_clock::duration duration
Definition: tz.h:1833
time_point< system_clock, typename decltype(Clock::to_sys(declval< time_point< Clock, Duration > const &>())) ::duration > clock_time_point
Definition: tz.h:2275
utc_time< std::chrono::seconds > utc_seconds
Definition: tz.h:1855
const_iterator cend() const noexcept
Definition: tz.h:1299
const_iterator cbegin() const noexcept
Definition: tz.h:1292
const tzdb & reload_tzdb()
Definition: tz.cpp:3465
std::chrono::system_clock::duration duration
Definition: tz.h:2094
std::chrono::time_point< Clock, Duration > operator()(const std::chrono::time_point< Clock, Duration > &tp) const
Definition: tz.h:2255
#define USE_OS_TZDB
Definition: tz.h:47
Definition: date.h:3549
#define AUTO_DOWNLOAD
Definition: tz.h:75
std::chrono::time_point< tai_clock > time_point
Definition: tz.h:1987
Definition: tz.h:285
Definition: tz.h:1830
CONSTCD11 bool operator<(const day &x, const day &y) NOEXCEPT
Definition: date.h:1290
duration::period period
Definition: tz.h:2096
const tzdb & front() const noexcept
Definition: tz.h:1225
Definition: tz_private.h:148
std::chrono::time_point< local_t, Duration > local_time
Definition: date.h:169
std::vector< time_zone > zones
Definition: tz.h:1160
std::forward_iterator_tag iterator_category
Definition: tz.h:1251
#define HAS_REMOTE_API
Definition: tz.h:55
sys_time< typename std::common_type< Duration, std::chrono::seconds >::type > operator()(const utc_time< Duration > &ut) const
Definition: tz.h:2244
sys_info get_info() const
Definition: tz.h:1648
std::chrono::time_point< utc_clock, Duration > utc_time
Definition: tz.h:1853
Definition: tz.h:1216
void set_install(const std::string &s)
Definition: tz.cpp:287
std::chrono::seconds offset
Definition: tz.h:160
static const time_zone * locate_zone(const char *name)
Definition: tz.h:319
utc_time< typename std::common_type< Duration, std::chrono::seconds >::type > operator()(const sys_time< Duration > &st) const
Definition: tz.h:2233
CONSTCD11 bool operator<=(const day &x, const day &y) NOEXCEPT
Definition: date.h:1306