Home | History | Annotate | Download | only in util
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #include <google/protobuf/util/time_util.h>
     32 
     33 #include <google/protobuf/stubs/time.h>
     34 #include <google/protobuf/stubs/int128.h>
     35 #include <google/protobuf/stubs/strutil.h>
     36 #include <google/protobuf/stubs/stringprintf.h>
     37 #include <google/protobuf/duration.pb.h>
     38 #include <google/protobuf/timestamp.pb.h>
     39 
     40 namespace google {
     41 namespace protobuf {
     42 namespace util {
     43 
     44 using google::protobuf::Timestamp;
     45 using google::protobuf::Duration;
     46 
     47 namespace {
     48 static const int kNanosPerSecond = 1000000000;
     49 static const int kMicrosPerSecond = 1000000;
     50 static const int kMillisPerSecond = 1000;
     51 static const int kNanosPerMillisecond = 1000000;
     52 static const int kMicrosPerMillisecond = 1000;
     53 static const int kNanosPerMicrosecond = 1000;
     54 static const int kSecondsPerMinute = 60;  // Note that we ignore leap seconds.
     55 static const int kSecondsPerHour = 3600;
     56 static const char kTimestampFormat[] = "%E4Y-%m-%dT%H:%M:%S";
     57 
     58 template <typename T>
     59 T CreateNormalized(int64 seconds, int64 nanos);
     60 
     61 template <>
     62 Timestamp CreateNormalized(int64 seconds, int64 nanos) {
     63   // Make sure nanos is in the range.
     64   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     65     seconds += nanos / kNanosPerSecond;
     66     nanos = nanos % kNanosPerSecond;
     67   }
     68   // For Timestamp nanos should be in the range [0, 999999999]
     69   if (nanos < 0) {
     70     seconds -= 1;
     71     nanos += kNanosPerSecond;
     72   }
     73   GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
     74          seconds <= TimeUtil::kTimestampMaxSeconds);
     75   Timestamp result;
     76   result.set_seconds(seconds);
     77   result.set_nanos(static_cast<int32>(nanos));
     78   return result;
     79 }
     80 
     81 template <>
     82 Duration CreateNormalized(int64 seconds, int64 nanos) {
     83   // Make sure nanos is in the range.
     84   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     85     seconds += nanos / kNanosPerSecond;
     86     nanos = nanos % kNanosPerSecond;
     87   }
     88   // nanos should have the same sign as seconds.
     89   if (seconds < 0 && nanos > 0) {
     90     seconds += 1;
     91     nanos -= kNanosPerSecond;
     92   } else if (seconds > 0 && nanos < 0) {
     93     seconds -= 1;
     94     nanos += kNanosPerSecond;
     95   }
     96   GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
     97          seconds <= TimeUtil::kDurationMaxSeconds);
     98   Duration result;
     99   result.set_seconds(seconds);
    100   result.set_nanos(static_cast<int32>(nanos));
    101   return result;
    102 }
    103 
    104 // Format nanoseconds with either 3, 6, or 9 digits depending on the required
    105 // precision to represent the exact value.
    106 string FormatNanos(int32 nanos) {
    107   if (nanos % kNanosPerMillisecond == 0) {
    108     return StringPrintf("%03d", nanos / kNanosPerMillisecond);
    109   } else if (nanos % kNanosPerMicrosecond == 0) {
    110     return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
    111   } else {
    112     return StringPrintf("%09d", nanos);
    113   }
    114 }
    115 
    116 string FormatTime(int64 seconds, int32 nanos) {
    117   return ::google::protobuf::internal::FormatTime(seconds, nanos);
    118 }
    119 
    120 bool ParseTime(const string& value, int64* seconds, int32* nanos) {
    121   return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
    122 }
    123 
    124 void CurrentTime(int64* seconds, int32* nanos) {
    125   return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
    126 }
    127 
    128 // Truncates the remainder part after division.
    129 int64 RoundTowardZero(int64 value, int64 divider) {
    130   int64 result = value / divider;
    131   int64 remainder = value % divider;
    132   // Before C++11, the sign of the remainder is implementation dependent if
    133   // any of the operands is negative. Here we try to enforce C++11's "rounded
    134   // toward zero" semantics. For example, for (-5) / 2 an implementation may
    135   // give -3 as the result with the remainder being 1. This function ensures
    136   // we always return -2 (closer to zero) regardless of the implementation.
    137   if (result < 0 && remainder > 0) {
    138     return result + 1;
    139   } else {
    140     return result;
    141   }
    142 }
    143 }  // namespace
    144 
    145 string TimeUtil::ToString(const Timestamp& timestamp) {
    146   return FormatTime(timestamp.seconds(), timestamp.nanos());
    147 }
    148 
    149 bool TimeUtil::FromString(const string& value, Timestamp* timestamp) {
    150   int64 seconds;
    151   int32 nanos;
    152   if (!ParseTime(value, &seconds, &nanos)) {
    153     return false;
    154   }
    155   *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
    156   return true;
    157 }
    158 
    159 Timestamp TimeUtil::GetCurrentTime() {
    160   int64 seconds;
    161   int32 nanos;
    162   CurrentTime(&seconds, &nanos);
    163   return CreateNormalized<Timestamp>(seconds, nanos);
    164 }
    165 
    166 Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
    167 
    168 string TimeUtil::ToString(const Duration& duration) {
    169   string result;
    170   int64 seconds = duration.seconds();
    171   int32 nanos = duration.nanos();
    172   if (seconds < 0 || nanos < 0) {
    173     result += "-";
    174     seconds = -seconds;
    175     nanos = -nanos;
    176   }
    177   result += StringPrintf("%" GOOGLE_LL_FORMAT "d", seconds);
    178   if (nanos != 0) {
    179     result += "." + FormatNanos(nanos);
    180   }
    181   result += "s";
    182   return result;
    183 }
    184 
    185 static int64 Pow(int64 x, int y) {
    186   int64 result = 1;
    187   for (int i = 0; i < y; ++i) {
    188     result *= x;
    189   }
    190   return result;
    191 }
    192 
    193 bool TimeUtil::FromString(const string& value, Duration* duration) {
    194   if (value.length() <= 1 || value[value.length() - 1] != 's') {
    195     return false;
    196   }
    197   bool negative = (value[0] == '-');
    198   int sign_length = (negative ? 1 : 0);
    199   // Parse the duration value as two integers rather than a float value
    200   // to avoid precision loss.
    201   string seconds_part, nanos_part;
    202   size_t pos = value.find_last_of(".");
    203   if (pos == string::npos) {
    204     seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
    205     nanos_part = "0";
    206   } else {
    207     seconds_part = value.substr(sign_length, pos - sign_length);
    208     nanos_part = value.substr(pos + 1, value.length() - pos - 2);
    209   }
    210   char* end;
    211   int64 seconds = strto64(seconds_part.c_str(), &end, 10);
    212   if (end != seconds_part.c_str() + seconds_part.length()) {
    213     return false;
    214   }
    215   int64 nanos = strto64(nanos_part.c_str(), &end, 10);
    216   if (end != nanos_part.c_str() + nanos_part.length()) {
    217     return false;
    218   }
    219   nanos = nanos * Pow(10, 9 - nanos_part.length());
    220   if (negative) {
    221     // If a Duration is negative, both seconds and nanos should be negative.
    222     seconds = -seconds;
    223     nanos = -nanos;
    224   }
    225   duration->set_seconds(seconds);
    226   duration->set_nanos(static_cast<int32>(nanos));
    227   return true;
    228 }
    229 
    230 Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
    231   return CreateNormalized<Duration>(nanos / kNanosPerSecond,
    232                                     nanos % kNanosPerSecond);
    233 }
    234 
    235 Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
    236   return CreateNormalized<Duration>(
    237       micros / kMicrosPerSecond,
    238       (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
    239 }
    240 
    241 Duration TimeUtil::MillisecondsToDuration(int64 millis) {
    242   return CreateNormalized<Duration>(
    243       millis / kMillisPerSecond,
    244       (millis % kMillisPerSecond) * kNanosPerMillisecond);
    245 }
    246 
    247 Duration TimeUtil::SecondsToDuration(int64 seconds) {
    248   return CreateNormalized<Duration>(seconds, 0);
    249 }
    250 
    251 Duration TimeUtil::MinutesToDuration(int64 minutes) {
    252   return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
    253 }
    254 
    255 Duration TimeUtil::HoursToDuration(int64 hours) {
    256   return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
    257 }
    258 
    259 int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
    260   return duration.seconds() * kNanosPerSecond + duration.nanos();
    261 }
    262 
    263 int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
    264   return duration.seconds() * kMicrosPerSecond +
    265          RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
    266 }
    267 
    268 int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
    269   return duration.seconds() * kMillisPerSecond +
    270          RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
    271 }
    272 
    273 int64 TimeUtil::DurationToSeconds(const Duration& duration) {
    274   return duration.seconds();
    275 }
    276 
    277 int64 TimeUtil::DurationToMinutes(const Duration& duration) {
    278   return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
    279 }
    280 
    281 int64 TimeUtil::DurationToHours(const Duration& duration) {
    282   return RoundTowardZero(duration.seconds(), kSecondsPerHour);
    283 }
    284 
    285 Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
    286   return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
    287                                      nanos % kNanosPerSecond);
    288 }
    289 
    290 Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
    291   return CreateNormalized<Timestamp>(
    292       micros / kMicrosPerSecond,
    293       micros % kMicrosPerSecond * kNanosPerMicrosecond);
    294 }
    295 
    296 Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
    297   return CreateNormalized<Timestamp>(
    298       millis / kMillisPerSecond,
    299       millis % kMillisPerSecond * kNanosPerMillisecond);
    300 }
    301 
    302 Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
    303   return CreateNormalized<Timestamp>(seconds, 0);
    304 }
    305 
    306 int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
    307   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
    308 }
    309 
    310 int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
    311   return timestamp.seconds() * kMicrosPerSecond +
    312          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
    313 }
    314 
    315 int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
    316   return timestamp.seconds() * kMillisPerSecond +
    317          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
    318 }
    319 
    320 int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
    321   return timestamp.seconds();
    322 }
    323 
    324 Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
    325   return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
    326 }
    327 
    328 time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
    329   return static_cast<time_t>(value.seconds());
    330 }
    331 
    332 Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
    333   return CreateNormalized<Timestamp>(value.tv_sec,
    334                                      value.tv_usec * kNanosPerMicrosecond);
    335 }
    336 
    337 timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
    338   timeval result;
    339   result.tv_sec = value.seconds();
    340   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
    341   return result;
    342 }
    343 
    344 Duration TimeUtil::TimevalToDuration(const timeval& value) {
    345   return CreateNormalized<Duration>(value.tv_sec,
    346                                     value.tv_usec * kNanosPerMicrosecond);
    347 }
    348 
    349 timeval TimeUtil::DurationToTimeval(const Duration& value) {
    350   timeval result;
    351   result.tv_sec = value.seconds();
    352   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
    353   // timeval.tv_usec's range is [0, 1000000)
    354   if (result.tv_usec < 0) {
    355     result.tv_sec -= 1;
    356     result.tv_usec += kMicrosPerSecond;
    357   }
    358   return result;
    359 }
    360 
    361 }  // namespace util
    362 }  // namespace protobuf
    363 
    364 
    365 namespace protobuf {
    366 namespace {
    367 using google::protobuf::util::kNanosPerSecond;
    368 using google::protobuf::util::CreateNormalized;
    369 
    370 // Convert a Timestamp to uint128.
    371 void ToUint128(const Timestamp& value, uint128* result, bool* negative) {
    372   if (value.seconds() < 0) {
    373     *negative = true;
    374     *result = static_cast<uint64>(-value.seconds());
    375     *result = *result * kNanosPerSecond - static_cast<uint32>(value.nanos());
    376   } else {
    377     *negative = false;
    378     *result = static_cast<uint64>(value.seconds());
    379     *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
    380   }
    381 }
    382 
    383 // Convert a Duration to uint128.
    384 void ToUint128(const Duration& value, uint128* result, bool* negative) {
    385   if (value.seconds() < 0 || value.nanos() < 0) {
    386     *negative = true;
    387     *result = static_cast<uint64>(-value.seconds());
    388     *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
    389   } else {
    390     *negative = false;
    391     *result = static_cast<uint64>(value.seconds());
    392     *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
    393   }
    394 }
    395 
    396 void ToTimestamp(const uint128& value, bool negative, Timestamp* timestamp) {
    397   int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
    398   int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
    399   if (negative) {
    400     seconds = -seconds;
    401     nanos = -nanos;
    402     if (nanos < 0) {
    403       nanos += kNanosPerSecond;
    404       seconds -= 1;
    405     }
    406   }
    407   timestamp->set_seconds(seconds);
    408   timestamp->set_nanos(nanos);
    409 }
    410 
    411 void ToDuration(const uint128& value, bool negative, Duration* duration) {
    412   int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
    413   int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
    414   if (negative) {
    415     seconds = -seconds;
    416     nanos = -nanos;
    417   }
    418   duration->set_seconds(seconds);
    419   duration->set_nanos(nanos);
    420 }
    421 }  // namespace
    422 
    423 Duration& operator+=(Duration& d1, const Duration& d2) {
    424   d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
    425                                   d1.nanos() + d2.nanos());
    426   return d1;
    427 }
    428 
    429 Duration& operator-=(Duration& d1, const Duration& d2) {  // NOLINT
    430   d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
    431                                   d1.nanos() - d2.nanos());
    432   return d1;
    433 }
    434 
    435 Duration& operator*=(Duration& d, int64 r) {  // NOLINT
    436   bool negative;
    437   uint128 value;
    438   ToUint128(d, &value, &negative);
    439   if (r > 0) {
    440     value *= static_cast<uint64>(r);
    441   } else {
    442     negative = !negative;
    443     value *= static_cast<uint64>(-r);
    444   }
    445   ToDuration(value, negative, &d);
    446   return d;
    447 }
    448 
    449 Duration& operator*=(Duration& d, double r) {  // NOLINT
    450   double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
    451   int64 seconds = static_cast<int64>(result);
    452   int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
    453   // Note that we normalize here not just because nanos can have a different
    454   // sign from seconds but also that nanos can be any arbitrary value when
    455   // overflow happens (i.e., the result is a much larger value than what
    456   // int64 can represent).
    457   d = CreateNormalized<Duration>(seconds, nanos);
    458   return d;
    459 }
    460 
    461 Duration& operator/=(Duration& d, int64 r) {  // NOLINT
    462   bool negative;
    463   uint128 value;
    464   ToUint128(d, &value, &negative);
    465   if (r > 0) {
    466     value /= static_cast<uint64>(r);
    467   } else {
    468     negative = !negative;
    469     value /= static_cast<uint64>(-r);
    470   }
    471   ToDuration(value, negative, &d);
    472   return d;
    473 }
    474 
    475 Duration& operator/=(Duration& d, double r) {  // NOLINT
    476   return d *= 1.0 / r;
    477 }
    478 
    479 Duration& operator%=(Duration& d1, const Duration& d2) {  // NOLINT
    480   bool negative1, negative2;
    481   uint128 value1, value2;
    482   ToUint128(d1, &value1, &negative1);
    483   ToUint128(d2, &value2, &negative2);
    484   uint128 result = value1 % value2;
    485   // When negative values are involved in division, we round the division
    486   // result towards zero. With this semantics, sign of the remainder is the
    487   // same as the dividend. For example:
    488   //     -5 / 10    = 0, -5 % 10    = -5
    489   //     -5 / (-10) = 0, -5 % (-10) = -5
    490   //      5 / (-10) = 0,  5 % (-10) = 5
    491   ToDuration(result, negative1, &d1);
    492   return d1;
    493 }
    494 
    495 int64 operator/(const Duration& d1, const Duration& d2) {
    496   bool negative1, negative2;
    497   uint128 value1, value2;
    498   ToUint128(d1, &value1, &negative1);
    499   ToUint128(d2, &value2, &negative2);
    500   int64 result = Uint128Low64(value1 / value2);
    501   if (negative1 != negative2) {
    502     result = -result;
    503   }
    504   return result;
    505 }
    506 
    507 Timestamp& operator+=(Timestamp& t, const Duration& d) {  // NOLINT
    508   t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
    509                                   t.nanos() + d.nanos());
    510   return t;
    511 }
    512 
    513 Timestamp& operator-=(Timestamp& t, const Duration& d) {  // NOLINT
    514   t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
    515                                   t.nanos() - d.nanos());
    516   return t;
    517 }
    518 
    519 Duration operator-(const Timestamp& t1, const Timestamp& t2) {
    520   return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
    521                                     t1.nanos() - t2.nanos());
    522 }
    523 }  // namespace protobuf
    524 
    525 }  // namespace google
    526