1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ 16 #define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ 17 18 #include <atomic> 19 #include <cstddef> 20 #include <cstdint> 21 #include <string> 22 #include <vector> 23 24 #include "absl/time/internal/cctz/include/cctz/civil_time.h" 25 #include "absl/time/internal/cctz/include/cctz/time_zone.h" 26 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" 27 #include "time_zone_if.h" 28 #include "tzfile.h" 29 30 namespace absl { 31 namespace time_internal { 32 namespace cctz { 33 34 // A transition to a new UTC offset. 35 struct Transition { 36 std::int_least64_t unix_time; // the instant of this transition 37 std::uint_least8_t type_index; // index of the transition type 38 civil_second civil_sec; // local civil time of transition 39 civil_second prev_civil_sec; // local civil time one second earlier 40 41 struct ByUnixTime { operatorTransition::ByUnixTime42 inline bool operator()(const Transition& lhs, const Transition& rhs) const { 43 return lhs.unix_time < rhs.unix_time; 44 } 45 }; 46 struct ByCivilTime { operatorTransition::ByCivilTime47 inline bool operator()(const Transition& lhs, const Transition& rhs) const { 48 return lhs.civil_sec < rhs.civil_sec; 49 } 50 }; 51 }; 52 53 // The characteristics of a particular transition. 54 struct TransitionType { 55 std::int_least32_t utc_offset; // the new prevailing UTC offset 56 civil_second civil_max; // max convertible civil time for offset 57 civil_second civil_min; // min convertible civil time for offset 58 bool is_dst; // did we move into daylight-saving time 59 std::uint_least8_t abbr_index; // index of the new abbreviation 60 }; 61 62 // A time zone backed by the IANA Time Zone Database (zoneinfo). 63 class TimeZoneInfo : public TimeZoneIf { 64 public: 65 TimeZoneInfo() = default; 66 TimeZoneInfo(const TimeZoneInfo&) = delete; 67 TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; 68 69 // Loads the zoneinfo for the given name, returning true if successful. 70 bool Load(const std::string& name); 71 72 // TimeZoneIf implementations. 73 time_zone::absolute_lookup BreakTime( 74 const time_point<seconds>& tp) const override; 75 time_zone::civil_lookup MakeTime( 76 const civil_second& cs) const override; 77 bool NextTransition(const time_point<seconds>& tp, 78 time_zone::civil_transition* trans) const override; 79 bool PrevTransition(const time_point<seconds>& tp, 80 time_zone::civil_transition* trans) const override; 81 std::string Version() const override; 82 std::string Description() const override; 83 84 private: 85 struct Header { // counts of: 86 std::size_t timecnt; // transition times 87 std::size_t typecnt; // transition types 88 std::size_t charcnt; // zone abbreviation characters 89 std::size_t leapcnt; // leap seconds (we expect none) 90 std::size_t ttisstdcnt; // UTC/local indicators (unused) 91 std::size_t ttisgmtcnt; // standard/wall indicators (unused) 92 93 bool Build(const tzhead& tzh); 94 std::size_t DataLength(std::size_t time_len) const; 95 }; 96 97 void CheckTransition(const std::string& name, const TransitionType& tt, 98 std::int_fast32_t offset, bool is_dst, 99 const std::string& abbr) const; 100 bool EquivTransitions(std::uint_fast8_t tt1_index, 101 std::uint_fast8_t tt2_index) const; 102 void ExtendTransitions(const std::string& name, const Header& hdr); 103 104 bool ResetToBuiltinUTC(const seconds& offset); 105 bool Load(const std::string& name, ZoneInfoSource* zip); 106 107 // Helpers for BreakTime() and MakeTime(). 108 time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, 109 const TransitionType& tt) const; 110 time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, 111 const Transition& tr) const; 112 time_zone::civil_lookup TimeLocal(const civil_second& cs, 113 year_t c4_shift) const; 114 115 std::vector<Transition> transitions_; // ordered by unix_time and civil_sec 116 std::vector<TransitionType> transition_types_; // distinct transition types 117 std::uint_fast8_t default_transition_type_; // for before first transition 118 std::string abbreviations_; // all the NUL-terminated abbreviations 119 120 std::string version_; // the tzdata version if available 121 std::string future_spec_; // for after the last zic transition 122 bool extended_; // future_spec_ was used to generate transitions 123 year_t last_year_; // the final year of the generated transitions 124 125 // We remember the transitions found during the last BreakTime() and 126 // MakeTime() calls. If the next request is for the same transition we 127 // will avoid re-searching. 128 mutable std::atomic<std::size_t> local_time_hint_ = {}; // BreakTime() hint 129 mutable std::atomic<std::size_t> time_local_hint_ = {}; // MakeTime() hint 130 }; 131 132 } // namespace cctz 133 } // namespace time_internal 134 } // namespace absl 135 136 #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ 137