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