diff options
author | Abseil Team <absl-team@google.com> | 2018-12-04 11:01:12 -0800 |
---|---|---|
committer | Ashley Hedberg <ahedberg@google.com> | 2018-12-04 16:54:40 -0500 |
commit | fcb104594b0bb4b8ac306cb2f55ecdad40974683 (patch) | |
tree | d2d79d246c6a894ca6716f47c15ebb7b8796b36a /absl/time/internal/cctz/src/time_zone_libc.cc | |
parent | 6c7de165d1c82684359ccb630bb5f83263fa5ebc (diff) | |
download | abseil-fcb104594b0bb4b8ac306cb2f55ecdad40974683.tar.gz abseil-fcb104594b0bb4b8ac306cb2f55ecdad40974683.tar.bz2 abseil-fcb104594b0bb4b8ac306cb2f55ecdad40974683.zip |
Creation of LTS branch "lts_2018_12_18"
- 44b0fafc62d9b8f192e8180cbe9c4b806b339d57 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 926bfeb9fff223429c12224b7514243886323e8d Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 13327debebc5c2d1d4991b69fe50450e340e50e4 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 3088e76c597e068479e82508b1770a7ad0c806b6 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f6ae816808cd913e0e2b3e2af14f328fa1071af0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- a06c4a1d9093137b7217a5aaba8920d62e835dc0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 7b46e1d31a6b08b1c6da2a13e7b151a20446fa07 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 070f6e47b33a2909d039e620c873204f78809492 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 7990fd459e9339467814ddb95000c87cb1e4d945 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f95179062eb65ce40895cc76f1398cce25394369 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- cc8dcd307b76a575d2e3e0958a4fe4c7193c2f68 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- a705aa78dc76fc5c79d501e61dcc077eca68a8a4 Merge pull request #194 from Mizux/windows by Xiaoyi Zhang <zhangxy988@gmail.com>
- a4c3ffff11eec0ee45742f915c255e9f870b7e0f Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 01174578651b73021d9b8c3820f6fea707dacdf0 Merge pull request #201 from ccawley2011/fix-byteswap by Matt Calabrese <38107210+mattcalabrese-google@users.noreply.github.com>
- f86f9413856b65afdd61fea938d684b8ab73115a Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 94c298e2a0ae409e283cab96c954a685bd865a70 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 0884a6a04e4497d11b1b398cc0e422b118bf977a Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- c16d5557cd05119b5b7b1318ef778ebe3195b4a1 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 45221ccc4ed643e4209b0cc5798e97203f108fa8 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 2019e17a520575ab365b2b5134d71068182c70b8 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 5b70a8910b2e6fb0ce5193a41873139a126d2f7f Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- a00bdd176d66ef0b417d9576052a19091fbdf891 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f340f773edab951656b19b6f1a77c964a78ec4c2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 445998d7ac4e5d3c50411d377e3b50e960d2d6c2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- e821380d69a549dc64900693942789d21aa4df5e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f21d187b80e3b7f08fb279775ea9c8b48c636030 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 5441bbe1db5d0f2ca24b5b60166367b0966790af Fix code snippet in comment (#174) by Loo Rong Jie <loorongjie@gmail.com>
- 5aae0cffae8ffaacab965756169b34e511b353df Fix CMake build (#173) by Stephan Dollberg <stephan.dollberg@gmail.com>
- 48cd2c3f351ff188bc85684b84a91b6e6d17d896 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- e291c279e458761e77a69b09b129d3d1e81f1e80 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- e01d95528ea2137a4a27a88d1f57c6cb260aafed Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 8ff1374008259719b54a8cb128ef951c02da164c Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 02451914b9ad5320f81f56a89f3eef1f8683227c Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 921fd5cf02ec0d665439a790148d59faa7d4a72c Merge pull request #166 from rongjiecomputer/cmake-test by Gennadiy Civil <gennadiycivil@users.noreply.github.com>
- fb462224c058487763f263b7995d70efd0242c17 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- c075ad321696fa5072e097f0a51e4fe76a6fe13e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 0f4bc966754ec6cd28d5f03467d56f1efdc598e3 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 6c7e5ffc43decd92f7bdfc510ad8a245a20b6dea Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- d6df769173bf0263489f98874b93034db0e479a2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 28080f5f050c9530aa9f2b39c60d8217038d64ff Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 9c987f429bba32fb4446280fd3b91e2472d71d4d Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 5e7d459eeca7bc53deab0ee9634601386b53d7c0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- bed5bd6e185c7e0311f3a1f2dab4c96083dac636 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- fefc83638fb69395d259ed245699310610429064 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- d8cfe9f2a77fbee02c09642491e62a3f3677e0f6 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- ad5c960b2eb914881d1ceba0e996a0a8f3f6ca59 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 86f0fe93ad9d6d033a319476736a3256369c1f75 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f0f15c2778b0e4959244dd25e63f445a455870f5 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 29ff6d4860070bf8fcbd39c8805d0c32d56628a3 Removed "warning treated as error" flag from MSVC (#153) by vocaviking <vocaviking@users.noreply.github.com>
- 083d04dd4a62ebbf037079b06e49b323c5e1192a Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- bea85b52733022294eef108a2e42d77b616ddca2 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 8f96be6ca60d967bd4b37f93d0a03bcff4145200 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 92e07e5590752d6b8e67f7f2f86c6286561e8cea Merge pull request #152 from clnperez/fix-multi-defines-p... by Derek Mauro <761129+derekmauro@users.noreply.github.com>
- 2125e6444a9de9e41f21ecdc674dd7d8759c149d Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 9acad869d21731f5bc50430a33fe61cc0ffcbb0b Merge pull request #150 from OlafvdSpek/patch-2 by Jonathan Cohen <cohenjon@google.com>
- c2e00d341913bf03b4597ade5b056042e23e8c58 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 9e060686d1c325f34f9806b45fe77bafeed00aee Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 7aa411ceafc1272a28579cca739a97a2fb79055a Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 2c5af55ed34850d8b7dd46177c8ca53fdfda920e Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 44aa275286baf97fc13529aca547a88b180beb08 Merge pull request #143 from rongjiecomputer/kernel by Xiaoyi Zhang <zhangxy988@gmail.com>
- 42f22a28401c952f1fc5942231c7fdac80811bf5 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- b973bc53ef366f0253b85eeed9a79b241884a843 Merge pull request #139 from siepkes/smartos-support by ahedberg <ahedberg@google.com>
- e0def7473e52336f58759e11db4cd9467e5e0356 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- f826f1d489b61b64df1d94afbe5981841a82e5fa Merge pull request #138 from edbaunton/remove-deprecated-... by ahedberg <ahedberg@google.com>
- 7b50a4a94b0c7df68b3a854c850b551aaef0a8b4 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- a5030ca5125b9d557ecfeea8acc8b1a8e49f6d27 Merge pull request #144 from rongjiecomputer/winsock2 by Xiaoyi Zhang <zhangxy988@gmail.com>
- 02687955b7ca8fc02ada9b14bc247deeb108d341 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 8f612ebb152fb7e05643a2bcf78cb89a8c0641ad Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 134496a31d8b324f762de3bee9a002658c984456 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- ba8d6cf07766263723e86736f20a51c1c9c67b19 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- be1e84b988fceabcea4fc9e93f899539f0c81901 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 16ac2ec2e38cdf47f9330a312e319d57da659c10 Merge pull request #134 from rongjiecomputer/cmake by Alex Strelnikov <strel@google.com>
- 7efd8dc0f1075356e9c7caa950afd1ecf854e8b9 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 87a4c07856e7dc69958019d47b2f02ae47746ec0 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
- 4491d606df34c44efda47b6d17b605262f17e182 Export of internal Abseil changes. by Abseil Team <absl-team@google.com>
GitOrigin-RevId: 44b0fafc62d9b8f192e8180cbe9c4b806b339d57
Change-Id: I2c427b5b41b2d34101922048b00f3d9dafcb498d
Diffstat (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc')
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_libc.cc | 222 |
1 files changed, 178 insertions, 44 deletions
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 32a7a927..3dd75b50 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -20,6 +20,7 @@ #include <chrono> #include <ctime> +#include <limits> #include <tuple> #include <utility> @@ -27,7 +28,7 @@ #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace time_internal { namespace cctz { @@ -86,73 +87,206 @@ OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr, #endif // !defined(__tm_gmtoff) && !defined(__tm_zone) #endif +inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return gmtime_s(result, timep) ? nullptr : result; +#else + return gmtime_r(timep, result); +#endif +} + +inline std::tm* local_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return localtime_s(result, timep) ? nullptr : result; +#else + return localtime_r(timep, result); +#endif +} + +// Converts a civil second and "dst" flag into a time_t and UTC offset. +// Returns false if time_t cannot represent the requested civil second. +// Caller must have already checked that cs.year() will fit into a tm_year. +bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { + std::tm tm; + tm.tm_year = static_cast<int>(cs.year() - year_t{1900}); + tm.tm_mon = cs.month() - 1; + tm.tm_mday = cs.day(); + tm.tm_hour = cs.hour(); + tm.tm_min = cs.minute(); + tm.tm_sec = cs.second(); + tm.tm_isdst = is_dst; + *t = std::mktime(&tm); + if (*t == std::time_t{-1}) { + std::tm tm2; + const std::tm* tmp = local_time(t, &tm2); + if (tmp == nullptr || tmp->tm_year != tm.tm_year || + tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday || + tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min || + tmp->tm_sec != tm.tm_sec) { + // A true error (not just one second before the epoch). + return false; + } + } + *off = get_offset_abbr(tm).first; + return true; +} + +// Find the least time_t in [lo:hi] where local time matches offset, given: +// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. +std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { + std::tm tm; + while (lo + 1 != hi) { + const std::time_t mid = lo + (hi - lo) / 2; + if (std::tm* tmp = local_time(&mid, &tm)) { + if (get_offset_abbr(*tmp).first == offset) { + hi = mid; + } else { + lo = mid; + } + } else { + // If std::tm cannot hold some result we resort to a linear search, + // ignoring all failed conversions. Slow, but never really happens. + while (++lo != hi) { + if (std::tm* tmp = local_time(&lo, &tm)) { + if (get_offset_abbr(*tmp).first == offset) break; + } + } + return lo; + } + } + return hi; +} + } // namespace TimeZoneLibC::TimeZoneLibC(const std::string& name) : local_(name == "localtime") {} time_zone::absolute_lookup TimeZoneLibC::BreakTime( - const time_point<sys_seconds>& tp) const { + const time_point<seconds>& tp) const { time_zone::absolute_lookup al; - std::time_t t = ToUnixSeconds(tp); + al.offset = 0; + al.is_dst = false; + al.abbr = "-00"; + + const std::int_fast64_t s = ToUnixSeconds(tp); + + // If std::time_t cannot hold the input we saturate the output. + if (s < std::numeric_limits<std::time_t>::min()) { + al.cs = civil_second::min(); + return al; + } + if (s > std::numeric_limits<std::time_t>::max()) { + al.cs = civil_second::max(); + return al; + } + + const std::time_t t = static_cast<std::time_t>(s); std::tm tm; - if (local_) { -#if defined(_WIN32) || defined(_WIN64) - localtime_s(&tm, &t); -#else - localtime_r(&t, &tm); -#endif - std::tie(al.offset, al.abbr) = get_offset_abbr(tm); - } else { -#if defined(_WIN32) || defined(_WIN64) - gmtime_s(&tm, &t); -#else - gmtime_r(&t, &tm); -#endif - al.offset = 0; - al.abbr = "UTC"; + std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); + + // If std::tm cannot hold the result we saturate the output. + if (tmp == nullptr) { + al.cs = (s < 0) ? civil_second::min() : civil_second::max(); + return al; } - al.cs = civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - al.is_dst = tm.tm_isdst > 0; + + const year_t year = tmp->tm_year + year_t{1900}; + al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp); + if (!local_) al.abbr = "UTC"; // as expected by cctz + al.is_dst = tmp->tm_isdst > 0; return al; } time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { - time_zone::civil_lookup cl; - std::time_t t; - if (local_) { - // Does not handle SKIPPED/AMBIGUOUS or huge years. - std::tm tm; - tm.tm_year = static_cast<int>(cs.year() - 1900); - tm.tm_mon = cs.month() - 1; - tm.tm_mday = cs.day(); - tm.tm_hour = cs.hour(); - tm.tm_min = cs.minute(); - tm.tm_sec = cs.second(); - tm.tm_isdst = -1; - t = std::mktime(&tm); + if (!local_) { + // If time_point<seconds> cannot hold the result we saturate. + static const civil_second min_tp_cs = + civil_second() + ToUnixSeconds(time_point<seconds>::min()); + static const civil_second max_tp_cs = + civil_second() + ToUnixSeconds(time_point<seconds>::max()); + const time_point<seconds> tp = + (cs < min_tp_cs) + ? time_point<seconds>::min() + : (cs > max_tp_cs) ? time_point<seconds>::max() + : FromUnixSeconds(cs - civil_second()); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + // If tm_year cannot hold the requested year we saturate the result. + if (cs.year() < 0) { + if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) { + const time_point<seconds> tp = time_point<seconds>::min(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } } else { - t = cs - civil_second(); + if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) { + const time_point<seconds> tp = time_point<seconds>::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } } - cl.kind = time_zone::civil_lookup::UNIQUE; - cl.pre = cl.trans = cl.post = FromUnixSeconds(t); - return cl; -} -std::string TimeZoneLibC::Description() const { - return local_ ? "localtime" : "UTC"; + // We probe with "is_dst" values of 0 and 1 to try to distinguish unique + // civil seconds from skipped or repeated ones. This is not always possible + // however, as the "dst" flag does not change over some offset transitions. + // We are also subject to the vagaries of mktime() implementations. + std::time_t t0, t1; + int offset0, offset1; + if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) { + if (t0 == t1) { + // The civil time was singular (pre == trans == post). + const time_point<seconds> tp = FromUnixSeconds(t0); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + if (t0 > t1) { + std::swap(t0, t1); + std::swap(offset0, offset1); + } + const std::time_t tt = find_trans(t0, t1, offset1); + const time_point<seconds> trans = FromUnixSeconds(tt); + + if (offset0 < offset1) { + // The civil time did not exist (pre >= trans > post). + const time_point<seconds> pre = FromUnixSeconds(t1); + const time_point<seconds> post = FromUnixSeconds(t0); + return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; + } + + // The civil time was ambiguous (pre < trans <= post). + const time_point<seconds> pre = FromUnixSeconds(t0); + const time_point<seconds> post = FromUnixSeconds(t1); + return {time_zone::civil_lookup::REPEATED, pre, trans, post}; + } + + // make_time() failed somehow so we saturate the result. + const time_point<seconds> tp = (cs < civil_second()) + ? time_point<seconds>::min() + : time_point<seconds>::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } -bool TimeZoneLibC::NextTransition(time_point<sys_seconds>* tp) const { +bool TimeZoneLibC::NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { return false; } -bool TimeZoneLibC::PrevTransition(time_point<sys_seconds>* tp) const { +bool TimeZoneLibC::PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { return false; } +std::string TimeZoneLibC::Version() const { + return std::string(); // unknown +} + +std::string TimeZoneLibC::Description() const { + return local_ ? "localtime" : "UTC"; +} + } // namespace cctz } // namespace time_internal -} // inline namespace lts_2018_06_20 +} // inline namespace lts_2018_12_18 } // namespace absl |