ferencd@0: #ifndef TZ_PRIVATE_H ferencd@0: #define TZ_PRIVATE_H ferencd@0: ferencd@0: // The MIT License (MIT) ferencd@0: // ferencd@0: // Copyright (c) 2015, 2016 Howard Hinnant ferencd@0: // ferencd@0: // Permission is hereby granted, free of charge, to any person obtaining a copy ferencd@0: // of this software and associated documentation files (the "Software"), to deal ferencd@0: // in the Software without restriction, including without limitation the rights ferencd@0: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ferencd@0: // copies of the Software, and to permit persons to whom the Software is ferencd@0: // furnished to do so, subject to the following conditions: ferencd@0: // ferencd@0: // The above copyright notice and this permission notice shall be included in all ferencd@0: // copies or substantial portions of the Software. ferencd@0: // ferencd@0: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ferencd@0: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ferencd@0: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ferencd@0: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ferencd@0: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ferencd@0: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ferencd@0: // SOFTWARE. ferencd@0: // ferencd@0: // Our apologies. When the previous paragraph was written, lowercase had not yet ferencd@0: // been invented (that would involve another several millennia of evolution). ferencd@0: // We did not mean to shout. ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: #include "tz.h" ferencd@0: #else ferencd@0: #include "date.h" ferencd@0: #include ferencd@0: #endif ferencd@0: ferencd@0: namespace date ferencd@0: { ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: #if !USE_OS_TZDB ferencd@0: ferencd@0: enum class tz {utc, local, standard}; ferencd@0: ferencd@0: //forward declare to avoid warnings in gcc 6.2 ferencd@0: class MonthDayTime; ferencd@0: std::istream& operator>>(std::istream& is, MonthDayTime& x); ferencd@0: std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); ferencd@0: ferencd@0: ferencd@0: class MonthDayTime ferencd@0: { ferencd@0: private: ferencd@0: struct pair ferencd@0: { ferencd@0: #if defined(_MSC_VER) && (_MSC_VER < 1900) ferencd@0: pair() : month_day_(date::jan / 1), weekday_(0U) {} ferencd@0: ferencd@0: pair(const date::month_day& month_day, const date::weekday& weekday) ferencd@0: : month_day_(month_day), weekday_(weekday) {} ferencd@0: #endif ferencd@0: ferencd@0: date::month_day month_day_; ferencd@0: date::weekday weekday_; ferencd@0: }; ferencd@0: ferencd@0: enum Type {month_day, month_last_dow, lteq, gteq}; ferencd@0: ferencd@0: Type type_{month_day}; ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: union U ferencd@0: #else ferencd@0: struct U ferencd@0: #endif ferencd@0: { ferencd@0: date::month_day month_day_; ferencd@0: date::month_weekday_last month_weekday_last_; ferencd@0: pair month_day_weekday_; ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: U() : month_day_{date::jan/1} {} ferencd@0: #else ferencd@0: U() : ferencd@0: month_day_(date::jan/1), ferencd@0: month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U))) ferencd@0: {} ferencd@0: ferencd@0: #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: ferencd@0: U& operator=(const date::month_day& x); ferencd@0: U& operator=(const date::month_weekday_last& x); ferencd@0: U& operator=(const pair& x); ferencd@0: } u; ferencd@0: ferencd@0: std::chrono::hours h_{}; ferencd@0: std::chrono::minutes m_{}; ferencd@0: std::chrono::seconds s_{}; ferencd@0: tz zone_{tz::local}; ferencd@0: ferencd@0: public: ferencd@0: MonthDayTime() = default; ferencd@0: MonthDayTime(local_seconds tp, tz timezone); ferencd@0: MonthDayTime(const date::month_day& md, tz timezone); ferencd@0: ferencd@0: date::day day() const; ferencd@0: date::month month() const; ferencd@0: tz zone() const {return zone_;} ferencd@0: ferencd@0: void canonicalize(date::year y); ferencd@0: ferencd@0: sys_seconds ferencd@0: to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const; ferencd@0: sys_days to_sys_days(date::year y) const; ferencd@0: ferencd@0: sys_seconds to_time_point(date::year y) const; ferencd@0: int compare(date::year y, const MonthDayTime& x, date::year yx, ferencd@0: std::chrono::seconds offset, std::chrono::minutes prev_save) const; ferencd@0: ferencd@0: friend std::istream& operator>>(std::istream& is, MonthDayTime& x); ferencd@0: friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); ferencd@0: }; ferencd@0: ferencd@0: // A Rule specifies one or more set of datetimes without using an offset. ferencd@0: // Multiple dates are specified with multiple years. The years in effect ferencd@0: // go from starting_year_ to ending_year_, inclusive. starting_year_ <= ferencd@0: // ending_year_. save_ is in effect for times from the specified time ferencd@0: // onward, including the specified time. When the specified time is ferencd@0: // local, it uses the save_ from the chronologically previous Rule, or if ferencd@0: // there is none, 0. ferencd@0: ferencd@0: //forward declare to avoid warnings in gcc 6.2 ferencd@0: class Rule; ferencd@0: bool operator==(const Rule& x, const Rule& y); ferencd@0: bool operator<(const Rule& x, const Rule& y); ferencd@0: bool operator==(const Rule& x, const date::year& y); ferencd@0: bool operator<(const Rule& x, const date::year& y); ferencd@0: bool operator==(const date::year& x, const Rule& y); ferencd@0: bool operator<(const date::year& x, const Rule& y); ferencd@0: bool operator==(const Rule& x, const std::string& y); ferencd@0: bool operator<(const Rule& x, const std::string& y); ferencd@0: bool operator==(const std::string& x, const Rule& y); ferencd@0: bool operator<(const std::string& x, const Rule& y); ferencd@0: std::ostream& operator<<(std::ostream& os, const Rule& r); ferencd@0: ferencd@0: class Rule ferencd@0: { ferencd@0: private: ferencd@0: std::string name_; ferencd@0: date::year starting_year_{0}; ferencd@0: date::year ending_year_{0}; ferencd@0: MonthDayTime starting_at_; ferencd@0: std::chrono::minutes save_{0}; ferencd@0: std::string abbrev_; ferencd@0: ferencd@0: public: ferencd@0: Rule() = default; ferencd@0: explicit Rule(const std::string& s); ferencd@0: Rule(const Rule& r, date::year starting_year, date::year ending_year); ferencd@0: ferencd@0: const std::string& name() const {return name_;} ferencd@0: const std::string& abbrev() const {return abbrev_;} ferencd@0: ferencd@0: const MonthDayTime& mdt() const {return starting_at_;} ferencd@0: const date::year& starting_year() const {return starting_year_;} ferencd@0: const date::year& ending_year() const {return ending_year_;} ferencd@0: const std::chrono::minutes& save() const {return save_;} ferencd@0: ferencd@0: static void split_overlaps(std::vector& rules); ferencd@0: ferencd@0: friend bool operator==(const Rule& x, const Rule& y); ferencd@0: friend bool operator<(const Rule& x, const Rule& y); ferencd@0: friend bool operator==(const Rule& x, const date::year& y); ferencd@0: friend bool operator<(const Rule& x, const date::year& y); ferencd@0: friend bool operator==(const date::year& x, const Rule& y); ferencd@0: friend bool operator<(const date::year& x, const Rule& y); ferencd@0: friend bool operator==(const Rule& x, const std::string& y); ferencd@0: friend bool operator<(const Rule& x, const std::string& y); ferencd@0: friend bool operator==(const std::string& x, const Rule& y); ferencd@0: friend bool operator<(const std::string& x, const Rule& y); ferencd@0: ferencd@0: friend std::ostream& operator<<(std::ostream& os, const Rule& r); ferencd@0: ferencd@0: private: ferencd@0: date::day day() const; ferencd@0: date::month month() const; ferencd@0: static void split_overlaps(std::vector& rules, std::size_t i, std::size_t& e); ferencd@0: static bool overlaps(const Rule& x, const Rule& y); ferencd@0: static void split(std::vector& rules, std::size_t i, std::size_t k, ferencd@0: std::size_t& e); ferencd@0: }; ferencd@0: ferencd@0: inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);} ferencd@0: inline bool operator> (const Rule& x, const Rule& y) {return y < x;} ferencd@0: inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);} ferencd@0: inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);} ferencd@0: ferencd@0: inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);} ferencd@0: inline bool operator> (const Rule& x, const date::year& y) {return y < x;} ferencd@0: inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);} ferencd@0: inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);} ferencd@0: ferencd@0: inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);} ferencd@0: inline bool operator> (const date::year& x, const Rule& y) {return y < x;} ferencd@0: inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);} ferencd@0: inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);} ferencd@0: ferencd@0: inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);} ferencd@0: inline bool operator> (const Rule& x, const std::string& y) {return y < x;} ferencd@0: inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);} ferencd@0: inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);} ferencd@0: ferencd@0: inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);} ferencd@0: inline bool operator> (const std::string& x, const Rule& y) {return y < x;} ferencd@0: inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);} ferencd@0: inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);} ferencd@0: ferencd@0: struct zonelet ferencd@0: { ferencd@0: enum tag {has_rule, has_save, is_empty}; ferencd@0: ferencd@0: std::chrono::seconds gmtoff_; ferencd@0: tag tag_ = has_rule; ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: union U ferencd@0: #else ferencd@0: struct U ferencd@0: #endif ferencd@0: { ferencd@0: std::string rule_; ferencd@0: std::chrono::minutes save_; ferencd@0: ferencd@0: ~U() {} ferencd@0: U() {} ferencd@0: U(const U&) {} ferencd@0: U& operator=(const U&) = delete; ferencd@0: } u; ferencd@0: ferencd@0: std::string format_; ferencd@0: date::year until_year_{0}; ferencd@0: MonthDayTime until_date_; ferencd@0: sys_seconds until_utc_; ferencd@0: local_seconds until_std_; ferencd@0: local_seconds until_loc_; ferencd@0: std::chrono::minutes initial_save_{}; ferencd@0: std::string initial_abbrev_; ferencd@0: std::pair first_rule_{nullptr, date::year::min()}; ferencd@0: std::pair last_rule_{nullptr, date::year::max()}; ferencd@0: ferencd@0: ~zonelet(); ferencd@0: zonelet(); ferencd@0: zonelet(const zonelet& i); ferencd@0: zonelet& operator=(const zonelet&) = delete; ferencd@0: }; ferencd@0: ferencd@0: #else // USE_OS_TZDB ferencd@0: ferencd@0: struct ttinfo ferencd@0: { ferencd@0: std::int32_t tt_gmtoff; ferencd@0: unsigned char tt_isdst; ferencd@0: unsigned char tt_abbrind; ferencd@0: unsigned char pad[2]; ferencd@0: }; ferencd@0: ferencd@0: static_assert(sizeof(ttinfo) == 8, ""); ferencd@0: ferencd@0: struct expanded_ttinfo ferencd@0: { ferencd@0: std::chrono::seconds offset; ferencd@0: std::string abbrev; ferencd@0: bool is_dst; ferencd@0: }; ferencd@0: ferencd@0: struct transition ferencd@0: { ferencd@0: sys_seconds timepoint; ferencd@0: const expanded_ttinfo* info; ferencd@0: ferencd@0: transition(sys_seconds tp, const expanded_ttinfo* i = nullptr) ferencd@0: : timepoint(tp) ferencd@0: , info(i) ferencd@0: {} ferencd@0: ferencd@0: friend ferencd@0: std::ostream& ferencd@0: operator<<(std::ostream& os, const transition& t) ferencd@0: { ferencd@0: using date::operator<<; ferencd@0: os << t.timepoint << "Z "; ferencd@0: if (t.info->offset >= std::chrono::seconds{0}) ferencd@0: os << '+'; ferencd@0: os << make_time(t.info->offset); ferencd@0: if (t.info->is_dst > 0) ferencd@0: os << " daylight "; ferencd@0: else ferencd@0: os << " standard "; ferencd@0: os << t.info->abbrev; ferencd@0: return os; ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: #endif // USE_OS_TZDB ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: } // namespace date ferencd@0: ferencd@0: #if defined(_MSC_VER) && (_MSC_VER < 1900) ferencd@0: #include "tz.h" ferencd@0: #endif ferencd@0: ferencd@0: #endif // TZ_PRIVATE_H