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/time.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/time.cc')
-rw-r--r-- | absl/time/time.cc | 338 |
1 files changed, 219 insertions, 119 deletions
diff --git a/absl/time/time.cc b/absl/time/time.cc index 76ce12c9..e60857e2 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -22,13 +22,14 @@ // NOTE: To keep type verbosity to a minimum, the following variable naming // conventions are used throughout this file. // -// cz: A cctz::time_zone // tz: An absl::TimeZone +// ci: An absl::TimeZone::CivilInfo +// ti: An absl::TimeZone::TimeInfo +// cd: An absl::CivilDay or a cctz::civil_day +// cs: An absl::CivilSecond or a cctz::civil_second +// bd: An absl::Time::Breakdown // cl: A cctz::time_zone::civil_lookup // al: A cctz::time_zone::absolute_lookup -// cd: A cctz::civil_day -// cs: A cctz::civil_second -// bd: An absl::Time::Breakdown #include "absl/time/time.h" @@ -41,12 +42,12 @@ namespace cctz = absl::time_internal::cctz; namespace absl { -inline namespace lts_2018_06_20 { +inline namespace lts_2018_12_18 { namespace { -inline cctz::time_point<cctz::sys_seconds> unix_epoch() { - return std::chrono::time_point_cast<cctz::sys_seconds>( +inline cctz::time_point<cctz::seconds> unix_epoch() { + return std::chrono::time_point_cast<cctz::seconds>( std::chrono::system_clock::from_time_t(0)); } @@ -76,7 +77,7 @@ inline absl::Time::Breakdown InfiniteFutureBreakdown() { return bd; } -inline Time::Breakdown InfinitePastBreakdown() { +inline absl::Time::Breakdown InfinitePastBreakdown() { Time::Breakdown bd; bd.year = std::numeric_limits<int64_t>::min(); bd.month = 1; @@ -93,6 +94,26 @@ inline Time::Breakdown InfinitePastBreakdown() { return bd; } +inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() { + TimeZone::CivilInfo ci; + ci.cs = CivilSecond::max(); + ci.subsecond = InfiniteDuration(); + ci.offset = 0; + ci.is_dst = false; + ci.zone_abbr = "-00"; + return ci; +} + +inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() { + TimeZone::CivilInfo ci; + ci.cs = CivilSecond::min(); + ci.subsecond = -InfiniteDuration(); + ci.offset = 0; + ci.is_dst = false; + ci.zone_abbr = "-00"; + return ci; +} + inline absl::TimeConversion InfiniteFutureTimeConversion() { absl::TimeConversion tc; tc.pre = tc.trans = tc.post = absl::InfiniteFuture(); @@ -111,12 +132,12 @@ inline TimeConversion InfinitePastTimeConversion() { // Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as // necessary. If sec is min/max, then consult cs+tz to check for overlow. -Time MakeTimeWithOverflow(const cctz::time_point<cctz::sys_seconds>& sec, +Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec, const cctz::civil_second& cs, const cctz::time_zone& tz, bool* normalized = nullptr) { - const auto max = cctz::time_point<cctz::sys_seconds>::max(); - const auto min = cctz::time_point<cctz::sys_seconds>::min(); + const auto max = cctz::time_point<cctz::seconds>::max(); + const auto min = cctz::time_point<cctz::seconds>::min(); if (sec == max) { const auto al = tz.lookup(max); if (cs > al.cs) { @@ -135,19 +156,6 @@ Time MakeTimeWithOverflow(const cctz::time_point<cctz::sys_seconds>& sec, return time_internal::FromUnixDuration(time_internal::MakeDuration(hi)); } -inline absl::TimeConversion::Kind MapKind( - const cctz::time_zone::civil_lookup::civil_kind& kind) { - switch (kind) { - case cctz::time_zone::civil_lookup::UNIQUE: - return absl::TimeConversion::UNIQUE; - case cctz::time_zone::civil_lookup::SKIPPED: - return absl::TimeConversion::SKIPPED; - case cctz::time_zone::civil_lookup::REPEATED: - return absl::TimeConversion::REPEATED; - } - return absl::TimeConversion::UNIQUE; -} - // Returns Mon=1..Sun=7. inline int MapWeekday(const cctz::weekday& wd) { switch (wd) { @@ -169,14 +177,31 @@ inline int MapWeekday(const cctz::weekday& wd) { return 1; } +bool FindTransition(const cctz::time_zone& tz, + bool (cctz::time_zone::*find_transition)( + const cctz::time_point<cctz::seconds>& tp, + cctz::time_zone::civil_transition* trans) const, + Time t, TimeZone::CivilTransition* trans) { + // Transitions are second-aligned, so we can discard any fractional part. + const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t)); + cctz::time_zone::civil_transition tr; + if (!(tz.*find_transition)(tp, &tr)) return false; + trans->from = CivilSecond(tr.from); + trans->to = CivilSecond(tr.to); + return true; +} + } // namespace +// +// Time +// + absl::Time::Breakdown Time::In(absl::TimeZone tz) const { - if (*this == absl::InfiniteFuture()) return absl::InfiniteFutureBreakdown(); - if (*this == absl::InfinitePast()) return absl::InfinitePastBreakdown(); + if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown(); + if (*this == absl::InfinitePast()) return InfinitePastBreakdown(); - const auto tp = - unix_epoch() + cctz::sys_seconds(time_internal::GetRepHi(rep_)); + const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_)); const auto al = cctz::time_zone(tz).lookup(tp); const auto cs = al.cs; const auto cd = cctz::civil_day(cs); @@ -189,92 +214,18 @@ absl::Time::Breakdown Time::In(absl::TimeZone tz) const { bd.minute = cs.minute(); bd.second = cs.second(); bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_)); - bd.weekday = MapWeekday(get_weekday(cd)); - bd.yearday = get_yearday(cd); + bd.weekday = MapWeekday(cctz::get_weekday(cd)); + bd.yearday = cctz::get_yearday(cd); bd.offset = al.offset; bd.is_dst = al.is_dst; bd.zone_abbr = al.abbr; return bd; } -absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) { - const auto cz = cctz::time_zone(tz); - const auto cs = - cctz::civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - const auto cl = cz.lookup(cs); - const auto tp = tm.tm_isdst == 0 ? cl.post : cl.pre; - return MakeTimeWithOverflow(tp, cs, cz); -} - -struct tm ToTM(absl::Time t, absl::TimeZone tz) { - const absl::Time::Breakdown bd = t.In(tz); - struct tm tm; - std::memset(&tm, 0, sizeof(tm)); - tm.tm_sec = bd.second; - tm.tm_min = bd.minute; - tm.tm_hour = bd.hour; - tm.tm_mday = bd.day; - tm.tm_mon = bd.month - 1; - - // Saturates tm.tm_year in cases of over/underflow, accounting for the fact - // that tm.tm_year is years since 1900. - if (bd.year < std::numeric_limits<int>::min() + 1900) { - tm.tm_year = std::numeric_limits<int>::min(); - } else if (bd.year > std::numeric_limits<int>::max()) { - tm.tm_year = std::numeric_limits<int>::max() - 1900; - } else { - tm.tm_year = static_cast<int>(bd.year - 1900); - } - - tm.tm_wday = bd.weekday % 7; - tm.tm_yday = bd.yearday - 1; - tm.tm_isdst = bd.is_dst ? 1 : 0; - - return tm; -} - // -// Factory functions. +// Conversions from/to other time types. // -absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz) { - // Avoids years that are too extreme for civil_second to normalize. - if (year > 300000000000) return InfiniteFutureTimeConversion(); - if (year < -300000000000) return InfinitePastTimeConversion(); - const auto cz = cctz::time_zone(tz); - const auto cs = cctz::civil_second(year, mon, day, hour, min, sec); - absl::TimeConversion tc; - tc.normalized = year != cs.year() || mon != cs.month() || day != cs.day() || - hour != cs.hour() || min != cs.minute() || sec != cs.second(); - const auto cl = cz.lookup(cs); - // Converts the civil_lookup struct to a TimeConversion. - tc.pre = MakeTimeWithOverflow(cl.pre, cs, cz, &tc.normalized); - tc.trans = MakeTimeWithOverflow(cl.trans, cs, cz, &tc.normalized); - tc.post = MakeTimeWithOverflow(cl.post, cs, cz, &tc.normalized); - tc.kind = MapKind(cl.kind); - return tc; -} - -absl::Time FromDateTime(int64_t year, int mon, int day, int hour, int min, - int sec, TimeZone tz) { - if (year > 300000000000) return InfiniteFuture(); - if (year < -300000000000) return InfinitePast(); - const auto cz = cctz::time_zone(tz); - const auto cs = cctz::civil_second(year, mon, day, hour, min, sec); - const auto cl = cz.lookup(cs); - return MakeTimeWithOverflow(cl.pre, cs, cz); -} - -absl::Time TimeFromTimespec(timespec ts) { - return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts)); -} - -absl::Time TimeFromTimeval(timeval tv) { - return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv)); -} - absl::Time FromUDate(double udate) { return time_internal::FromUnixDuration(absl::Milliseconds(udate)); } @@ -283,10 +234,6 @@ absl::Time FromUniversal(int64_t universal) { return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal); } -// -// Conversion to other time types. -// - int64_t ToUnixNanos(Time t) { if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) { @@ -323,6 +270,23 @@ int64_t ToUnixSeconds(Time t) { time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; } +double ToUDate(Time t) { + return absl::FDivDuration(time_internal::ToUnixDuration(t), + absl::Milliseconds(1)); +} + +int64_t ToUniversal(absl::Time t) { + return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100)); +} + +absl::Time TimeFromTimespec(timespec ts) { + return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts)); +} + +absl::Time TimeFromTimeval(timeval tv) { + return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv)); +} + timespec ToTimespec(Time t) { timespec ts; absl::Duration d = time_internal::ToUnixDuration(t); @@ -361,15 +325,6 @@ timeval ToTimeval(Time t) { return tv; } -double ToUDate(Time t) { - return absl::FDivDuration(time_internal::ToUnixDuration(t), - absl::Milliseconds(1)); -} - -int64_t ToUniversal(absl::Time t) { - return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100)); -} - Time FromChrono(const std::chrono::system_clock::time_point& tp) { return time_internal::FromUnixDuration(time_internal::FromChrono( tp - std::chrono::system_clock::from_time_t(0))); @@ -383,5 +338,150 @@ std::chrono::system_clock::time_point ToChronoTime(absl::Time t) { time_internal::ToChronoDuration<D>(d); } -} // inline namespace lts_2018_06_20 +// +// TimeZone +// + +absl::TimeZone::CivilInfo TimeZone::At(Time t) const { + if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo(); + if (t == absl::InfinitePast()) return InfinitePastCivilInfo(); + + const auto ud = time_internal::ToUnixDuration(t); + const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud)); + const auto al = cz_.lookup(tp); + + TimeZone::CivilInfo ci; + ci.cs = CivilSecond(al.cs); + ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud)); + ci.offset = al.offset; + ci.is_dst = al.is_dst; + ci.zone_abbr = al.abbr; + return ci; +} + +absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const { + const cctz::civil_second cs(ct); + const auto cl = cz_.lookup(cs); + + TimeZone::TimeInfo ti; + switch (cl.kind) { + case cctz::time_zone::civil_lookup::UNIQUE: + ti.kind = TimeZone::TimeInfo::UNIQUE; + break; + case cctz::time_zone::civil_lookup::SKIPPED: + ti.kind = TimeZone::TimeInfo::SKIPPED; + break; + case cctz::time_zone::civil_lookup::REPEATED: + ti.kind = TimeZone::TimeInfo::REPEATED; + break; + } + ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_); + ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_); + ti.post = MakeTimeWithOverflow(cl.post, cs, cz_); + return ti; +} + +bool TimeZone::NextTransition(Time t, CivilTransition* trans) const { + return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans); +} + +bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const { + return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans); +} + +// +// Conversions involving time zones. +// + +absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, + int min, int sec, TimeZone tz) { + // Avoids years that are too extreme for CivilSecond to normalize. + if (year > 300000000000) return InfiniteFutureTimeConversion(); + if (year < -300000000000) return InfinitePastTimeConversion(); + + const CivilSecond cs(year, mon, day, hour, min, sec); + const auto ti = tz.At(cs); + + TimeConversion tc; + tc.pre = ti.pre; + tc.trans = ti.trans; + tc.post = ti.post; + switch (ti.kind) { + case TimeZone::TimeInfo::UNIQUE: + tc.kind = TimeConversion::UNIQUE; + break; + case TimeZone::TimeInfo::SKIPPED: + tc.kind = TimeConversion::SKIPPED; + break; + case TimeZone::TimeInfo::REPEATED: + tc.kind = TimeConversion::REPEATED; + break; + } + tc.normalized = false; + if (year != cs.year() || mon != cs.month() || day != cs.day() || + hour != cs.hour() || min != cs.minute() || sec != cs.second()) { + tc.normalized = true; + } + return tc; +} + +absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) { + const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + const auto ti = tz.At(cs); + return tm.tm_isdst == 0 ? ti.post : ti.pre; +} + +struct tm ToTM(absl::Time t, absl::TimeZone tz) { + struct tm tm = {}; + + const auto ci = tz.At(t); + const auto& cs = ci.cs; + tm.tm_sec = cs.second(); + tm.tm_min = cs.minute(); + tm.tm_hour = cs.hour(); + tm.tm_mday = cs.day(); + tm.tm_mon = cs.month() - 1; + + // Saturates tm.tm_year in cases of over/underflow, accounting for the fact + // that tm.tm_year is years since 1900. + if (cs.year() < std::numeric_limits<int>::min() + 1900) { + tm.tm_year = std::numeric_limits<int>::min(); + } else if (cs.year() > std::numeric_limits<int>::max()) { + tm.tm_year = std::numeric_limits<int>::max() - 1900; + } else { + tm.tm_year = static_cast<int>(cs.year() - 1900); + } + + const CivilDay cd(cs); + switch (GetWeekday(cd)) { + case Weekday::sunday: + tm.tm_wday = 0; + break; + case Weekday::monday: + tm.tm_wday = 1; + break; + case Weekday::tuesday: + tm.tm_wday = 2; + break; + case Weekday::wednesday: + tm.tm_wday = 3; + break; + case Weekday::thursday: + tm.tm_wday = 4; + break; + case Weekday::friday: + tm.tm_wday = 5; + break; + case Weekday::saturday: + tm.tm_wday = 6; + break; + } + tm.tm_yday = GetYearDay(cd) - 1; + tm.tm_isdst = ci.is_dst ? 1 : 0; + + return tm; +} + +} // inline namespace lts_2018_12_18 } // namespace absl |