00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <algorithm>
00053 #include <cassert>
00054 #include <cctype>
00055 #include <cerrno>
00056 #include <cmath>
00057 #include <cstdint>
00058 #include <cstdlib>
00059 #include <cstring>
00060 #include <ctime>
00061 #include <functional>
00062 #include <limits>
00063 #include <string>
00064
00065 #include "absl/base/casts.h"
00066 #include "absl/numeric/int128.h"
00067 #include "absl/time/time.h"
00068
00069 namespace absl {
00070
00071 namespace {
00072
00073 using time_internal::kTicksPerNanosecond;
00074 using time_internal::kTicksPerSecond;
00075
00076 constexpr int64_t kint64max = std::numeric_limits<int64_t>::max();
00077 constexpr int64_t kint64min = std::numeric_limits<int64_t>::min();
00078
00079
00080 inline bool IsFinite(double d) {
00081 if (std::isnan(d)) return false;
00082 return d != std::numeric_limits<double>::infinity() &&
00083 d != -std::numeric_limits<double>::infinity();
00084 }
00085
00086 inline bool IsValidDivisor(double d) {
00087 if (std::isnan(d)) return false;
00088 return d != 0.0;
00089 }
00090
00091
00092
00093 template <typename Double>
00094 inline double Round(Double d) {
00095 return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5);
00096 }
00097
00098
00099
00100
00101 inline void NormalizeTicks(int64_t* sec, int64_t* ticks) {
00102 if (*ticks < 0) {
00103 --*sec;
00104 *ticks += kTicksPerSecond;
00105 }
00106 }
00107
00108
00109 inline uint128 MakeU128(int64_t a) {
00110 uint128 u128 = 0;
00111 if (a < 0) {
00112 ++u128;
00113 ++a;
00114 a = -a;
00115 }
00116 u128 += static_cast<uint64_t>(a);
00117 return u128;
00118 }
00119
00120
00121 inline uint128 MakeU128Ticks(Duration d) {
00122 int64_t rep_hi = time_internal::GetRepHi(d);
00123 uint32_t rep_lo = time_internal::GetRepLo(d);
00124 if (rep_hi < 0) {
00125 ++rep_hi;
00126 rep_hi = -rep_hi;
00127 rep_lo = kTicksPerSecond - rep_lo;
00128 }
00129 uint128 u128 = static_cast<uint64_t>(rep_hi);
00130 u128 *= static_cast<uint64_t>(kTicksPerSecond);
00131 u128 += rep_lo;
00132 return u128;
00133 }
00134
00135
00136 inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) {
00137 int64_t rep_hi;
00138 uint32_t rep_lo;
00139 const uint64_t h64 = Uint128High64(u128);
00140 const uint64_t l64 = Uint128Low64(u128);
00141 if (h64 == 0) {
00142 const uint64_t hi = l64 / kTicksPerSecond;
00143 rep_hi = static_cast<int64_t>(hi);
00144 rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond);
00145 } else {
00146
00147
00148
00149
00150
00151 const uint64_t kMaxRepHi64 = 0x77359400UL;
00152 if (h64 >= kMaxRepHi64) {
00153 if (is_neg && h64 == kMaxRepHi64 && l64 == 0) {
00154
00155 return time_internal::MakeDuration(kint64min);
00156 }
00157 return is_neg ? -InfiniteDuration() : InfiniteDuration();
00158 }
00159 const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond);
00160 const uint128 hi = u128 / kTicksPerSecond128;
00161 rep_hi = static_cast<int64_t>(Uint128Low64(hi));
00162 rep_lo =
00163 static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128));
00164 }
00165 if (is_neg) {
00166 rep_hi = -rep_hi;
00167 if (rep_lo != 0) {
00168 --rep_hi;
00169 rep_lo = kTicksPerSecond - rep_lo;
00170 }
00171 }
00172 return time_internal::MakeDuration(rep_hi, rep_lo);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 inline uint64_t EncodeTwosComp(int64_t v) {
00184 return absl::bit_cast<uint64_t>(v);
00185 }
00186 inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); }
00187
00188
00189
00190
00191
00192
00193
00194 inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {
00195 double c = a_hi + b_hi;
00196 if (c >= kint64max) {
00197 *d = InfiniteDuration();
00198 return false;
00199 }
00200 if (c <= kint64min) {
00201 *d = -InfiniteDuration();
00202 return false;
00203 }
00204 *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d));
00205 return true;
00206 }
00207
00208
00209
00210 template <typename Ignored>
00211 struct SafeMultiply {
00212 uint128 operator()(uint128 a, uint128 b) const {
00213
00214 assert(Uint128High64(b) == 0);
00215
00216 if (Uint128High64(a) == 0) {
00217 return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0)
00218 ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b))
00219 : a * b;
00220 }
00221 return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b;
00222 }
00223 };
00224
00225
00226
00227 template <template <typename> class Operation>
00228 inline Duration ScaleFixed(Duration d, int64_t r) {
00229 const uint128 a = MakeU128Ticks(d);
00230 const uint128 b = MakeU128(r);
00231 const uint128 q = Operation<uint128>()(a, b);
00232 const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0);
00233 return MakeDurationFromU128(q, is_neg);
00234 }
00235
00236
00237
00238 template <template <typename> class Operation>
00239 inline Duration ScaleDouble(Duration d, double r) {
00240 Operation<double> op;
00241 double hi_doub = op(time_internal::GetRepHi(d), r);
00242 double lo_doub = op(time_internal::GetRepLo(d), r);
00243
00244 double hi_int = 0;
00245 double hi_frac = std::modf(hi_doub, &hi_int);
00246
00247
00248 lo_doub /= kTicksPerSecond;
00249 lo_doub += hi_frac;
00250
00251 double lo_int = 0;
00252 double lo_frac = std::modf(lo_doub, &lo_int);
00253
00254
00255 int64_t lo64 = Round(lo_frac * kTicksPerSecond);
00256
00257 Duration ans;
00258 if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;
00259 int64_t hi64 = time_internal::GetRepHi(ans);
00260 if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans;
00261 hi64 = time_internal::GetRepHi(ans);
00262 lo64 %= kTicksPerSecond;
00263 NormalizeTicks(&hi64, &lo64);
00264 return time_internal::MakeDuration(hi64, lo64);
00265 }
00266
00267
00268
00269
00270 inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q,
00271 Duration* rem) {
00272
00273 if (time_internal::IsInfiniteDuration(num) ||
00274 time_internal::IsInfiniteDuration(den))
00275 return false;
00276
00277 int64_t num_hi = time_internal::GetRepHi(num);
00278 uint32_t num_lo = time_internal::GetRepLo(num);
00279 int64_t den_hi = time_internal::GetRepHi(den);
00280 uint32_t den_lo = time_internal::GetRepLo(den);
00281
00282 if (den_hi == 0 && den_lo == kTicksPerNanosecond) {
00283
00284 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) {
00285 *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond;
00286 *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00287 return true;
00288 }
00289 } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) {
00290
00291 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) {
00292 *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond);
00293 *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00294 return true;
00295 }
00296 } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) {
00297
00298 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) {
00299 *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond);
00300 *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00301 return true;
00302 }
00303 } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) {
00304
00305 if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) {
00306 *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond);
00307 *rem = time_internal::MakeDuration(0, num_lo % den_lo);
00308 return true;
00309 }
00310 } else if (den_hi > 0 && den_lo == 0) {
00311
00312 if (num_hi >= 0) {
00313 if (den_hi == 1) {
00314 *q = num_hi;
00315 *rem = time_internal::MakeDuration(0, num_lo);
00316 return true;
00317 }
00318 *q = num_hi / den_hi;
00319 *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo);
00320 return true;
00321 }
00322 if (num_lo != 0) {
00323 num_hi += 1;
00324 }
00325 int64_t quotient = num_hi / den_hi;
00326 int64_t rem_sec = num_hi % den_hi;
00327 if (rem_sec > 0) {
00328 rem_sec -= den_hi;
00329 quotient += 1;
00330 }
00331 if (num_lo != 0) {
00332 rem_sec -= 1;
00333 }
00334 *q = quotient;
00335 *rem = time_internal::MakeDuration(rem_sec, num_lo);
00336 return true;
00337 }
00338
00339 return false;
00340 }
00341
00342 }
00343
00344 namespace time_internal {
00345
00346
00347
00348
00349
00350 int64_t IDivDuration(bool satq, const Duration num, const Duration den,
00351 Duration* rem) {
00352 int64_t q = 0;
00353 if (IDivFastPath(num, den, &q, rem)) {
00354 return q;
00355 }
00356
00357 const bool num_neg = num < ZeroDuration();
00358 const bool den_neg = den < ZeroDuration();
00359 const bool quotient_neg = num_neg != den_neg;
00360
00361 if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
00362 *rem = num_neg ? -InfiniteDuration() : InfiniteDuration();
00363 return quotient_neg ? kint64min : kint64max;
00364 }
00365 if (time_internal::IsInfiniteDuration(den)) {
00366 *rem = num;
00367 return 0;
00368 }
00369
00370 const uint128 a = MakeU128Ticks(num);
00371 const uint128 b = MakeU128Ticks(den);
00372 uint128 quotient128 = a / b;
00373
00374 if (satq) {
00375
00376 if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) {
00377 quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min))
00378 : uint128(static_cast<uint64_t>(kint64max));
00379 }
00380 }
00381
00382 const uint128 remainder128 = a - quotient128 * b;
00383 *rem = MakeDurationFromU128(remainder128, num_neg);
00384
00385 if (!quotient_neg || quotient128 == 0) {
00386 return Uint128Low64(quotient128) & kint64max;
00387 }
00388
00389
00390 return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1;
00391 }
00392
00393 }
00394
00395
00396
00397
00398
00399 Duration& Duration::operator+=(Duration rhs) {
00400 if (time_internal::IsInfiniteDuration(*this)) return *this;
00401 if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs;
00402 const int64_t orig_rep_hi = rep_hi_;
00403 rep_hi_ =
00404 DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_));
00405 if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) {
00406 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1);
00407 rep_lo_ -= kTicksPerSecond;
00408 }
00409 rep_lo_ += rhs.rep_lo_;
00410 if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) {
00411 return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration();
00412 }
00413 return *this;
00414 }
00415
00416 Duration& Duration::operator-=(Duration rhs) {
00417 if (time_internal::IsInfiniteDuration(*this)) return *this;
00418 if (time_internal::IsInfiniteDuration(rhs)) {
00419 return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
00420 }
00421 const int64_t orig_rep_hi = rep_hi_;
00422 rep_hi_ =
00423 DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_));
00424 if (rep_lo_ < rhs.rep_lo_) {
00425 rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1);
00426 rep_lo_ += kTicksPerSecond;
00427 }
00428 rep_lo_ -= rhs.rep_lo_;
00429 if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) {
00430 return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration();
00431 }
00432 return *this;
00433 }
00434
00435
00436
00437
00438
00439 Duration& Duration::operator*=(int64_t r) {
00440 if (time_internal::IsInfiniteDuration(*this)) {
00441 const bool is_neg = (r < 0) != (rep_hi_ < 0);
00442 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00443 }
00444 return *this = ScaleFixed<SafeMultiply>(*this, r);
00445 }
00446
00447 Duration& Duration::operator*=(double r) {
00448 if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) {
00449 const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
00450 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00451 }
00452 return *this = ScaleDouble<std::multiplies>(*this, r);
00453 }
00454
00455 Duration& Duration::operator/=(int64_t r) {
00456 if (time_internal::IsInfiniteDuration(*this) || r == 0) {
00457 const bool is_neg = (r < 0) != (rep_hi_ < 0);
00458 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00459 }
00460 return *this = ScaleFixed<std::divides>(*this, r);
00461 }
00462
00463 Duration& Duration::operator/=(double r) {
00464 if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {
00465 const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
00466 return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
00467 }
00468 return *this = ScaleDouble<std::divides>(*this, r);
00469 }
00470
00471 Duration& Duration::operator%=(Duration rhs) {
00472 time_internal::IDivDuration(false, *this, rhs, this);
00473 return *this;
00474 }
00475
00476 double FDivDuration(Duration num, Duration den) {
00477
00478 if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) {
00479 return (num < ZeroDuration()) == (den < ZeroDuration())
00480 ? std::numeric_limits<double>::infinity()
00481 : -std::numeric_limits<double>::infinity();
00482 }
00483 if (time_internal::IsInfiniteDuration(den)) return 0.0;
00484
00485 double a =
00486 static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond +
00487 time_internal::GetRepLo(num);
00488 double b =
00489 static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond +
00490 time_internal::GetRepLo(den);
00491 return a / b;
00492 }
00493
00494
00495
00496
00497
00498 Duration Trunc(Duration d, Duration unit) {
00499 return d - (d % unit);
00500 }
00501
00502 Duration Floor(const Duration d, const Duration unit) {
00503 const absl::Duration td = Trunc(d, unit);
00504 return td <= d ? td : td - AbsDuration(unit);
00505 }
00506
00507 Duration Ceil(const Duration d, const Duration unit) {
00508 const absl::Duration td = Trunc(d, unit);
00509 return td >= d ? td : td + AbsDuration(unit);
00510 }
00511
00512
00513
00514
00515
00516 Duration DurationFromTimespec(timespec ts) {
00517 if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) {
00518 int64_t ticks = ts.tv_nsec * kTicksPerNanosecond;
00519 return time_internal::MakeDuration(ts.tv_sec, ticks);
00520 }
00521 return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec);
00522 }
00523
00524 Duration DurationFromTimeval(timeval tv) {
00525 if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) {
00526 int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond;
00527 return time_internal::MakeDuration(tv.tv_sec, ticks);
00528 }
00529 return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec);
00530 }
00531
00532
00533
00534
00535
00536 int64_t ToInt64Nanoseconds(Duration d) {
00537 if (time_internal::GetRepHi(d) >= 0 &&
00538 time_internal::GetRepHi(d) >> 33 == 0) {
00539 return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
00540 (time_internal::GetRepLo(d) / kTicksPerNanosecond);
00541 }
00542 return d / Nanoseconds(1);
00543 }
00544 int64_t ToInt64Microseconds(Duration d) {
00545 if (time_internal::GetRepHi(d) >= 0 &&
00546 time_internal::GetRepHi(d) >> 43 == 0) {
00547 return (time_internal::GetRepHi(d) * 1000 * 1000) +
00548 (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000));
00549 }
00550 return d / Microseconds(1);
00551 }
00552 int64_t ToInt64Milliseconds(Duration d) {
00553 if (time_internal::GetRepHi(d) >= 0 &&
00554 time_internal::GetRepHi(d) >> 53 == 0) {
00555 return (time_internal::GetRepHi(d) * 1000) +
00556 (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000));
00557 }
00558 return d / Milliseconds(1);
00559 }
00560 int64_t ToInt64Seconds(Duration d) {
00561 int64_t hi = time_internal::GetRepHi(d);
00562 if (time_internal::IsInfiniteDuration(d)) return hi;
00563 if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00564 return hi;
00565 }
00566 int64_t ToInt64Minutes(Duration d) {
00567 int64_t hi = time_internal::GetRepHi(d);
00568 if (time_internal::IsInfiniteDuration(d)) return hi;
00569 if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00570 return hi / 60;
00571 }
00572 int64_t ToInt64Hours(Duration d) {
00573 int64_t hi = time_internal::GetRepHi(d);
00574 if (time_internal::IsInfiniteDuration(d)) return hi;
00575 if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
00576 return hi / (60 * 60);
00577 }
00578
00579 double ToDoubleNanoseconds(Duration d) {
00580 return FDivDuration(d, Nanoseconds(1));
00581 }
00582 double ToDoubleMicroseconds(Duration d) {
00583 return FDivDuration(d, Microseconds(1));
00584 }
00585 double ToDoubleMilliseconds(Duration d) {
00586 return FDivDuration(d, Milliseconds(1));
00587 }
00588 double ToDoubleSeconds(Duration d) {
00589 return FDivDuration(d, Seconds(1));
00590 }
00591 double ToDoubleMinutes(Duration d) {
00592 return FDivDuration(d, Minutes(1));
00593 }
00594 double ToDoubleHours(Duration d) {
00595 return FDivDuration(d, Hours(1));
00596 }
00597
00598 timespec ToTimespec(Duration d) {
00599 timespec ts;
00600 if (!time_internal::IsInfiniteDuration(d)) {
00601 int64_t rep_hi = time_internal::GetRepHi(d);
00602 uint32_t rep_lo = time_internal::GetRepLo(d);
00603 if (rep_hi < 0) {
00604
00605
00606 rep_lo += kTicksPerNanosecond - 1;
00607 if (rep_lo >= kTicksPerSecond) {
00608 rep_hi += 1;
00609 rep_lo -= kTicksPerSecond;
00610 }
00611 }
00612 ts.tv_sec = rep_hi;
00613 if (ts.tv_sec == rep_hi) {
00614 ts.tv_nsec = rep_lo / kTicksPerNanosecond;
00615 return ts;
00616 }
00617 }
00618 if (d >= ZeroDuration()) {
00619 ts.tv_sec = std::numeric_limits<time_t>::max();
00620 ts.tv_nsec = 1000 * 1000 * 1000 - 1;
00621 } else {
00622 ts.tv_sec = std::numeric_limits<time_t>::min();
00623 ts.tv_nsec = 0;
00624 }
00625 return ts;
00626 }
00627
00628 timeval ToTimeval(Duration d) {
00629 timeval tv;
00630 timespec ts = ToTimespec(d);
00631 if (ts.tv_sec < 0) {
00632
00633
00634 ts.tv_nsec += 1000 - 1;
00635 if (ts.tv_nsec >= 1000 * 1000 * 1000) {
00636 ts.tv_sec += 1;
00637 ts.tv_nsec -= 1000 * 1000 * 1000;
00638 }
00639 }
00640 tv.tv_sec = ts.tv_sec;
00641 if (tv.tv_sec != ts.tv_sec) {
00642 if (ts.tv_sec < 0) {
00643 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
00644 tv.tv_usec = 0;
00645 } else {
00646 tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max();
00647 tv.tv_usec = 1000 * 1000 - 1;
00648 }
00649 return tv;
00650 }
00651 tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000);
00652 return tv;
00653 }
00654
00655 std::chrono::nanoseconds ToChronoNanoseconds(Duration d) {
00656 return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d);
00657 }
00658 std::chrono::microseconds ToChronoMicroseconds(Duration d) {
00659 return time_internal::ToChronoDuration<std::chrono::microseconds>(d);
00660 }
00661 std::chrono::milliseconds ToChronoMilliseconds(Duration d) {
00662 return time_internal::ToChronoDuration<std::chrono::milliseconds>(d);
00663 }
00664 std::chrono::seconds ToChronoSeconds(Duration d) {
00665 return time_internal::ToChronoDuration<std::chrono::seconds>(d);
00666 }
00667 std::chrono::minutes ToChronoMinutes(Duration d) {
00668 return time_internal::ToChronoDuration<std::chrono::minutes>(d);
00669 }
00670 std::chrono::hours ToChronoHours(Duration d) {
00671 return time_internal::ToChronoDuration<std::chrono::hours>(d);
00672 }
00673
00674
00675
00676
00677
00678 namespace {
00679
00680
00681
00682
00683 char* Format64(char* ep, int width, int64_t v) {
00684 do {
00685 --width;
00686 *--ep = '0' + (v % 10);
00687 } while (v /= 10);
00688 while (--width >= 0) *--ep = '0';
00689 return ep;
00690 }
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 struct DisplayUnit {
00706 const char* abbr;
00707 int prec;
00708 double pow10;
00709 };
00710 const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
00711 const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
00712 const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
00713 const DisplayUnit kDisplaySec = {"s", 11, 1e11};
00714 const DisplayUnit kDisplayMin = {"m", -1, 0.0};
00715 const DisplayUnit kDisplayHour = {"h", -1, 0.0};
00716
00717 void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
00718 char buf[sizeof("2562047788015216")];
00719 char* const ep = buf + sizeof(buf);
00720 char* bp = Format64(ep, 0, n);
00721 if (*bp != '0' || bp + 1 != ep) {
00722 out->append(bp, ep - bp);
00723 out->append(unit.abbr);
00724 }
00725 }
00726
00727
00728
00729 void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
00730 const int buf_size = std::numeric_limits<double>::digits10;
00731 const int prec = std::min(buf_size, unit.prec);
00732 char buf[buf_size];
00733 char* ep = buf + sizeof(buf);
00734 double d = 0;
00735 int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
00736 int64_t int_part = d;
00737 if (int_part != 0 || frac_part != 0) {
00738 char* bp = Format64(ep, 0, int_part);
00739 out->append(bp, ep - bp);
00740 if (frac_part != 0) {
00741 out->push_back('.');
00742 bp = Format64(ep, prec, frac_part);
00743 while (ep[-1] == '0') --ep;
00744 out->append(bp, ep - bp);
00745 }
00746 out->append(unit.abbr);
00747 }
00748 }
00749
00750 }
00751
00752
00753
00754
00755
00756
00757
00758 std::string FormatDuration(Duration d) {
00759 const Duration min_duration = Seconds(kint64min);
00760 if (d == min_duration) {
00761
00762
00763 return "-2562047788015215h30m8s";
00764 }
00765 std::string s;
00766 if (d < ZeroDuration()) {
00767 s.append("-");
00768 d = -d;
00769 }
00770 if (d == InfiniteDuration()) {
00771 s.append("inf");
00772 } else if (d < Seconds(1)) {
00773
00774
00775 if (d < Microseconds(1)) {
00776 AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano);
00777 } else if (d < Milliseconds(1)) {
00778 AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro);
00779 } else {
00780 AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli);
00781 }
00782 } else {
00783 AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour);
00784 AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin);
00785 AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec);
00786 }
00787 if (s.empty() || s == "-") {
00788 s = "0";
00789 }
00790 return s;
00791 }
00792
00793 namespace {
00794
00795
00796
00797
00798 bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
00799 int64_t* frac_part, int64_t* frac_scale) {
00800 *int_part = 0;
00801 *frac_part = 0;
00802 *frac_scale = 1;
00803 const char* start = *dpp;
00804 for (; std::isdigit(**dpp); *dpp += 1) {
00805 const int d = **dpp - '0';
00806 if (*int_part > kint64max / 10) return false;
00807 *int_part *= 10;
00808 if (*int_part > kint64max - d) return false;
00809 *int_part += d;
00810 }
00811 const bool int_part_empty = (*dpp == start);
00812 if (**dpp != '.') return !int_part_empty;
00813 for (*dpp += 1; std::isdigit(**dpp); *dpp += 1) {
00814 const int d = **dpp - '0';
00815 if (*frac_scale <= kint64max / 10) {
00816 *frac_part *= 10;
00817 *frac_part += d;
00818 *frac_scale *= 10;
00819 }
00820 }
00821 return !int_part_empty || *frac_scale != 1;
00822 }
00823
00824
00825
00826
00827
00828 bool ConsumeDurationUnit(const char** start, Duration* unit) {
00829 const char *s = *start;
00830 bool ok = true;
00831 if (strncmp(s, "ns", 2) == 0) {
00832 s += 2;
00833 *unit = Nanoseconds(1);
00834 } else if (strncmp(s, "us", 2) == 0) {
00835 s += 2;
00836 *unit = Microseconds(1);
00837 } else if (strncmp(s, "ms", 2) == 0) {
00838 s += 2;
00839 *unit = Milliseconds(1);
00840 } else if (strncmp(s, "s", 1) == 0) {
00841 s += 1;
00842 *unit = Seconds(1);
00843 } else if (strncmp(s, "m", 1) == 0) {
00844 s += 1;
00845 *unit = Minutes(1);
00846 } else if (strncmp(s, "h", 1) == 0) {
00847 s += 1;
00848 *unit = Hours(1);
00849 } else {
00850 ok = false;
00851 }
00852 *start = s;
00853 return ok;
00854 }
00855
00856 }
00857
00858
00859
00860
00861
00862
00863 bool ParseDuration(const std::string& dur_string, Duration* d) {
00864 const char* start = dur_string.c_str();
00865 int sign = 1;
00866
00867 if (*start == '-' || *start == '+') {
00868 sign = *start == '-' ? -1 : 1;
00869 ++start;
00870 }
00871
00872
00873 if (*start == '\0') {
00874 return false;
00875 }
00876
00877
00878 if (*start == '0' && *(start + 1) == '\0') {
00879 *d = ZeroDuration();
00880 return true;
00881 }
00882
00883 if (strcmp(start, "inf") == 0) {
00884 *d = sign * InfiniteDuration();
00885 return true;
00886 }
00887
00888 Duration dur;
00889 while (*start != '\0') {
00890 int64_t int_part;
00891 int64_t frac_part;
00892 int64_t frac_scale;
00893 Duration unit;
00894 if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
00895 !ConsumeDurationUnit(&start, &unit)) {
00896 return false;
00897 }
00898 if (int_part != 0) dur += sign * int_part * unit;
00899 if (frac_part != 0) dur += sign * frac_part * unit / frac_scale;
00900 }
00901 *d = dur;
00902 return true;
00903 }
00904
00905 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
00906 return ParseDuration(text, dst);
00907 }
00908
00909 std::string UnparseFlag(Duration d) { return FormatDuration(d); }
00910
00911 }