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