time_util.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. #include <google/protobuf/util/time_util.h>
  31. #include <google/protobuf/stubs/int128.h>
  32. #include <google/protobuf/stubs/stringprintf.h>
  33. #include <google/protobuf/stubs/strutil.h>
  34. #include <google/protobuf/stubs/time.h>
  35. #include <google/protobuf/duration.pb.h>
  36. #include <google/protobuf/timestamp.pb.h>
  37. namespace google {
  38. namespace protobuf {
  39. namespace util {
  40. using google::protobuf::Timestamp;
  41. using google::protobuf::Duration;
  42. namespace {
  43. static const int kNanosPerSecond = 1000000000;
  44. static const int kMicrosPerSecond = 1000000;
  45. static const int kMillisPerSecond = 1000;
  46. static const int kNanosPerMillisecond = 1000000;
  47. static const int kNanosPerMicrosecond = 1000;
  48. static const int kSecondsPerMinute = 60; // Note that we ignore leap seconds.
  49. static const int kSecondsPerHour = 3600;
  50. template <typename T>
  51. T CreateNormalized(int64 seconds, int64 nanos);
  52. template <>
  53. Timestamp CreateNormalized(int64 seconds, int64 nanos) {
  54. // Make sure nanos is in the range.
  55. if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
  56. seconds += nanos / kNanosPerSecond;
  57. nanos = nanos % kNanosPerSecond;
  58. }
  59. // For Timestamp nanos should be in the range [0, 999999999]
  60. if (nanos < 0) {
  61. seconds -= 1;
  62. nanos += kNanosPerSecond;
  63. }
  64. GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
  65. seconds <= TimeUtil::kTimestampMaxSeconds);
  66. Timestamp result;
  67. result.set_seconds(seconds);
  68. result.set_nanos(static_cast<int32>(nanos));
  69. return result;
  70. }
  71. template <>
  72. Duration CreateNormalized(int64 seconds, int64 nanos) {
  73. // Make sure nanos is in the range.
  74. if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
  75. seconds += nanos / kNanosPerSecond;
  76. nanos = nanos % kNanosPerSecond;
  77. }
  78. // nanos should have the same sign as seconds.
  79. if (seconds < 0 && nanos > 0) {
  80. seconds += 1;
  81. nanos -= kNanosPerSecond;
  82. } else if (seconds > 0 && nanos < 0) {
  83. seconds -= 1;
  84. nanos += kNanosPerSecond;
  85. }
  86. GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
  87. seconds <= TimeUtil::kDurationMaxSeconds);
  88. Duration result;
  89. result.set_seconds(seconds);
  90. result.set_nanos(static_cast<int32>(nanos));
  91. return result;
  92. }
  93. // Format nanoseconds with either 3, 6, or 9 digits depending on the required
  94. // precision to represent the exact value.
  95. string FormatNanos(int32 nanos) {
  96. if (nanos % kNanosPerMillisecond == 0) {
  97. return StringPrintf("%03d", nanos / kNanosPerMillisecond);
  98. } else if (nanos % kNanosPerMicrosecond == 0) {
  99. return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
  100. } else {
  101. return StringPrintf("%09d", nanos);
  102. }
  103. }
  104. string FormatTime(int64 seconds, int32 nanos) {
  105. return ::google::protobuf::internal::FormatTime(seconds, nanos);
  106. }
  107. bool ParseTime(const string& value, int64* seconds, int32* nanos) {
  108. return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
  109. }
  110. void CurrentTime(int64* seconds, int32* nanos) {
  111. return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
  112. }
  113. // Truncates the remainder part after division.
  114. int64 RoundTowardZero(int64 value, int64 divider) {
  115. int64 result = value / divider;
  116. int64 remainder = value % divider;
  117. // Before C++11, the sign of the remainder is implementation dependent if
  118. // any of the operands is negative. Here we try to enforce C++11's "rounded
  119. // toward zero" semantics. For example, for (-5) / 2 an implementation may
  120. // give -3 as the result with the remainder being 1. This function ensures
  121. // we always return -2 (closer to zero) regardless of the implementation.
  122. if (result < 0 && remainder > 0) {
  123. return result + 1;
  124. } else {
  125. return result;
  126. }
  127. }
  128. } // namespace
  129. // Actually define these static const integers. Required by C++ standard (but
  130. // some compilers don't like it).
  131. #ifndef _MSC_VER
  132. const int64 TimeUtil::kTimestampMinSeconds;
  133. const int64 TimeUtil::kTimestampMaxSeconds;
  134. const int64 TimeUtil::kDurationMaxSeconds;
  135. const int64 TimeUtil::kDurationMinSeconds;
  136. #endif // !_MSC_VER
  137. string TimeUtil::ToString(const Timestamp& timestamp) {
  138. return FormatTime(timestamp.seconds(), timestamp.nanos());
  139. }
  140. bool TimeUtil::FromString(const string& value, Timestamp* timestamp) {
  141. int64 seconds;
  142. int32 nanos;
  143. if (!ParseTime(value, &seconds, &nanos)) {
  144. return false;
  145. }
  146. *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
  147. return true;
  148. }
  149. Timestamp TimeUtil::GetCurrentTime() {
  150. int64 seconds;
  151. int32 nanos;
  152. CurrentTime(&seconds, &nanos);
  153. return CreateNormalized<Timestamp>(seconds, nanos);
  154. }
  155. Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
  156. string TimeUtil::ToString(const Duration& duration) {
  157. string result;
  158. int64 seconds = duration.seconds();
  159. int32 nanos = duration.nanos();
  160. if (seconds < 0 || nanos < 0) {
  161. result += "-";
  162. seconds = -seconds;
  163. nanos = -nanos;
  164. }
  165. result += SimpleItoa(seconds);
  166. if (nanos != 0) {
  167. result += "." + FormatNanos(nanos);
  168. }
  169. result += "s";
  170. return result;
  171. }
  172. static int64 Pow(int64 x, int y) {
  173. int64 result = 1;
  174. for (int i = 0; i < y; ++i) {
  175. result *= x;
  176. }
  177. return result;
  178. }
  179. bool TimeUtil::FromString(const string& value, Duration* duration) {
  180. if (value.length() <= 1 || value[value.length() - 1] != 's') {
  181. return false;
  182. }
  183. bool negative = (value[0] == '-');
  184. int sign_length = (negative ? 1 : 0);
  185. // Parse the duration value as two integers rather than a float value
  186. // to avoid precision loss.
  187. string seconds_part, nanos_part;
  188. size_t pos = value.find_last_of(".");
  189. if (pos == string::npos) {
  190. seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
  191. nanos_part = "0";
  192. } else {
  193. seconds_part = value.substr(sign_length, pos - sign_length);
  194. nanos_part = value.substr(pos + 1, value.length() - pos - 2);
  195. }
  196. char* end;
  197. int64 seconds = strto64(seconds_part.c_str(), &end, 10);
  198. if (end != seconds_part.c_str() + seconds_part.length()) {
  199. return false;
  200. }
  201. int64 nanos = strto64(nanos_part.c_str(), &end, 10);
  202. if (end != nanos_part.c_str() + nanos_part.length()) {
  203. return false;
  204. }
  205. nanos = nanos * Pow(10, 9 - nanos_part.length());
  206. if (negative) {
  207. // If a Duration is negative, both seconds and nanos should be negative.
  208. seconds = -seconds;
  209. nanos = -nanos;
  210. }
  211. duration->set_seconds(seconds);
  212. duration->set_nanos(static_cast<int32>(nanos));
  213. return true;
  214. }
  215. Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
  216. return CreateNormalized<Duration>(nanos / kNanosPerSecond,
  217. nanos % kNanosPerSecond);
  218. }
  219. Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
  220. return CreateNormalized<Duration>(
  221. micros / kMicrosPerSecond,
  222. (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
  223. }
  224. Duration TimeUtil::MillisecondsToDuration(int64 millis) {
  225. return CreateNormalized<Duration>(
  226. millis / kMillisPerSecond,
  227. (millis % kMillisPerSecond) * kNanosPerMillisecond);
  228. }
  229. Duration TimeUtil::SecondsToDuration(int64 seconds) {
  230. return CreateNormalized<Duration>(seconds, 0);
  231. }
  232. Duration TimeUtil::MinutesToDuration(int64 minutes) {
  233. return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
  234. }
  235. Duration TimeUtil::HoursToDuration(int64 hours) {
  236. return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
  237. }
  238. int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
  239. return duration.seconds() * kNanosPerSecond + duration.nanos();
  240. }
  241. int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
  242. return duration.seconds() * kMicrosPerSecond +
  243. RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
  244. }
  245. int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
  246. return duration.seconds() * kMillisPerSecond +
  247. RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
  248. }
  249. int64 TimeUtil::DurationToSeconds(const Duration& duration) {
  250. return duration.seconds();
  251. }
  252. int64 TimeUtil::DurationToMinutes(const Duration& duration) {
  253. return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
  254. }
  255. int64 TimeUtil::DurationToHours(const Duration& duration) {
  256. return RoundTowardZero(duration.seconds(), kSecondsPerHour);
  257. }
  258. Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
  259. return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
  260. nanos % kNanosPerSecond);
  261. }
  262. Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
  263. return CreateNormalized<Timestamp>(
  264. micros / kMicrosPerSecond,
  265. micros % kMicrosPerSecond * kNanosPerMicrosecond);
  266. }
  267. Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
  268. return CreateNormalized<Timestamp>(
  269. millis / kMillisPerSecond,
  270. millis % kMillisPerSecond * kNanosPerMillisecond);
  271. }
  272. Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
  273. return CreateNormalized<Timestamp>(seconds, 0);
  274. }
  275. int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
  276. return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
  277. }
  278. int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
  279. return timestamp.seconds() * kMicrosPerSecond +
  280. RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
  281. }
  282. int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
  283. return timestamp.seconds() * kMillisPerSecond +
  284. RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
  285. }
  286. int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
  287. return timestamp.seconds();
  288. }
  289. Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
  290. return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
  291. }
  292. time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
  293. return static_cast<time_t>(value.seconds());
  294. }
  295. Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
  296. return CreateNormalized<Timestamp>(value.tv_sec,
  297. value.tv_usec * kNanosPerMicrosecond);
  298. }
  299. timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
  300. timeval result;
  301. result.tv_sec = value.seconds();
  302. result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
  303. return result;
  304. }
  305. Duration TimeUtil::TimevalToDuration(const timeval& value) {
  306. return CreateNormalized<Duration>(value.tv_sec,
  307. value.tv_usec * kNanosPerMicrosecond);
  308. }
  309. timeval TimeUtil::DurationToTimeval(const Duration& value) {
  310. timeval result;
  311. result.tv_sec = value.seconds();
  312. result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
  313. // timeval.tv_usec's range is [0, 1000000)
  314. if (result.tv_usec < 0) {
  315. result.tv_sec -= 1;
  316. result.tv_usec += kMicrosPerSecond;
  317. }
  318. return result;
  319. }
  320. } // namespace util
  321. } // namespace protobuf
  322. namespace protobuf {
  323. namespace {
  324. using google::protobuf::util::kNanosPerSecond;
  325. using google::protobuf::util::CreateNormalized;
  326. // Convert a Duration to uint128.
  327. void ToUint128(const Duration& value, uint128* result, bool* negative) {
  328. if (value.seconds() < 0 || value.nanos() < 0) {
  329. *negative = true;
  330. *result = static_cast<uint64>(-value.seconds());
  331. *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
  332. } else {
  333. *negative = false;
  334. *result = static_cast<uint64>(value.seconds());
  335. *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
  336. }
  337. }
  338. void ToDuration(const uint128& value, bool negative, Duration* duration) {
  339. int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
  340. int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
  341. if (negative) {
  342. seconds = -seconds;
  343. nanos = -nanos;
  344. }
  345. duration->set_seconds(seconds);
  346. duration->set_nanos(nanos);
  347. }
  348. } // namespace
  349. Duration& operator+=(Duration& d1, const Duration& d2) {
  350. d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
  351. d1.nanos() + d2.nanos());
  352. return d1;
  353. }
  354. Duration& operator-=(Duration& d1, const Duration& d2) { // NOLINT
  355. d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
  356. d1.nanos() - d2.nanos());
  357. return d1;
  358. }
  359. Duration& operator*=(Duration& d, int64 r) { // NOLINT
  360. bool negative;
  361. uint128 value;
  362. ToUint128(d, &value, &negative);
  363. if (r > 0) {
  364. value *= static_cast<uint64>(r);
  365. } else {
  366. negative = !negative;
  367. value *= static_cast<uint64>(-r);
  368. }
  369. ToDuration(value, negative, &d);
  370. return d;
  371. }
  372. Duration& operator*=(Duration& d, double r) { // NOLINT
  373. double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
  374. int64 seconds = static_cast<int64>(result);
  375. int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
  376. // Note that we normalize here not just because nanos can have a different
  377. // sign from seconds but also that nanos can be any arbitrary value when
  378. // overflow happens (i.e., the result is a much larger value than what
  379. // int64 can represent).
  380. d = CreateNormalized<Duration>(seconds, nanos);
  381. return d;
  382. }
  383. Duration& operator/=(Duration& d, int64 r) { // NOLINT
  384. bool negative;
  385. uint128 value;
  386. ToUint128(d, &value, &negative);
  387. if (r > 0) {
  388. value /= static_cast<uint64>(r);
  389. } else {
  390. negative = !negative;
  391. value /= static_cast<uint64>(-r);
  392. }
  393. ToDuration(value, negative, &d);
  394. return d;
  395. }
  396. Duration& operator/=(Duration& d, double r) { // NOLINT
  397. return d *= 1.0 / r;
  398. }
  399. Duration& operator%=(Duration& d1, const Duration& d2) { // NOLINT
  400. bool negative1, negative2;
  401. uint128 value1, value2;
  402. ToUint128(d1, &value1, &negative1);
  403. ToUint128(d2, &value2, &negative2);
  404. uint128 result = value1 % value2;
  405. // When negative values are involved in division, we round the division
  406. // result towards zero. With this semantics, sign of the remainder is the
  407. // same as the dividend. For example:
  408. // -5 / 10 = 0, -5 % 10 = -5
  409. // -5 / (-10) = 0, -5 % (-10) = -5
  410. // 5 / (-10) = 0, 5 % (-10) = 5
  411. ToDuration(result, negative1, &d1);
  412. return d1;
  413. }
  414. int64 operator/(const Duration& d1, const Duration& d2) {
  415. bool negative1, negative2;
  416. uint128 value1, value2;
  417. ToUint128(d1, &value1, &negative1);
  418. ToUint128(d2, &value2, &negative2);
  419. int64 result = Uint128Low64(value1 / value2);
  420. if (negative1 != negative2) {
  421. result = -result;
  422. }
  423. return result;
  424. }
  425. Timestamp& operator+=(Timestamp& t, const Duration& d) { // NOLINT
  426. t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
  427. t.nanos() + d.nanos());
  428. return t;
  429. }
  430. Timestamp& operator-=(Timestamp& t, const Duration& d) { // NOLINT
  431. t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
  432. t.nanos() - d.nanos());
  433. return t;
  434. }
  435. Duration operator-(const Timestamp& t1, const Timestamp& t2) {
  436. return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
  437. t1.nanos() - t2.nanos());
  438. }
  439. } // namespace protobuf
  440. } // namespace google