tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

time.cc (15652B)


      1 // Copyright 2017 The Abseil Authors.
      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 // The implementation of the absl::Time class, which is declared in
     16 // //absl/time.h.
     17 //
     18 // The representation for an absl::Time is an absl::Duration offset from the
     19 // epoch.  We use the traditional Unix epoch (1970-01-01 00:00:00 +0000)
     20 // for convenience, but this is not exposed in the API and could be changed.
     21 //
     22 // NOTE: To keep type verbosity to a minimum, the following variable naming
     23 // conventions are used throughout this file.
     24 //
     25 // tz: An absl::TimeZone
     26 // ci: An absl::TimeZone::CivilInfo
     27 // ti: An absl::TimeZone::TimeInfo
     28 // cd: An absl::CivilDay or a cctz::civil_day
     29 // cs: An absl::CivilSecond or a cctz::civil_second
     30 // bd: An absl::Time::Breakdown
     31 // cl: A cctz::time_zone::civil_lookup
     32 // al: A cctz::time_zone::absolute_lookup
     33 
     34 #include "absl/time/time.h"
     35 
     36 #if defined(_MSC_VER)
     37 #include <winsock2.h>  // for timeval
     38 #endif
     39 
     40 #include <cstring>
     41 #include <ctime>
     42 #include <limits>
     43 
     44 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
     45 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
     46 
     47 namespace cctz = absl::time_internal::cctz;
     48 
     49 namespace absl {
     50 ABSL_NAMESPACE_BEGIN
     51 
     52 namespace {
     53 
     54 inline cctz::time_point<cctz::seconds> unix_epoch() {
     55  return std::chrono::time_point_cast<cctz::seconds>(
     56      std::chrono::system_clock::from_time_t(0));
     57 }
     58 
     59 // Floors d to the next unit boundary closer to negative infinity.
     60 inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
     61  absl::Duration rem;
     62  int64_t q = absl::IDivDuration(d, unit, &rem);
     63  return (q > 0 || rem >= ZeroDuration() ||
     64          q == std::numeric_limits<int64_t>::min())
     65             ? q
     66             : q - 1;
     67 }
     68 
     69 ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
     70 inline absl::Time::Breakdown InfiniteFutureBreakdown() {
     71  absl::Time::Breakdown bd;
     72  bd.year = std::numeric_limits<int64_t>::max();
     73  bd.month = 12;
     74  bd.day = 31;
     75  bd.hour = 23;
     76  bd.minute = 59;
     77  bd.second = 59;
     78  bd.subsecond = absl::InfiniteDuration();
     79  bd.weekday = 4;
     80  bd.yearday = 365;
     81  bd.offset = 0;
     82  bd.is_dst = false;
     83  bd.zone_abbr = "-00";
     84  return bd;
     85 }
     86 
     87 inline absl::Time::Breakdown InfinitePastBreakdown() {
     88  Time::Breakdown bd;
     89  bd.year = std::numeric_limits<int64_t>::min();
     90  bd.month = 1;
     91  bd.day = 1;
     92  bd.hour = 0;
     93  bd.minute = 0;
     94  bd.second = 0;
     95  bd.subsecond = -absl::InfiniteDuration();
     96  bd.weekday = 7;
     97  bd.yearday = 1;
     98  bd.offset = 0;
     99  bd.is_dst = false;
    100  bd.zone_abbr = "-00";
    101  return bd;
    102 }
    103 ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
    104 
    105 inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
    106  TimeZone::CivilInfo ci;
    107  ci.cs = CivilSecond::max();
    108  ci.subsecond = InfiniteDuration();
    109  ci.offset = 0;
    110  ci.is_dst = false;
    111  ci.zone_abbr = "-00";
    112  return ci;
    113 }
    114 
    115 inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
    116  TimeZone::CivilInfo ci;
    117  ci.cs = CivilSecond::min();
    118  ci.subsecond = -InfiniteDuration();
    119  ci.offset = 0;
    120  ci.is_dst = false;
    121  ci.zone_abbr = "-00";
    122  return ci;
    123 }
    124 
    125 ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
    126 inline absl::TimeConversion InfiniteFutureTimeConversion() {
    127  absl::TimeConversion tc;
    128  tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
    129  tc.kind = absl::TimeConversion::UNIQUE;
    130  tc.normalized = true;
    131  return tc;
    132 }
    133 
    134 inline TimeConversion InfinitePastTimeConversion() {
    135  absl::TimeConversion tc;
    136  tc.pre = tc.trans = tc.post = absl::InfinitePast();
    137  tc.kind = absl::TimeConversion::UNIQUE;
    138  tc.normalized = true;
    139  return tc;
    140 }
    141 ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
    142 
    143 // Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as
    144 // necessary. If sec is min/max, then consult cs+tz to check for overflow.
    145 Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec,
    146                          const cctz::civil_second& cs,
    147                          const cctz::time_zone& tz,
    148                          bool* normalized = nullptr) {
    149  const auto max = cctz::time_point<cctz::seconds>::max();
    150  const auto min = cctz::time_point<cctz::seconds>::min();
    151  if (sec == max) {
    152    const auto al = tz.lookup(max);
    153    if (cs > al.cs) {
    154      if (normalized) *normalized = true;
    155      return absl::InfiniteFuture();
    156    }
    157  }
    158  if (sec == min) {
    159    const auto al = tz.lookup(min);
    160    if (cs < al.cs) {
    161      if (normalized) *normalized = true;
    162      return absl::InfinitePast();
    163    }
    164  }
    165  const auto hi = (sec - unix_epoch()).count();
    166  return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
    167 }
    168 
    169 // Returns Mon=1..Sun=7.
    170 inline int MapWeekday(const cctz::weekday& wd) {
    171  switch (wd) {
    172    case cctz::weekday::monday:
    173      return 1;
    174    case cctz::weekday::tuesday:
    175      return 2;
    176    case cctz::weekday::wednesday:
    177      return 3;
    178    case cctz::weekday::thursday:
    179      return 4;
    180    case cctz::weekday::friday:
    181      return 5;
    182    case cctz::weekday::saturday:
    183      return 6;
    184    case cctz::weekday::sunday:
    185      return 7;
    186  }
    187  return 1;
    188 }
    189 
    190 bool FindTransition(const cctz::time_zone& tz,
    191                    bool (cctz::time_zone::*find_transition)(
    192                        const cctz::time_point<cctz::seconds>& tp,
    193                        cctz::time_zone::civil_transition* trans) const,
    194                    Time t, TimeZone::CivilTransition* trans) {
    195  // Transitions are second-aligned, so we can discard any fractional part.
    196  const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
    197  cctz::time_zone::civil_transition tr;
    198  if (!(tz.*find_transition)(tp, &tr)) return false;
    199  trans->from = CivilSecond(tr.from);
    200  trans->to = CivilSecond(tr.to);
    201  return true;
    202 }
    203 
    204 }  // namespace
    205 
    206 //
    207 // Time
    208 //
    209 
    210 ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
    211 absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
    212  if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
    213  if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
    214 
    215  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
    216  const auto al = cctz::time_zone(tz).lookup(tp);
    217  const auto cs = al.cs;
    218  const auto cd = cctz::civil_day(cs);
    219 
    220  absl::Time::Breakdown bd;
    221  bd.year = cs.year();
    222  bd.month = cs.month();
    223  bd.day = cs.day();
    224  bd.hour = cs.hour();
    225  bd.minute = cs.minute();
    226  bd.second = cs.second();
    227  bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
    228  bd.weekday = MapWeekday(cctz::get_weekday(cd));
    229  bd.yearday = cctz::get_yearday(cd);
    230  bd.offset = al.offset;
    231  bd.is_dst = al.is_dst;
    232  bd.zone_abbr = al.abbr;
    233  return bd;
    234 }
    235 ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
    236 
    237 //
    238 // Conversions from/to other time types.
    239 //
    240 
    241 absl::Time FromUDate(double udate) {
    242  return time_internal::FromUnixDuration(absl::Milliseconds(udate));
    243 }
    244 
    245 absl::Time FromUniversal(int64_t universal) {
    246  return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
    247 }
    248 
    249 int64_t ToUnixNanos(Time t) {
    250  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
    251      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
    252    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
    253            1000 * 1000 * 1000) +
    254           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4);
    255  }
    256  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Nanoseconds(1));
    257 }
    258 
    259 int64_t ToUnixMicros(Time t) {
    260  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
    261      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) {
    262    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) *
    263            1000 * 1000) +
    264           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000);
    265  }
    266  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Microseconds(1));
    267 }
    268 
    269 int64_t ToUnixMillis(Time t) {
    270  if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
    271      time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) {
    272    return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) +
    273           (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) /
    274            (4000 * 1000));
    275  }
    276  return FloorToUnit(time_internal::ToUnixDuration(t), absl::Milliseconds(1));
    277 }
    278 
    279 int64_t ToUnixSeconds(Time t) {
    280  return time_internal::GetRepHi(time_internal::ToUnixDuration(t));
    281 }
    282 
    283 time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
    284 
    285 double ToUDate(Time t) {
    286  return absl::FDivDuration(time_internal::ToUnixDuration(t),
    287                            absl::Milliseconds(1));
    288 }
    289 
    290 int64_t ToUniversal(absl::Time t) {
    291  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
    292 }
    293 
    294 absl::Time TimeFromTimespec(timespec ts) {
    295  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
    296 }
    297 
    298 absl::Time TimeFromTimeval(timeval tv) {
    299  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
    300 }
    301 
    302 timespec ToTimespec(Time t) {
    303  timespec ts;
    304  absl::Duration d = time_internal::ToUnixDuration(t);
    305  if (!time_internal::IsInfiniteDuration(d)) {
    306    ts.tv_sec = static_cast<decltype(ts.tv_sec)>(time_internal::GetRepHi(d));
    307    if (ts.tv_sec == time_internal::GetRepHi(d)) {  // no time_t narrowing
    308      ts.tv_nsec = time_internal::GetRepLo(d) / 4;  // floor
    309      return ts;
    310    }
    311  }
    312  if (d >= absl::ZeroDuration()) {
    313    ts.tv_sec = std::numeric_limits<time_t>::max();
    314    ts.tv_nsec = 1000 * 1000 * 1000 - 1;
    315  } else {
    316    ts.tv_sec = std::numeric_limits<time_t>::min();
    317    ts.tv_nsec = 0;
    318  }
    319  return ts;
    320 }
    321 
    322 timeval ToTimeval(Time t) {
    323  timeval tv;
    324  timespec ts = absl::ToTimespec(t);
    325  tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);
    326  if (tv.tv_sec != ts.tv_sec) {  // narrowing
    327    if (ts.tv_sec < 0) {
    328      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
    329      tv.tv_usec = 0;
    330    } else {
    331      tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
    332      tv.tv_usec = 1000 * 1000 - 1;
    333    }
    334    return tv;
    335  }
    336  tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);  // suseconds_t
    337  return tv;
    338 }
    339 
    340 Time FromChrono(const std::chrono::system_clock::time_point& tp) {
    341  return time_internal::FromUnixDuration(time_internal::FromChrono(
    342      tp - std::chrono::system_clock::from_time_t(0)));
    343 }
    344 
    345 std::chrono::system_clock::time_point ToChronoTime(absl::Time t) {
    346  using D = std::chrono::system_clock::duration;
    347  auto d = time_internal::ToUnixDuration(t);
    348  if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1}));
    349  return std::chrono::system_clock::from_time_t(0) +
    350         time_internal::ToChronoDuration<D>(d);
    351 }
    352 
    353 //
    354 // TimeZone
    355 //
    356 
    357 absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
    358  if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
    359  if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
    360 
    361  const auto ud = time_internal::ToUnixDuration(t);
    362  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
    363  const auto al = cz_.lookup(tp);
    364 
    365  TimeZone::CivilInfo ci;
    366  ci.cs = CivilSecond(al.cs);
    367  ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
    368  ci.offset = al.offset;
    369  ci.is_dst = al.is_dst;
    370  ci.zone_abbr = al.abbr;
    371  return ci;
    372 }
    373 
    374 absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
    375  const cctz::civil_second cs(ct);
    376  const auto cl = cz_.lookup(cs);
    377 
    378  TimeZone::TimeInfo ti;
    379  switch (cl.kind) {
    380    case cctz::time_zone::civil_lookup::UNIQUE:
    381      ti.kind = TimeZone::TimeInfo::UNIQUE;
    382      break;
    383    case cctz::time_zone::civil_lookup::SKIPPED:
    384      ti.kind = TimeZone::TimeInfo::SKIPPED;
    385      break;
    386    case cctz::time_zone::civil_lookup::REPEATED:
    387      ti.kind = TimeZone::TimeInfo::REPEATED;
    388      break;
    389  }
    390  ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
    391  ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
    392  ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
    393  return ti;
    394 }
    395 
    396 bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
    397  return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
    398 }
    399 
    400 bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
    401  return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
    402 }
    403 
    404 //
    405 // Conversions involving time zones.
    406 //
    407 ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
    408 absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
    409                                     int min, int sec, TimeZone tz) {
    410  // Avoids years that are too extreme for CivilSecond to normalize.
    411  if (year > 300000000000) return InfiniteFutureTimeConversion();
    412  if (year < -300000000000) return InfinitePastTimeConversion();
    413 
    414  const CivilSecond cs(year, mon, day, hour, min, sec);
    415  const auto ti = tz.At(cs);
    416 
    417  TimeConversion tc;
    418  tc.pre = ti.pre;
    419  tc.trans = ti.trans;
    420  tc.post = ti.post;
    421  switch (ti.kind) {
    422    case TimeZone::TimeInfo::UNIQUE:
    423      tc.kind = TimeConversion::UNIQUE;
    424      break;
    425    case TimeZone::TimeInfo::SKIPPED:
    426      tc.kind = TimeConversion::SKIPPED;
    427      break;
    428    case TimeZone::TimeInfo::REPEATED:
    429      tc.kind = TimeConversion::REPEATED;
    430      break;
    431  }
    432  tc.normalized = false;
    433  if (year != cs.year() || mon != cs.month() || day != cs.day() ||
    434      hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
    435    tc.normalized = true;
    436  }
    437  return tc;
    438 }
    439 ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
    440 
    441 absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
    442  civil_year_t tm_year = tm.tm_year;
    443  // Avoids years that are too extreme for CivilSecond to normalize.
    444  if (tm_year > 300000000000ll) return InfiniteFuture();
    445  if (tm_year < -300000000000ll) return InfinitePast();
    446  int tm_mon = tm.tm_mon;
    447  if (tm_mon == std::numeric_limits<int>::max()) {
    448    tm_mon -= 12;
    449    tm_year += 1;
    450  }
    451  const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
    452                                    tm.tm_hour, tm.tm_min, tm.tm_sec));
    453  return tm.tm_isdst == 0 ? ti.post : ti.pre;
    454 }
    455 
    456 struct tm ToTM(absl::Time t, absl::TimeZone tz) {
    457  struct tm tm = {};
    458 
    459  const auto ci = tz.At(t);
    460  const auto& cs = ci.cs;
    461  tm.tm_sec = cs.second();
    462  tm.tm_min = cs.minute();
    463  tm.tm_hour = cs.hour();
    464  tm.tm_mday = cs.day();
    465  tm.tm_mon = cs.month() - 1;
    466 
    467  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
    468  // that tm.tm_year is years since 1900.
    469  if (cs.year() < std::numeric_limits<int>::min() + 1900) {
    470    tm.tm_year = std::numeric_limits<int>::min();
    471  } else if (cs.year() > std::numeric_limits<int>::max()) {
    472    tm.tm_year = std::numeric_limits<int>::max() - 1900;
    473  } else {
    474    tm.tm_year = static_cast<int>(cs.year() - 1900);
    475  }
    476 
    477  switch (GetWeekday(cs)) {
    478    case Weekday::sunday:
    479      tm.tm_wday = 0;
    480      break;
    481    case Weekday::monday:
    482      tm.tm_wday = 1;
    483      break;
    484    case Weekday::tuesday:
    485      tm.tm_wday = 2;
    486      break;
    487    case Weekday::wednesday:
    488      tm.tm_wday = 3;
    489      break;
    490    case Weekday::thursday:
    491      tm.tm_wday = 4;
    492      break;
    493    case Weekday::friday:
    494      tm.tm_wday = 5;
    495      break;
    496    case Weekday::saturday:
    497      tm.tm_wday = 6;
    498      break;
    499  }
    500  tm.tm_yday = GetYearDay(cs) - 1;
    501  tm.tm_isdst = ci.is_dst ? 1 : 0;
    502 
    503  return tm;
    504 }
    505 
    506 ABSL_NAMESPACE_END
    507 }  // namespace absl