annotate common/date/tz.h @ 0:a4671277546c tip

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