tor-browser

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

time_zone_fixed.cc (4434B)


      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 #include "absl/time/internal/cctz/src/time_zone_fixed.h"
     16 
     17 #include <algorithm>
     18 #include <cassert>
     19 #include <chrono>
     20 #include <cstring>
     21 #include <string>
     22 
     23 #include "absl/base/config.h"
     24 
     25 namespace absl {
     26 ABSL_NAMESPACE_BEGIN
     27 namespace time_internal {
     28 namespace cctz {
     29 
     30 namespace {
     31 
     32 // The prefix used for the internal names of fixed-offset zones.
     33 const char kFixedZonePrefix[] = "Fixed/UTC";
     34 
     35 const char kDigits[] = "0123456789";
     36 
     37 char* Format02d(char* p, int v) {
     38  *p++ = kDigits[(v / 10) % 10];
     39  *p++ = kDigits[v % 10];
     40  return p;
     41 }
     42 
     43 int Parse02d(const char* p) {
     44  if (const char* ap = std::strchr(kDigits, *p)) {
     45    int v = static_cast<int>(ap - kDigits);
     46    if (const char* bp = std::strchr(kDigits, *++p)) {
     47      return (v * 10) + static_cast<int>(bp - kDigits);
     48    }
     49  }
     50  return -1;
     51 }
     52 
     53 }  // namespace
     54 
     55 bool FixedOffsetFromName(const std::string& name, seconds* offset) {
     56  if (name == "UTC" || name == "UTC0") {
     57    *offset = seconds::zero();
     58    return true;
     59  }
     60 
     61  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
     62  const char* const ep = kFixedZonePrefix + prefix_len;
     63  if (name.size() != prefix_len + 9)  // <prefix>+99:99:99
     64    return false;
     65  if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;
     66  const char* np = name.data() + prefix_len;
     67  if (np[0] != '+' && np[0] != '-') return false;
     68  if (np[3] != ':' || np[6] != ':')  // see note below about large offsets
     69    return false;
     70 
     71  int hours = Parse02d(np + 1);
     72  if (hours == -1) return false;
     73  int mins = Parse02d(np + 4);
     74  if (mins == -1) return false;
     75  int secs = Parse02d(np + 7);
     76  if (secs == -1) return false;
     77 
     78  secs += ((hours * 60) + mins) * 60;
     79  if (secs > 24 * 60 * 60) return false;  // outside supported offset range
     80  *offset = seconds(secs * (np[0] == '-' ? -1 : 1));  // "-" means west
     81  return true;
     82 }
     83 
     84 std::string FixedOffsetToName(const seconds& offset) {
     85  if (offset == seconds::zero()) return "UTC";
     86  if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) {
     87    // We don't support fixed-offset zones more than 24 hours
     88    // away from UTC to avoid complications in rendering such
     89    // offsets and to (somewhat) limit the total number of zones.
     90    return "UTC";
     91  }
     92  int offset_seconds = static_cast<int>(offset.count());
     93  const char sign = (offset_seconds < 0 ? '-' : '+');
     94  int offset_minutes = offset_seconds / 60;
     95  offset_seconds %= 60;
     96  if (sign == '-') {
     97    if (offset_seconds > 0) {
     98      offset_seconds -= 60;
     99      offset_minutes += 1;
    100    }
    101    offset_seconds = -offset_seconds;
    102    offset_minutes = -offset_minutes;
    103  }
    104  int offset_hours = offset_minutes / 60;
    105  offset_minutes %= 60;
    106  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
    107  char buf[prefix_len + sizeof("-24:00:00")];
    108  char* ep = std::copy_n(kFixedZonePrefix, prefix_len, buf);
    109  *ep++ = sign;
    110  ep = Format02d(ep, offset_hours);
    111  *ep++ = ':';
    112  ep = Format02d(ep, offset_minutes);
    113  *ep++ = ':';
    114  ep = Format02d(ep, offset_seconds);
    115  *ep++ = '\0';
    116  assert(ep == buf + sizeof(buf));
    117  return buf;
    118 }
    119 
    120 std::string FixedOffsetToAbbr(const seconds& offset) {
    121  std::string abbr = FixedOffsetToName(offset);
    122  const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
    123  if (abbr.size() == prefix_len + 9) {         // <prefix>+99:99:99
    124    abbr.erase(0, prefix_len);                 // +99:99:99
    125    abbr.erase(6, 1);                          // +99:9999
    126    abbr.erase(3, 1);                          // +999999
    127    if (abbr[5] == '0' && abbr[6] == '0') {    // +999900
    128      abbr.erase(5, 2);                        // +9999
    129      if (abbr[3] == '0' && abbr[4] == '0') {  // +9900
    130        abbr.erase(3, 2);                      // +99
    131      }
    132    }
    133  }
    134  return abbr;
    135 }
    136 
    137 }  // namespace cctz
    138 }  // namespace time_internal
    139 ABSL_NAMESPACE_END
    140 }  // namespace absl