Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "time_zone_fixed.h"
00016
00017 #include <algorithm>
00018 #include <cassert>
00019 #include <chrono>
00020 #include <cstring>
00021 #include <string>
00022
00023 namespace absl {
00024 namespace time_internal {
00025 namespace cctz {
00026
00027 namespace {
00028
00029
00030 const char kFixedOffsetPrefix[] = "Fixed/UTC";
00031
00032 const char kDigits[] = "0123456789";
00033
00034 char* Format02d(char* p, int v) {
00035 *p++ = kDigits[(v / 10) % 10];
00036 *p++ = kDigits[v % 10];
00037 return p;
00038 }
00039
00040 int Parse02d(const char* p) {
00041 if (const char* ap = std::strchr(kDigits, *p)) {
00042 int v = static_cast<int>(ap - kDigits);
00043 if (const char* bp = std::strchr(kDigits, *++p)) {
00044 return (v * 10) + static_cast<int>(bp - kDigits);
00045 }
00046 }
00047 return -1;
00048 }
00049
00050 }
00051
00052 bool FixedOffsetFromName(const std::string& name, seconds* offset) {
00053 if (name.compare(0, std::string::npos, "UTC", 3) == 0) {
00054 *offset = seconds::zero();
00055 return true;
00056 }
00057
00058 const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
00059 const char* const ep = kFixedOffsetPrefix + prefix_len;
00060 if (name.size() != prefix_len + 9)
00061 return false;
00062 if (!std::equal(kFixedOffsetPrefix, ep, name.begin()))
00063 return false;
00064 const char* np = name.data() + prefix_len;
00065 if (np[0] != '+' && np[0] != '-')
00066 return false;
00067 if (np[3] != ':' || np[6] != ':')
00068 return false;
00069
00070 int hours = Parse02d(np + 1);
00071 if (hours == -1) return false;
00072 int mins = Parse02d(np + 4);
00073 if (mins == -1) return false;
00074 int secs = Parse02d(np + 7);
00075 if (secs == -1) return false;
00076
00077 secs += ((hours * 60) + mins) * 60;
00078 if (secs > 24 * 60 * 60) return false;
00079 *offset = seconds(secs * (np[0] == '-' ? -1 : 1));
00080 return true;
00081 }
00082
00083 std::string FixedOffsetToName(const seconds& offset) {
00084 if (offset == seconds::zero()) return "UTC";
00085 if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) {
00086
00087
00088
00089 return "UTC";
00090 }
00091 int seconds = static_cast<int>(offset.count());
00092 const char sign = (seconds < 0 ? '-' : '+');
00093 int minutes = seconds / 60;
00094 seconds %= 60;
00095 if (sign == '-') {
00096 if (seconds > 0) {
00097 seconds -= 60;
00098 minutes += 1;
00099 }
00100 seconds = -seconds;
00101 minutes = -minutes;
00102 }
00103 int hours = minutes / 60;
00104 minutes %= 60;
00105 char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
00106 std::strcpy(buf, kFixedOffsetPrefix);
00107 char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
00108 *ep++ = sign;
00109 ep = Format02d(ep, hours);
00110 *ep++ = ':';
00111 ep = Format02d(ep, minutes);
00112 *ep++ = ':';
00113 ep = Format02d(ep, seconds);
00114 *ep++ = '\0';
00115 assert(ep == buf + sizeof(buf));
00116 return buf;
00117 }
00118
00119 std::string FixedOffsetToAbbr(const seconds& offset) {
00120 std::string abbr = FixedOffsetToName(offset);
00121 const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
00122 if (abbr.size() == prefix_len + 9) {
00123 abbr.erase(0, prefix_len);
00124 abbr.erase(6, 1);
00125 abbr.erase(3, 1);
00126 if (abbr[5] == '0' && abbr[6] == '0') {
00127 abbr.erase(5, 2);
00128 if (abbr[3] == '0' && abbr[4] == '0') {
00129 abbr.erase(3, 2);
00130 }
00131 }
00132 }
00133 return abbr;
00134 }
00135
00136 }
00137 }
00138 }