00001 // Copyright 2016 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 // A library for translating between absolute times (represented by 00016 // std::chrono::time_points of the std::chrono::system_clock) and civil 00017 // times (represented by cctz::civil_second) using the rules defined by 00018 // a time zone (cctz::time_zone). 00019 00020 #ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ 00021 #define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ 00022 00023 #include <chrono> 00024 #include <cstdint> 00025 #include <string> 00026 #include <utility> 00027 00028 #include "absl/time/internal/cctz/include/cctz/civil_time.h" 00029 00030 namespace absl { 00031 namespace time_internal { 00032 namespace cctz { 00033 00034 // Convenience aliases. Not intended as public API points. 00035 template <typename D> 00036 using time_point = std::chrono::time_point<std::chrono::system_clock, D>; 00037 using seconds = std::chrono::duration<std::int_fast64_t>; 00038 using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. 00039 00040 namespace detail { 00041 template <typename D> 00042 inline std::pair<time_point<seconds>, D> 00043 split_seconds(const time_point<D>& tp) { 00044 auto sec = std::chrono::time_point_cast<seconds>(tp); 00045 auto sub = tp - sec; 00046 if (sub.count() < 0) { 00047 sec -= seconds(1); 00048 sub += seconds(1); 00049 } 00050 return {sec, std::chrono::duration_cast<D>(sub)}; 00051 } 00052 inline std::pair<time_point<seconds>, seconds> 00053 split_seconds(const time_point<seconds>& tp) { 00054 return {tp, seconds::zero()}; 00055 } 00056 } // namespace detail 00057 00058 // cctz::time_zone is an opaque, small, value-type class representing a 00059 // geo-political region within which particular rules are used for mapping 00060 // between absolute and civil times. Time zones are named using the TZ 00061 // identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" 00062 // or "Australia/Sydney". Time zones are created from factory functions such 00063 // as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ 00064 // identifiers. 00065 // 00066 // Example: 00067 // cctz::time_zone utc = cctz::utc_time_zone(); 00068 // cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8)); 00069 // cctz::time_zone loc = cctz::local_time_zone(); 00070 // cctz::time_zone lax; 00071 // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } 00072 // 00073 // See also: 00074 // - http://www.iana.org/time-zones 00075 // - https://en.wikipedia.org/wiki/Zoneinfo 00076 class time_zone { 00077 public: 00078 time_zone() : time_zone(nullptr) {} // Equivalent to UTC 00079 time_zone(const time_zone&) = default; 00080 time_zone& operator=(const time_zone&) = default; 00081 00082 std::string name() const; 00083 00084 // An absolute_lookup represents the civil time (cctz::civil_second) within 00085 // this time_zone at the given absolute time (time_point). There are 00086 // additionally a few other fields that may be useful when working with 00087 // older APIs, such as std::tm. 00088 // 00089 // Example: 00090 // const cctz::time_zone tz = ... 00091 // const auto tp = std::chrono::system_clock::now(); 00092 // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); 00093 struct absolute_lookup { 00094 civil_second cs; 00095 // Note: The following fields exist for backward compatibility with older 00096 // APIs. Accessing these fields directly is a sign of imprudent logic in 00097 // the calling code. Modern time-related code should only access this data 00098 // indirectly by way of cctz::format(). 00099 int offset; // civil seconds east of UTC 00100 bool is_dst; // is offset non-standard? 00101 const char* abbr; // time-zone abbreviation (e.g., "PST") 00102 }; 00103 absolute_lookup lookup(const time_point<seconds>& tp) const; 00104 template <typename D> 00105 absolute_lookup lookup(const time_point<D>& tp) const { 00106 return lookup(detail::split_seconds(tp).first); 00107 } 00108 00109 // A civil_lookup represents the absolute time(s) (time_point) that 00110 // correspond to the given civil time (cctz::civil_second) within this 00111 // time_zone. Usually the given civil time represents a unique instant 00112 // in time, in which case the conversion is unambiguous. However, 00113 // within this time zone, the given civil time may be skipped (e.g., 00114 // during a positive UTC offset shift), or repeated (e.g., during a 00115 // negative UTC offset shift). To account for these possibilities, 00116 // civil_lookup is richer than just a single time_point. 00117 // 00118 // In all cases the civil_lookup::kind enum will indicate the nature 00119 // of the given civil-time argument, and the pre, trans, and post 00120 // members will give the absolute time answers using the pre-transition 00121 // offset, the transition point itself, and the post-transition offset, 00122 // respectively (all three times are equal if kind == UNIQUE). If any 00123 // of these three absolute times is outside the representable range of a 00124 // time_point<seconds> the field is set to its maximum/minimum value. 00125 // 00126 // Example: 00127 // cctz::time_zone lax; 00128 // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } 00129 // 00130 // // A unique civil time. 00131 // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); 00132 // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE 00133 // // jan01.pre is 2011/01/01 00:00:00 -0800 00134 // // jan01.trans is 2011/01/01 00:00:00 -0800 00135 // // jan01.post is 2011/01/01 00:00:00 -0800 00136 // 00137 // // A Spring DST transition, when there is a gap in civil time. 00138 // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); 00139 // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED 00140 // // mar13.pre is 2011/03/13 03:15:00 -0700 00141 // // mar13.trans is 2011/03/13 03:00:00 -0700 00142 // // mar13.post is 2011/03/13 01:15:00 -0800 00143 // 00144 // // A Fall DST transition, when civil times are repeated. 00145 // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); 00146 // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED 00147 // // nov06.pre is 2011/11/06 01:15:00 -0700 00148 // // nov06.trans is 2011/11/06 01:00:00 -0800 00149 // // nov06.post is 2011/11/06 01:15:00 -0800 00150 struct civil_lookup { 00151 enum civil_kind { 00152 UNIQUE, // the civil time was singular (pre == trans == post) 00153 SKIPPED, // the civil time did not exist (pre >= trans > post) 00154 REPEATED, // the civil time was ambiguous (pre < trans <= post) 00155 } kind; 00156 time_point<seconds> pre; // uses the pre-transition offset 00157 time_point<seconds> trans; // instant of civil-offset change 00158 time_point<seconds> post; // uses the post-transition offset 00159 }; 00160 civil_lookup lookup(const civil_second& cs) const; 00161 00162 // Finds the time of the next/previous offset change in this time zone. 00163 // 00164 // By definition, next_transition(tp, &trans) returns false when tp has 00165 // its maximum value, and prev_transition(tp, &trans) returns false 00166 // when tp has its minimum value. If the zone has no transitions, the 00167 // result will also be false no matter what the argument. 00168 // 00169 // Otherwise, when tp has its minimum value, next_transition(tp, &trans) 00170 // returns true and sets trans to the first recorded transition. Chains 00171 // of calls to next_transition()/prev_transition() will eventually return 00172 // false, but it is unspecified exactly when next_transition(tp, &trans) 00173 // jumps to false, or what time is set by prev_transition(tp, &trans) for 00174 // a very distant tp. 00175 // 00176 // Note: Enumeration of time-zone transitions is for informational purposes 00177 // only. Modern time-related code should not care about when offset changes 00178 // occur. 00179 // 00180 // Example: 00181 // cctz::time_zone nyc; 00182 // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } 00183 // const auto now = std::chrono::system_clock::now(); 00184 // auto tp = cctz::time_point<cctz::seconds>::min(); 00185 // cctz::time_zone::civil_transition trans; 00186 // while (tp <= now && nyc.next_transition(tp, &trans)) { 00187 // // transition: trans.from -> trans.to 00188 // tp = nyc.lookup(trans.to).trans; 00189 // } 00190 struct civil_transition { 00191 civil_second from; // the civil time we jump from 00192 civil_second to; // the civil time we jump to 00193 }; 00194 bool next_transition(const time_point<seconds>& tp, 00195 civil_transition* trans) const; 00196 template <typename D> 00197 bool next_transition(const time_point<D>& tp, 00198 civil_transition* trans) const { 00199 return next_transition(detail::split_seconds(tp).first, trans); 00200 } 00201 bool prev_transition(const time_point<seconds>& tp, 00202 civil_transition* trans) const; 00203 template <typename D> 00204 bool prev_transition(const time_point<D>& tp, 00205 civil_transition* trans) const { 00206 return prev_transition(detail::split_seconds(tp).first, trans); 00207 } 00208 00209 // version() and description() provide additional information about the 00210 // time zone. The content of each of the returned strings is unspecified, 00211 // however, when the IANA Time Zone Database is the underlying data source 00212 // the version() std::string will be in the familar form (e.g, "2018e") or 00213 // empty when unavailable. 00214 // 00215 // Note: These functions are for informational or testing purposes only. 00216 std::string version() const; // empty when unknown 00217 std::string description() const; 00218 00219 // Relational operators. 00220 friend bool operator==(time_zone lhs, time_zone rhs) { 00221 return &lhs.effective_impl() == &rhs.effective_impl(); 00222 } 00223 friend bool operator!=(time_zone lhs, time_zone rhs) { 00224 return !(lhs == rhs); 00225 } 00226 00227 template <typename H> 00228 friend H AbslHashValue(H h, time_zone tz) { 00229 return H::combine(std::move(h), &tz.effective_impl()); 00230 } 00231 00232 class Impl; 00233 00234 private: 00235 explicit time_zone(const Impl* impl) : impl_(impl) {} 00236 const Impl& effective_impl() const; // handles implicit UTC 00237 const Impl* impl_; 00238 }; 00239 00240 // Loads the named time zone. May perform I/O on the initial load. 00241 // If the name is invalid, or some other kind of error occurs, returns 00242 // false and "*tz" is set to the UTC time zone. 00243 bool load_time_zone(const std::string& name, time_zone* tz); 00244 00245 // Returns a time_zone representing UTC. Cannot fail. 00246 time_zone utc_time_zone(); 00247 00248 // Returns a time zone that is a fixed offset (seconds east) from UTC. 00249 // Note: If the absolute value of the offset is greater than 24 hours 00250 // you'll get UTC (i.e., zero offset) instead. 00251 time_zone fixed_time_zone(const seconds& offset); 00252 00253 // Returns a time zone representing the local time zone. Falls back to UTC. 00254 // Note: local_time_zone.name() may only be something like "localtime". 00255 time_zone local_time_zone(); 00256 00257 // Returns the civil time (cctz::civil_second) within the given time zone at 00258 // the given absolute time (time_point). Since the additional fields provided 00259 // by the time_zone::absolute_lookup struct should rarely be needed in modern 00260 // code, this convert() function is simpler and should be preferred. 00261 template <typename D> 00262 inline civil_second convert(const time_point<D>& tp, const time_zone& tz) { 00263 return tz.lookup(tp).cs; 00264 } 00265 00266 // Returns the absolute time (time_point) that corresponds to the given civil 00267 // time within the given time zone. If the civil time is not unique (i.e., if 00268 // it was either repeated or non-existent), then the returned time_point is 00269 // the best estimate that preserves relative order. That is, this function 00270 // guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). 00271 inline time_point<seconds> convert(const civil_second& cs, 00272 const time_zone& tz) { 00273 const time_zone::civil_lookup cl = tz.lookup(cs); 00274 if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; 00275 return cl.pre; 00276 } 00277 00278 namespace detail { 00279 using femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>; 00280 std::string format(const std::string&, const time_point<seconds>&, 00281 const femtoseconds&, const time_zone&); 00282 bool parse(const std::string&, const std::string&, const time_zone&, 00283 time_point<seconds>*, femtoseconds*, std::string* err = nullptr); 00284 } // namespace detail 00285 00286 // Formats the given time_point in the given cctz::time_zone according to 00287 // the provided format string. Uses strftime()-like formatting options, 00288 // with the following extensions: 00289 // 00290 // - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) 00291 // - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) 00292 // - %E#S - Seconds with # digits of fractional precision 00293 // - %E*S - Seconds with full fractional precision (a literal '*') 00294 // - %E#f - Fractional seconds with # digits of precision 00295 // - %E*f - Fractional seconds with full precision (a literal '*') 00296 // - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) 00297 // 00298 // Note that %E0S behaves like %S, and %E0f produces no characters. In 00299 // contrast %E*f always produces at least one digit, which may be '0'. 00300 // 00301 // Note that %Y produces as many characters as it takes to fully render the 00302 // year. A year outside of [-999:9999] when formatted with %E4Y will produce 00303 // more than four characters, just like %Y. 00304 // 00305 // Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z) 00306 // so that the resulting string uniquely identifies an absolute time. 00307 // 00308 // Example: 00309 // cctz::time_zone lax; 00310 // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } 00311 // auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); 00312 // std::string f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05" 00313 // f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" 00314 template <typename D> 00315 inline std::string format(const std::string& fmt, const time_point<D>& tp, 00316 const time_zone& tz) { 00317 const auto p = detail::split_seconds(tp); 00318 const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second); 00319 return detail::format(fmt, p.first, n, tz); 00320 } 00321 00322 // Parses an input string according to the provided format string and 00323 // returns the corresponding time_point. Uses strftime()-like formatting 00324 // options, with the same extensions as cctz::format(), but with the 00325 // exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez 00326 // and %E*z also accept the same inputs. 00327 // 00328 // %Y consumes as many numeric characters as it can, so the matching data 00329 // should always be terminated with a non-numeric. %E4Y always consumes 00330 // exactly four characters, including any sign. 00331 // 00332 // Unspecified fields are taken from the default date and time of ... 00333 // 00334 // "1970-01-01 00:00:00.0 +0000" 00335 // 00336 // For example, parsing a string of "15:45" (%H:%M) will return a time_point 00337 // that represents "1970-01-01 15:45:00.0 +0000". 00338 // 00339 // Note that parse() returns time instants, so it makes most sense to parse 00340 // fully-specified date/time strings that include a UTC offset (%z, %Ez, or 00341 // %E*z). 00342 // 00343 // Note also that parse() only heeds the fields year, month, day, hour, 00344 // minute, (fractional) second, and UTC offset. Other fields, like weekday (%a 00345 // or %A), while parsed for syntactic validity, are ignored in the conversion. 00346 // 00347 // Date and time fields that are out-of-range will be treated as errors rather 00348 // than normalizing them like cctz::civil_second() would do. For example, it 00349 // is an error to parse the date "Oct 32, 2013" because 32 is out of range. 00350 // 00351 // A second of ":60" is normalized to ":00" of the following minute with 00352 // fractional seconds discarded. The following table shows how the given 00353 // seconds and subseconds will be parsed: 00354 // 00355 // "59.x" -> 59.x // exact 00356 // "60.x" -> 00.0 // normalized 00357 // "00.x" -> 00.x // exact 00358 // 00359 // Errors are indicated by returning false. 00360 // 00361 // Example: 00362 // const cctz::time_zone tz = ... 00363 // std::chrono::system_clock::time_point tp; 00364 // if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { 00365 // ... 00366 // } 00367 template <typename D> 00368 inline bool parse(const std::string& fmt, const std::string& input, 00369 const time_zone& tz, time_point<D>* tpp) { 00370 time_point<seconds> sec; 00371 detail::femtoseconds fs; 00372 const bool b = detail::parse(fmt, input, tz, &sec, &fs); 00373 if (b) { 00374 // TODO: Return false if unrepresentable as a time_point<D>. 00375 *tpp = std::chrono::time_point_cast<D>(sec); 00376 *tpp += std::chrono::duration_cast<D>(fs); 00377 } 00378 return b; 00379 } 00380 00381 } // namespace cctz 00382 } // namespace time_internal 00383 } // namespace absl 00384 00385 #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_