1 #ifndef TZ_PRIVATE_H 2 #define TZ_PRIVATE_H 3 4 // The MIT License (MIT) 5 // 6 // Copyright (c) 2015, 2016 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 // Our apologies. When the previous paragraph was written, lowercase had not yet 27 // been invented (that would involve another several millennia of evolution). 28 // We did not mean to shout. 29 30 #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 31 #include "tz.h" 32 #else 33 #include "date.h" 34 #include <vector> 35 #endif 36 37 namespace date 38 { 39 40 namespace detail 41 { 42 43 #if !USE_OS_TZDB 44 45 enum class tz {utc, local, standard}; 46 47 //forward declare to avoid warnings in gcc 6.2 48 class MonthDayTime; 49 std::istream& operator>>(std::istream& is, MonthDayTime& x); 50 std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); 51 52 53 class MonthDayTime 54 { 55 private: 56 struct pair 57 { 58 #if defined(_MSC_VER) && (_MSC_VER < 1900) pairpair59 pair() : month_day_(date::jan / 1), weekday_(0U) {} 60 pairpair61 pair(const date::month_day& month_day, const date::weekday& weekday) 62 : month_day_(month_day), weekday_(weekday) {} 63 #endif 64 65 date::month_day month_day_; 66 date::weekday weekday_; 67 }; 68 69 enum Type {month_day, month_last_dow, lteq, gteq}; 70 71 Type type_{month_day}; 72 73 #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 74 union U 75 #else 76 struct U 77 #endif 78 { 79 date::month_day month_day_; 80 date::month_weekday_last month_weekday_last_; 81 pair month_day_weekday_; 82 83 #if !defined(_MSC_VER) || (_MSC_VER >= 1900) U()84 U() : month_day_{date::jan/1} {} 85 #else U()86 U() : 87 month_day_(date::jan/1), 88 month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U))) 89 {} 90 91 #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) 92 93 U& operator=(const date::month_day& x); 94 U& operator=(const date::month_weekday_last& x); 95 U& operator=(const pair& x); 96 } u; 97 98 std::chrono::hours h_{0}; 99 std::chrono::minutes m_{0}; 100 std::chrono::seconds s_{0}; 101 tz zone_{tz::local}; 102 103 public: 104 MonthDayTime() = default; 105 MonthDayTime(local_seconds tp, tz timezone); 106 MonthDayTime(const date::month_day& md, tz timezone); 107 108 date::day day() const; 109 date::month month() const; zone()110 tz zone() const {return zone_;} 111 112 void canonicalize(date::year y); 113 114 sys_seconds 115 to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const; 116 sys_days to_sys_days(date::year y) const; 117 118 sys_seconds to_time_point(date::year y) const; 119 int compare(date::year y, const MonthDayTime& x, date::year yx, 120 std::chrono::seconds offset, std::chrono::minutes prev_save) const; 121 122 friend std::istream& operator>>(std::istream& is, MonthDayTime& x); 123 friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x); 124 }; 125 126 // A Rule specifies one or more set of datetimes without using an offset. 127 // Multiple dates are specified with multiple years. The years in effect 128 // go from starting_year_ to ending_year_, inclusive. starting_year_ <= 129 // ending_year_. save_ is in effect for times from the specified time 130 // onward, including the specified time. When the specified time is 131 // local, it uses the save_ from the chronologically previous Rule, or if 132 // there is none, 0. 133 134 //forward declare to avoid warnings in gcc 6.2 135 class Rule; 136 bool operator==(const Rule& x, const Rule& y); 137 bool operator<(const Rule& x, const Rule& y); 138 bool operator==(const Rule& x, const date::year& y); 139 bool operator<(const Rule& x, const date::year& y); 140 bool operator==(const date::year& x, const Rule& y); 141 bool operator<(const date::year& x, const Rule& y); 142 bool operator==(const Rule& x, const std::string& y); 143 bool operator<(const Rule& x, const std::string& y); 144 bool operator==(const std::string& x, const Rule& y); 145 bool operator<(const std::string& x, const Rule& y); 146 std::ostream& operator<<(std::ostream& os, const Rule& r); 147 148 class Rule 149 { 150 private: 151 std::string name_; 152 date::year starting_year_{0}; 153 date::year ending_year_{0}; 154 MonthDayTime starting_at_; 155 std::chrono::minutes save_{0}; 156 std::string abbrev_; 157 158 public: 159 Rule() = default; 160 explicit Rule(const std::string& s); 161 Rule(const Rule& r, date::year starting_year, date::year ending_year); 162 name()163 const std::string& name() const {return name_;} abbrev()164 const std::string& abbrev() const {return abbrev_;} 165 mdt()166 const MonthDayTime& mdt() const {return starting_at_;} starting_year()167 const date::year& starting_year() const {return starting_year_;} ending_year()168 const date::year& ending_year() const {return ending_year_;} save()169 const std::chrono::minutes& save() const {return save_;} 170 171 static void split_overlaps(std::vector<Rule>& rules); 172 173 friend bool operator==(const Rule& x, const Rule& y); 174 friend bool operator<(const Rule& x, const Rule& y); 175 friend bool operator==(const Rule& x, const date::year& y); 176 friend bool operator<(const Rule& x, const date::year& y); 177 friend bool operator==(const date::year& x, const Rule& y); 178 friend bool operator<(const date::year& x, const Rule& y); 179 friend bool operator==(const Rule& x, const std::string& y); 180 friend bool operator<(const Rule& x, const std::string& y); 181 friend bool operator==(const std::string& x, const Rule& y); 182 friend bool operator<(const std::string& x, const Rule& y); 183 184 friend std::ostream& operator<<(std::ostream& os, const Rule& r); 185 186 private: 187 date::day day() const; 188 date::month month() const; 189 static void split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e); 190 static bool overlaps(const Rule& x, const Rule& y); 191 static void split(std::vector<Rule>& rules, std::size_t i, std::size_t k, 192 std::size_t& e); 193 }; 194 195 inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);} 196 inline bool operator> (const Rule& x, const Rule& y) {return y < x;} 197 inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);} 198 inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);} 199 200 inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);} 201 inline bool operator> (const Rule& x, const date::year& y) {return y < x;} 202 inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);} 203 inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);} 204 205 inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);} 206 inline bool operator> (const date::year& x, const Rule& y) {return y < x;} 207 inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);} 208 inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);} 209 210 inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);} 211 inline bool operator> (const Rule& x, const std::string& y) {return y < x;} 212 inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);} 213 inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);} 214 215 inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);} 216 inline bool operator> (const std::string& x, const Rule& y) {return y < x;} 217 inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);} 218 inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);} 219 220 struct zonelet 221 { 222 enum tag {has_rule, has_save, is_empty}; 223 224 std::chrono::seconds gmtoff_; 225 tag tag_ = has_rule; 226 227 #if !defined(_MSC_VER) || (_MSC_VER >= 1900) 228 union U 229 #else 230 struct U 231 #endif 232 { 233 std::string rule_; 234 std::chrono::minutes save_; 235 ~U()236 ~U() {} U()237 U() {} U(const U &)238 U(const U&) {} 239 U& operator=(const U&) = delete; 240 } u; 241 242 std::string format_; 243 date::year until_year_{0}; 244 MonthDayTime until_date_; 245 sys_seconds until_utc_; 246 local_seconds until_std_; 247 local_seconds until_loc_; 248 std::chrono::minutes initial_save_{0}; 249 std::string initial_abbrev_; 250 std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()}; 251 std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()}; 252 253 ~zonelet(); 254 zonelet(); 255 zonelet(const zonelet& i); 256 zonelet& operator=(const zonelet&) = delete; 257 }; 258 259 #else // USE_OS_TZDB 260 261 struct ttinfo 262 { 263 std::int32_t tt_gmtoff; 264 unsigned char tt_isdst; 265 unsigned char tt_abbrind; 266 unsigned char pad[2]; 267 }; 268 269 static_assert(sizeof(ttinfo) == 8, ""); 270 271 struct expanded_ttinfo 272 { 273 std::chrono::seconds offset; 274 std::string abbrev; 275 bool is_dst; 276 }; 277 278 struct transition 279 { 280 sys_seconds timepoint; 281 const expanded_ttinfo* info; 282 283 transition(sys_seconds tp, const expanded_ttinfo* i = nullptr) 284 : timepoint(tp) 285 , info(i) 286 {} 287 288 friend 289 std::ostream& 290 operator<<(std::ostream& os, const transition& t) 291 { 292 using date::operator<<; 293 os << t.timepoint << "Z "; 294 if (t.info->offset >= std::chrono::seconds{0}) 295 os << '+'; 296 os << make_time(t.info->offset); 297 if (t.info->is_dst > 0) 298 os << " daylight "; 299 else 300 os << " standard "; 301 os << t.info->abbrev; 302 return os; 303 } 304 }; 305 306 #endif // USE_OS_TZDB 307 308 } // namespace detail 309 310 } // namespace date 311 312 #if defined(_MSC_VER) && (_MSC_VER < 1900) 313 #include "tz.h" 314 #endif 315 316 #endif // TZ_PRIVATE_H 317