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 // https://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/base/config.h" 25 #include "absl/time/internal/cctz/include/cctz/civil_time.h" 26 #include "absl/time/internal/cctz/include/cctz/time_zone.h" 27 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" 28 #include "time_zone_if.h" 29 #include "tzfile.h" 30 31 namespace absl { 32 ABSL_NAMESPACE_BEGIN 33 namespace time_internal { 34 namespace cctz { 35 36 // A transition to a new UTC offset. 37 struct Transition { 38 std::int_least64_t unix_time; // the instant of this transition 39 std::uint_least8_t type_index; // index of the transition type 40 civil_second civil_sec; // local civil time of transition 41 civil_second prev_civil_sec; // local civil time one second earlier 42 43 struct ByUnixTime { operatorTransition::ByUnixTime44 inline bool operator()(const Transition& lhs, const Transition& rhs) const { 45 return lhs.unix_time < rhs.unix_time; 46 } 47 }; 48 struct ByCivilTime { operatorTransition::ByCivilTime49 inline bool operator()(const Transition& lhs, const Transition& rhs) const { 50 return lhs.civil_sec < rhs.civil_sec; 51 } 52 }; 53 }; 54 55 // The characteristics of a particular transition. 56 struct TransitionType { 57 std::int_least32_t utc_offset; // the new prevailing UTC offset 58 civil_second civil_max; // max convertible civil time for offset 59 civil_second civil_min; // min convertible civil time for offset 60 bool is_dst; // did we move into daylight-saving time 61 std::uint_least8_t abbr_index; // index of the new abbreviation 62 }; 63 64 // A time zone backed by the IANA Time Zone Database (zoneinfo). 65 class TimeZoneInfo : public TimeZoneIf { 66 public: 67 TimeZoneInfo() = default; 68 TimeZoneInfo(const TimeZoneInfo&) = delete; 69 TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; 70 71 // Loads the zoneinfo for the given name, returning true if successful. 72 bool Load(const std::string& name); 73 74 // TimeZoneIf implementations. 75 time_zone::absolute_lookup BreakTime( 76 const time_point<seconds>& tp) const override; 77 time_zone::civil_lookup MakeTime(const civil_second& cs) const override; 78 bool NextTransition(const time_point<seconds>& tp, 79 time_zone::civil_transition* trans) const override; 80 bool PrevTransition(const time_point<seconds>& tp, 81 time_zone::civil_transition* trans) const override; 82 std::string Version() const override; 83 std::string Description() const override; 84 85 private: 86 struct Header { // counts of: 87 std::size_t timecnt; // transition times 88 std::size_t typecnt; // transition types 89 std::size_t charcnt; // zone abbreviation characters 90 std::size_t leapcnt; // leap seconds (we expect none) 91 std::size_t ttisstdcnt; // UTC/local indicators (unused) 92 std::size_t ttisutcnt; // standard/wall indicators (unused) 93 94 bool Build(const tzhead& tzh); 95 std::size_t DataLength(std::size_t time_len) const; 96 }; 97 98 bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, 99 const std::string& abbr, std::uint_least8_t* index); 100 bool EquivTransitions(std::uint_fast8_t tt1_index, 101 std::uint_fast8_t tt2_index) const; 102 bool ExtendTransitions(); 103 104 bool ResetToBuiltinUTC(const seconds& offset); 105 bool Load(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 ABSL_NAMESPACE_END 135 } // namespace absl 136 137 #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ 138