NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
ptz.h
Go to the documentation of this file.
1#ifndef PTZ_H
2#define PTZ_H
3
4// The MIT License (MIT)
5//
6// Copyright (c) 2017 Howard Hinnant
7//
8// Permission is hereby granted, free of charge, to any person obtaining a copy
9// of this software and associated documentation files (the "Software"), to deal
10// in the Software without restriction, including without limitation the rights
11// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12// copies of the Software, and to permit persons to whom the Software is
13// furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in all
16// copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24// SOFTWARE.
25
26// This header allows Posix-style time zones as specified for TZ here:
27// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
28//
29// Posix::time_zone can be constructed with a posix-style string and then used in
30// a zoned_time like so:
31//
32// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
33// system_clock::now()};
34// or:
35//
36// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
37// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
38//
39// If the rule set is missing (everything starting with ','), then the rule is that the
40// alternate offset is never enabled.
41//
42// Note, Posix-style time zones are not recommended for all of the reasons described here:
43// https://stackoverflow.com/tags/timezone/info
44//
45// They are provided here as a non-trivial custom time zone example, and if you really
46// have to have Posix time zones, you're welcome to use this one.
47
48#include "date/tz.h"
49#include <cctype>
50#include <ostream>
51#include <string>
52
53namespace Posix
54{
55
56namespace detail
57{
58
59#if HAS_STRING_VIEW
60
61using string_t = std::string_view;
62
63#else // !HAS_STRING_VIEW
64
65using string_t = std::string;
66
67#endif // !HAS_STRING_VIEW
68
69class rule;
70
71void throw_invalid(const string_t& s, unsigned i, const string_t& message);
72unsigned read_date(const string_t& s, unsigned i, rule& r);
73unsigned read_name(const string_t& s, unsigned i, std::string& name);
74unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
75unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
76unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
77 const string_t& message = string_t{});
78
79class rule
80{
81 enum {off, J, M, N};
82
85 unsigned short n_ : 14;
86 unsigned short mode_ : 2;
87 std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
88
89public:
90 rule() : mode_(off) {}
91
92 bool ok() const {return mode_ != off;}
94 std::string to_string() const;
95
96 friend std::ostream& operator<<(std::ostream& os, const rule& r);
97 friend unsigned read_date(const string_t& s, unsigned i, rule& r);
98 friend bool operator==(const rule& x, const rule& y);
99};
100
101inline
102bool
103operator==(const rule& x, const rule& y)
104{
105 if (x.mode_ != y.mode_)
106 return false;
107 switch (x.mode_)
108 {
109 case rule::J:
110 case rule::N:
111 return x.n_ == y.n_;
112 case rule::M:
113 return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_;
114 default:
115 return true;
116 }
117}
118
119inline
120bool
121operator!=(const rule& x, const rule& y)
122{
123 return !(x == y);
124}
125
126inline
129{
130 using date::local_days;
131 using date::January;
132 using date::days;
133 using date::last;
134 using sec = std::chrono::seconds;
136 switch (mode_)
137 {
138 case J:
139 t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
140 break;
141 case M:
142 t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
143 break;
144 case N:
145 t = local_days{y/January/1} + days{n_} + sec{time_};
146 break;
147 default:
148 assert(!"rule called with bad mode");
149 }
150 return t;
151}
152
153inline
154std::string
156{
157 using namespace std::chrono;
158 auto print_offset = [](seconds off)
159 {
160 std::string nm;
161 if (off != hours{2})
162 {
164 nm = '/';
165 nm += std::to_string(offset.hours().count());
166 if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
167 {
168 nm += ':';
169 if (offset.minutes() < minutes{10})
170 nm += '0';
171 nm += std::to_string(offset.minutes().count());
172 if (offset.seconds() != seconds{0})
173 {
174 nm += ':';
175 if (offset.seconds() < seconds{10})
176 nm += '0';
177 nm += std::to_string(offset.seconds().count());
178 }
179 }
180 }
181 return nm;
182 };
183
184 std::string nm;
185 switch (mode_)
186 {
187 case rule::J:
188 nm = 'J';
189 nm += std::to_string(n_);
190 break;
191 case rule::M:
192 nm = 'M';
193 nm += std::to_string(static_cast<unsigned>(m_));
194 nm += '.';
195 nm += std::to_string(n_);
196 nm += '.';
197 nm += std::to_string(wd_.c_encoding());
198 break;
199 case rule::N:
200 nm = std::to_string(n_);
201 break;
202 default:
203 break;
204 }
205 nm += print_offset(time_);
206 return nm;
207}
208
209inline
210std::ostream&
211operator<<(std::ostream& os, const rule& r)
212{
213 switch (r.mode_)
214 {
215 case rule::J:
216 os << 'J' << r.n_ << date::format(" %T", r.time_);
217 break;
218 case rule::M:
219 if (r.n_ == 5)
220 os << r.m_/r.wd_[date::last];
221 else
222 os << r.m_/r.wd_[r.n_];
223 os << date::format(" %T", r.time_);
224 break;
225 case rule::N:
226 os << r.n_ << date::format(" %T", r.time_);
227 break;
228 default:
229 break;
230 }
231 return os;
232}
233
234} // namespace detail
235
237{
238 std::string std_abbrev_;
239 std::string dst_abbrev_ = {};
240 std::chrono::seconds offset_;
241 std::chrono::seconds save_ = std::chrono::hours{1};
244
245public:
246 explicit time_zone(const detail::string_t& name);
247
248 template <class Duration>
250 template <class Duration>
252
253 template <class Duration>
256
257 template <class Duration>
260
261 template <class Duration>
264
265 friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
266
267 const time_zone* operator->() const {return this;}
268
269 std::string name() const;
270
271 friend bool operator==(const time_zone& x, const time_zone& y);
272
273private:
281};
282
283inline
286{
287 return date::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
288}
289
290inline
293{
294 return date::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()};
295}
296
297inline
300{
301 return date::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()};
302}
303
304inline
307{
308 return date::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
309}
310
311inline
314{
315 return date::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()};
316}
317
318inline
321{
322 return date::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()};
323}
324
327{
328 using date::year;
329 using date::sys_info;
330 using date::sys_days;
331 using date::January;
332 using date::December;
333 using date::last;
334 sys_info r;
335 r.begin = sys_days{year::min()/January/1};
336 r.end = sys_days{year::max()/December/last};
337 r.abbrev = std_abbrev_;
338 r.offset = offset_;
339 return r;
340}
341
342inline
344{
345 using detail::read_name;
348 auto i = read_name(s, 0, std_abbrev_);
349 i = read_signed_time(s, i, offset_);
350 offset_ = -offset_;
351 if (i != s.size())
352 {
353 i = read_name(s, i, dst_abbrev_);
354 if (i != s.size())
355 {
356 if (s[i] != ',')
357 {
358 i = read_signed_time(s, i, save_);
359 save_ = -save_ - offset_;
360 }
361 if (i != s.size())
362 {
363 if (s[i] != ',')
364 throw_invalid(s, i, "Expecting end of string or ',' to start rule");
365 ++i;
366 i = read_date(s, i, start_rule_);
367 if (i == s.size() || s[i] != ',')
368 throw_invalid(s, i, "Expecting ',' and then the ending rule");
369 ++i;
370 i = read_date(s, i, end_rule_);
371 if (i != s.size())
372 throw_invalid(s, i, "Found unexpected trailing characters");
373 }
374 }
375 }
376}
377
378template <class Duration>
381{
382 using date::sys_info;
384 using date::sys_days;
385 using date::floor;
386 using date::ceil;
387 using date::days;
388 using date::year;
389 using date::January;
390 using date::December;
391 using date::last;
392 using std::chrono::minutes;
393 sys_info r{};
394 r.offset = offset_;
395 if (start_rule_.ok())
396 {
397 auto y = year_month_day{floor<days>(st)}.year();
398 auto start = get_start(y);
399 auto end = get_end(y);
400 if (start <= end) // (northern hemisphere)
401 {
402 if (start <= st && st < end)
403 {
404 r.begin = start;
405 r.end = end;
406 r.offset += save_;
407 r.save = ceil<minutes>(save_);
408 r.abbrev = dst_abbrev_;
409 }
410 else if (st < start)
411 {
412 r.begin = get_prev_end(y);
413 r.end = start;
414 r.abbrev = std_abbrev_;
415 }
416 else // st >= end
417 {
418 r.begin = end;
419 r.end = get_next_start(y);
420 r.abbrev = std_abbrev_;
421 }
422 }
423 else // end < start (southern hemisphere)
424 {
425 if (end <= st && st < start)
426 {
427 r.begin = end;
428 r.end = start;
429 r.abbrev = std_abbrev_;
430 }
431 else if (st < end)
432 {
433 r.begin = get_prev_start(y);
434 r.end = end;
435 r.offset += save_;
436 r.save = ceil<minutes>(save_);
437 r.abbrev = dst_abbrev_;
438 }
439 else // st >= start
440 {
441 r.begin = start;
442 r.end = get_next_end(y);
443 r.offset += save_;
444 r.save = ceil<minutes>(save_);
445 r.abbrev = dst_abbrev_;
446 }
447 }
448 }
449 else
450 r = contant_offset();
451 return r;
452}
453
454template <class Duration>
457{
458 using date::local_info;
460 using date::days;
461 using date::sys_days;
462 using date::sys_seconds;
463 using date::year;
464 using date::ceil;
465 using date::January;
466 using date::December;
467 using date::last;
468 using std::chrono::seconds;
469 using std::chrono::minutes;
470 local_info r{};
471 using date::floor;
472 if (start_rule_.ok())
473 {
474 auto y = year_month_day{floor<days>(tp)}.year();
475 auto start = get_start(y);
476 auto end = get_end(y);
477 auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
478 auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
479 auto northern = start <= end;
480 if ((utcs < start) != (utcd < start))
481 {
482 if (northern)
483 r.first.begin = get_prev_end(y);
484 else
485 r.first.begin = end;
486 r.first.end = start;
487 r.first.offset = offset_;
488 r.first.abbrev = std_abbrev_;
489 r.second.begin = start;
490 if (northern)
491 r.second.end = end;
492 else
493 r.second.end = get_next_end(y);
494 r.second.abbrev = dst_abbrev_;
495 r.second.offset = offset_ + save_;
496 r.second.save = ceil<minutes>(save_);
497 r.result = save_ > seconds{0} ? local_info::nonexistent
498 : local_info::ambiguous;
499 }
500 else if ((utcs < end) != (utcd < end))
501 {
502 if (northern)
503 r.first.begin = start;
504 else
505 r.first.begin = get_prev_start(y);
506 r.first.end = end;
507 r.first.offset = offset_ + save_;
508 r.first.save = ceil<minutes>(save_);
509 r.first.abbrev = dst_abbrev_;
510 r.second.begin = end;
511 if (northern)
512 r.second.end = get_next_start(y);
513 else
514 r.second.end = start;
515 r.second.abbrev = std_abbrev_;
516 r.second.offset = offset_;
517 r.result = save_ > seconds{0} ? local_info::ambiguous
518 : local_info::nonexistent;
519 }
520 else
521 r.first = get_info(utcs);
522 }
523 else
524 r.first = contant_offset();
525 return r;
526}
527
528template <class Duration>
531{
532 using date::local_info;
533 using date::sys_time;
536 auto i = get_info(tp);
537 if (i.result == local_info::nonexistent)
538 throw nonexistent_local_time(tp, i);
539 else if (i.result == local_info::ambiguous)
540 throw ambiguous_local_time(tp, i);
541 return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
542}
543
544template <class Duration>
547{
548 using date::local_info;
549 using date::sys_time;
550 using date::choose;
551 auto i = get_info(tp);
552 if (i.result == local_info::nonexistent)
553 {
554 return i.first.end;
555 }
556 else if (i.result == local_info::ambiguous)
557 {
558 if (z == choose::latest)
559 return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
560 }
561 return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
562}
563
564template <class Duration>
567{
568 using date::local_time;
569 using std::chrono::seconds;
570 using LT = local_time<typename std::common_type<Duration, seconds>::type>;
571 auto i = get_info(tp);
572 return LT{(tp + i.offset).time_since_epoch()};
573}
574
575inline
576std::ostream&
577operator<<(std::ostream& os, const time_zone& z)
578{
579 using date::operator<<;
580 os << '{';
581 os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
582 << date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
583 return os;
584}
585
586inline
587std::string
589{
590 using namespace date;
591 using namespace std::chrono;
592 auto nm = std_abbrev_;
593 auto print_offset = [](seconds off)
594 {
595 std::string nm;
596 hh_mm_ss<seconds> offset{-off};
597 if (offset.is_negative())
598 nm += '-';
599 nm += std::to_string(offset.hours().count());
600 if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
601 {
602 nm += ':';
603 if (offset.minutes() < minutes{10})
604 nm += '0';
605 nm += std::to_string(offset.minutes().count());
606 if (offset.seconds() != seconds{0})
607 {
608 nm += ':';
609 if (offset.seconds() < seconds{10})
610 nm += '0';
611 nm += std::to_string(offset.seconds().count());
612 }
613 }
614 return nm;
615 };
616 nm += print_offset(offset_);
617 if (!dst_abbrev_.empty())
618 {
619 nm += dst_abbrev_;
620 if (save_ != hours{1})
621 nm += print_offset(offset_+save_);
622 if (start_rule_.ok())
623 {
624 nm += ',';
625 nm += start_rule_.to_string();
626 nm += ',';
627 nm += end_rule_.to_string();
628 }
629 }
630 return nm;
631}
632
633inline
634bool
635operator==(const time_zone& x, const time_zone& y)
636{
637 return x.std_abbrev_ == y.std_abbrev_ &&
638 x.dst_abbrev_ == y. dst_abbrev_ &&
639 x.offset_ == y.offset_ &&
640 x.save_ == y.save_ &&
641 x.start_rule_ == y.start_rule_ &&
642 x.end_rule_ == y.end_rule_;
643}
644
645inline
646bool
647operator!=(const time_zone& x, const time_zone& y)
648{
649 return !(x == y);
650}
651
652namespace detail
653{
654
655inline
656void
657throw_invalid(const string_t& s, unsigned i, const string_t& message)
658{
659 throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
660 std::string(message) + ":\n" +
661 std::string(s) + '\n' +
662 "\x1b[1;32m" +
663 std::string(i, '~') + '^' +
664 std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
665 "\x1b[0m");
666}
667
668inline
669unsigned
670read_date(const string_t& s, unsigned i, rule& r)
671{
672 using date::month;
673 using date::weekday;
674 if (i == s.size())
675 throw_invalid(s, i, "Expected rule but found end of string");
676 if (s[i] == 'J')
677 {
678 ++i;
679 unsigned n;
680 i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
681 r.mode_ = rule::J;
682 r.n_ = n;
683 }
684 else if (s[i] == 'M')
685 {
686 ++i;
687 unsigned m;
688 i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
689 if (i == s.size() || s[i] != '.')
690 throw_invalid(s, i, "Expected '.' after month");
691 ++i;
692 unsigned n;
693 i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
694 if (i == s.size() || s[i] != '.')
695 throw_invalid(s, i, "Expected '.' after weekday index");
696 ++i;
697 unsigned wd;
698 i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
699 r.mode_ = rule::M;
700 r.m_ = month{m};
701 r.wd_ = weekday{wd};
702 r.n_ = n;
703 }
704 else if (std::isdigit(s[i]))
705 {
706 unsigned n;
707 i = read_unsigned(s, i, 3, n);
708 r.mode_ = rule::N;
709 r.n_ = n;
710 }
711 else
712 throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
713 if (i != s.size() && s[i] == '/')
714 {
715 ++i;
716 std::chrono::seconds t;
717 i = read_unsigned_time(s, i, t);
718 r.time_ = t;
719 }
720 return i;
721}
722
723inline
724unsigned
725read_name(const string_t& s, unsigned i, std::string& name)
726{
727 if (i == s.size())
728 throw_invalid(s, i, "Expected a name but found end of string");
729 if (s[i] == '<')
730 {
731 ++i;
732 while (true)
733 {
734 if (i == s.size())
735 throw_invalid(s, i,
736 "Expected to find closing '>', but found end of string");
737 if (s[i] == '>')
738 break;
739 name.push_back(s[i]);
740 ++i;
741 }
742 ++i;
743 }
744 else
745 {
746 while (i != s.size() && std::isalpha(s[i]))
747 {
748 name.push_back(s[i]);
749 ++i;
750 }
751 }
752 if (name.size() < 3)
753 throw_invalid(s, i, "Found name to be shorter than 3 characters");
754 return i;
755}
756
757inline
758unsigned
759read_signed_time(const string_t& s, unsigned i,
760 std::chrono::seconds& t)
761{
762 if (i == s.size())
763 throw_invalid(s, i, "Expected to read signed time, but found end of string");
764 bool negative = false;
765 if (s[i] == '-')
766 {
767 negative = true;
768 ++i;
769 }
770 else if (s[i] == '+')
771 ++i;
772 i = read_unsigned_time(s, i, t);
773 if (negative)
774 t = -t;
775 return i;
776}
777
778inline
779unsigned
780read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
781{
782 using std::chrono::seconds;
783 using std::chrono::minutes;
784 using std::chrono::hours;
785 if (i == s.size())
786 throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
787 unsigned x;
788 i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
789 t = hours{x};
790 if (i != s.size() && s[i] == ':')
791 {
792 ++i;
793 i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
794 t += minutes{x};
795 if (i != s.size() && s[i] == ':')
796 {
797 ++i;
798 i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
799 t += seconds{x};
800 }
801 }
802 return i;
803}
804
805inline
806unsigned
807read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
808 const string_t& message)
809{
810 if (i == s.size() || !std::isdigit(s[i]))
811 throw_invalid(s, i, message);
812 u = static_cast<unsigned>(s[i] - '0');
813 unsigned count = 1;
814 for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
815 u = u * 10 + static_cast<unsigned>(s[i] - '0');
816 return i;
817}
818
819} // namespace detail
820
821} // namespace Posix
822
823namespace date
824{
825
826template <>
828{
829
830#if HAS_STRING_VIEW
831
832 static
834 locate_zone(std::string_view name)
835 {
836 return Posix::time_zone{name};
837 }
838
839#else // !HAS_STRING_VIEW
840
841 static
843 locate_zone(const std::string& name)
844 {
845 return Posix::time_zone{name};
846 }
847
848 static
850 locate_zone(const char* name)
851 {
852 return Posix::time_zone{name};
853 }
854
855#endif // !HAS_STRING_VIEW
856
857};
858
859} // namespace date
860
861#endif // PTZ_H
friend std::ostream & operator<<(std::ostream &os, const rule &r)
Definition: ptz.h:211
date::month m_
Definition: ptz.h:83
unsigned short mode_
Definition: ptz.h:86
unsigned short n_
Definition: ptz.h:85
date::weekday wd_
Definition: ptz.h:84
std::chrono::duration< std::int32_t > time_
Definition: ptz.h:87
date::local_seconds operator()(date::year y) const
Definition: ptz.h:128
friend bool operator==(const rule &x, const rule &y)
Definition: ptz.h:103
bool ok() const
Definition: ptz.h:92
friend unsigned read_date(const string_t &s, unsigned i, rule &r)
Definition: ptz.h:670
std::string to_string() const
Definition: ptz.h:155
date::sys_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_sys(date::local_time< Duration > tp) const
Definition: ptz.h:530
date::sys_info contant_offset() const
Definition: ptz.h:326
std::string name() const
Definition: ptz.h:588
detail::rule start_rule_
Definition: ptz.h:242
date::sys_seconds get_end(date::year y) const
Definition: ptz.h:306
date::sys_info get_info(date::sys_time< Duration > st) const
Definition: ptz.h:380
std::chrono::seconds save_
Definition: ptz.h:241
std::chrono::seconds offset_
Definition: ptz.h:240
date::sys_seconds get_next_end(date::year y) const
Definition: ptz.h:320
time_zone(const detail::string_t &name)
Definition: ptz.h:343
date::local_time< typename std::common_type< Duration, std::chrono::seconds >::type > to_local(date::sys_time< Duration > tp) const
Definition: ptz.h:566
friend std::ostream & operator<<(std::ostream &os, const time_zone &z)
Definition: ptz.h:577
const time_zone * operator->() const
Definition: ptz.h:267
date::sys_seconds get_start(date::year y) const
Definition: ptz.h:285
date::sys_seconds get_prev_start(date::year y) const
Definition: ptz.h:292
std::string std_abbrev_
Definition: ptz.h:238
detail::rule end_rule_
Definition: ptz.h:243
std::string dst_abbrev_
Definition: ptz.h:239
date::sys_seconds get_prev_end(date::year y) const
Definition: ptz.h:313
date::sys_seconds get_next_start(date::year y) const
Definition: ptz.h:299
friend bool operator==(const time_zone &x, const time_zone &y)
Definition: ptz.h:635
CONSTCD11 unsigned c_encoding() const NOEXCEPT
Definition: date.h:1874
CONSTCD11 bool is_leap() const NOEXCEPT
Definition: date.h:1694
bool operator==(const rule &x, const rule &y)
Definition: ptz.h:103
unsigned read_signed_time(const string_t &s, unsigned i, std::chrono::seconds &t)
Definition: ptz.h:759
unsigned read_unsigned(const string_t &s, unsigned i, unsigned limit, unsigned &u, const string_t &message=string_t{})
Definition: ptz.h:807
void throw_invalid(const string_t &s, unsigned i, const string_t &message)
Definition: ptz.h:657
unsigned read_date(const string_t &s, unsigned i, rule &r)
Definition: ptz.h:670
std::ostream & operator<<(std::ostream &os, const rule &r)
Definition: ptz.h:211
unsigned read_unsigned_time(const string_t &s, unsigned i, std::chrono::seconds &t)
Definition: ptz.h:780
unsigned read_name(const string_t &s, unsigned i, std::string &name)
Definition: ptz.h:725
bool operator!=(const rule &x, const rule &y)
Definition: ptz.h:121
std::string string_t
Definition: ptz.h:65
Definition: ptz.h:54
bool operator!=(const time_zone &x, const time_zone &y)
Definition: ptz.h:647
bool operator==(const time_zone &x, const time_zone &y)
Definition: ptz.h:635
std::ostream & operator<<(std::ostream &os, const time_zone &z)
Definition: ptz.h:577
CONSTDATA date::last_spec last
Definition: date.h:1989
Definition: date.h:88
local_time< std::chrono::seconds > local_seconds
Definition: date.h:201
local_time< days > local_days
Definition: date.h:202
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > & >(), fmt, tp), std::basic_string< CharT >{})
Definition: date.h:6249
CONSTDATA date::month January
Definition: date.h:2016
std::chrono::time_point< std::chrono::system_clock, Duration > sys_time
Definition: date.h:191
CONSTCD14 std::enable_if< detail::no_overflow< Period, typenameTo::period >::value, To >::type floor(const std::chrono::duration< Rep, Period > &d)
Definition: date.h:1251
CONSTDATA date::month December
Definition: date.h:2027
const time_zone * locate_zone(const std::string &tz_name)
Definition: tz.cpp:3633
choose
Definition: tz.h:140
std::chrono::duration< int, detail::ratio_multiply< std::ratio< 24 >, std::chrono::hours::period > > days
Definition: date.h:177
std::chrono::time_point< local_t, Duration > local_time
Definition: date.h:199
sys_time< std::chrono::seconds > sys_seconds
Definition: date.h:194
sys_time< days > sys_days
Definition: date.h:193
CONSTCD14 To ceil(const std::chrono::duration< Rep, Period > &d)
Definition: date.h:1302
char name[32]
Definition: resampler.cpp:371
#define min(a, b)
Definition: resampler.cpp:34
#define max(a, b)
Definition: resampler.cpp:30
static Posix::time_zone locate_zone(const char *name)
Definition: ptz.h:850
static Posix::time_zone locate_zone(const std::string &name)
Definition: ptz.h:843