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 <>
CreateNormalized(int64 seconds,int64 nanos)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 <>
CreateNormalized(int64 seconds,int64 nanos)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.
FormatNanos(int32 nanos)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 
FormatTime(int64 seconds,int32 nanos)116 string FormatTime(int64 seconds, int32 nanos) {
117   return ::google::protobuf::internal::FormatTime(seconds, nanos);
118 }
119 
ParseTime(const string & value,int64 * seconds,int32 * nanos)120 bool ParseTime(const string& value, int64* seconds, int32* nanos) {
121   return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
122 }
123 
CurrentTime(int64 * seconds,int32 * nanos)124 void CurrentTime(int64* seconds, int32* nanos) {
125   return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
126 }
127 
128 // Truncates the remainder part after division.
RoundTowardZero(int64 value,int64 divider)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 // Actually define these static const integers. Required by C++ standard (but
146 // omitting them may still work with some compilers).
147 const int64 TimeUtil::kTimestampMinSeconds;
148 const int64 TimeUtil::kTimestampMaxSeconds;
149 const int64 TimeUtil::kDurationMaxSeconds;
150 const int64 TimeUtil::kDurationMinSeconds;
151 
ToString(const Timestamp & timestamp)152 string TimeUtil::ToString(const Timestamp& timestamp) {
153   return FormatTime(timestamp.seconds(), timestamp.nanos());
154 }
155 
FromString(const string & value,Timestamp * timestamp)156 bool TimeUtil::FromString(const string& value, Timestamp* timestamp) {
157   int64 seconds;
158   int32 nanos;
159   if (!ParseTime(value, &seconds, &nanos)) {
160     return false;
161   }
162   *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
163   return true;
164 }
165 
GetCurrentTime()166 Timestamp TimeUtil::GetCurrentTime() {
167   int64 seconds;
168   int32 nanos;
169   CurrentTime(&seconds, &nanos);
170   return CreateNormalized<Timestamp>(seconds, nanos);
171 }
172 
GetEpoch()173 Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
174 
ToString(const Duration & duration)175 string TimeUtil::ToString(const Duration& duration) {
176   string result;
177   int64 seconds = duration.seconds();
178   int32 nanos = duration.nanos();
179   if (seconds < 0 || nanos < 0) {
180     result += "-";
181     seconds = -seconds;
182     nanos = -nanos;
183   }
184   result += SimpleItoa(seconds);
185   if (nanos != 0) {
186     result += "." + FormatNanos(nanos);
187   }
188   result += "s";
189   return result;
190 }
191 
Pow(int64 x,int y)192 static int64 Pow(int64 x, int y) {
193   int64 result = 1;
194   for (int i = 0; i < y; ++i) {
195     result *= x;
196   }
197   return result;
198 }
199 
FromString(const string & value,Duration * duration)200 bool TimeUtil::FromString(const string& value, Duration* duration) {
201   if (value.length() <= 1 || value[value.length() - 1] != 's') {
202     return false;
203   }
204   bool negative = (value[0] == '-');
205   int sign_length = (negative ? 1 : 0);
206   // Parse the duration value as two integers rather than a float value
207   // to avoid precision loss.
208   string seconds_part, nanos_part;
209   size_t pos = value.find_last_of(".");
210   if (pos == string::npos) {
211     seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
212     nanos_part = "0";
213   } else {
214     seconds_part = value.substr(sign_length, pos - sign_length);
215     nanos_part = value.substr(pos + 1, value.length() - pos - 2);
216   }
217   char* end;
218   int64 seconds = strto64(seconds_part.c_str(), &end, 10);
219   if (end != seconds_part.c_str() + seconds_part.length()) {
220     return false;
221   }
222   int64 nanos = strto64(nanos_part.c_str(), &end, 10);
223   if (end != nanos_part.c_str() + nanos_part.length()) {
224     return false;
225   }
226   nanos = nanos * Pow(10, 9 - nanos_part.length());
227   if (negative) {
228     // If a Duration is negative, both seconds and nanos should be negative.
229     seconds = -seconds;
230     nanos = -nanos;
231   }
232   duration->set_seconds(seconds);
233   duration->set_nanos(static_cast<int32>(nanos));
234   return true;
235 }
236 
NanosecondsToDuration(int64 nanos)237 Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
238   return CreateNormalized<Duration>(nanos / kNanosPerSecond,
239                                     nanos % kNanosPerSecond);
240 }
241 
MicrosecondsToDuration(int64 micros)242 Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
243   return CreateNormalized<Duration>(
244       micros / kMicrosPerSecond,
245       (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
246 }
247 
MillisecondsToDuration(int64 millis)248 Duration TimeUtil::MillisecondsToDuration(int64 millis) {
249   return CreateNormalized<Duration>(
250       millis / kMillisPerSecond,
251       (millis % kMillisPerSecond) * kNanosPerMillisecond);
252 }
253 
SecondsToDuration(int64 seconds)254 Duration TimeUtil::SecondsToDuration(int64 seconds) {
255   return CreateNormalized<Duration>(seconds, 0);
256 }
257 
MinutesToDuration(int64 minutes)258 Duration TimeUtil::MinutesToDuration(int64 minutes) {
259   return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
260 }
261 
HoursToDuration(int64 hours)262 Duration TimeUtil::HoursToDuration(int64 hours) {
263   return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
264 }
265 
DurationToNanoseconds(const Duration & duration)266 int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
267   return duration.seconds() * kNanosPerSecond + duration.nanos();
268 }
269 
DurationToMicroseconds(const Duration & duration)270 int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
271   return duration.seconds() * kMicrosPerSecond +
272          RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
273 }
274 
DurationToMilliseconds(const Duration & duration)275 int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
276   return duration.seconds() * kMillisPerSecond +
277          RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
278 }
279 
DurationToSeconds(const Duration & duration)280 int64 TimeUtil::DurationToSeconds(const Duration& duration) {
281   return duration.seconds();
282 }
283 
DurationToMinutes(const Duration & duration)284 int64 TimeUtil::DurationToMinutes(const Duration& duration) {
285   return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
286 }
287 
DurationToHours(const Duration & duration)288 int64 TimeUtil::DurationToHours(const Duration& duration) {
289   return RoundTowardZero(duration.seconds(), kSecondsPerHour);
290 }
291 
NanosecondsToTimestamp(int64 nanos)292 Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
293   return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
294                                      nanos % kNanosPerSecond);
295 }
296 
MicrosecondsToTimestamp(int64 micros)297 Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
298   return CreateNormalized<Timestamp>(
299       micros / kMicrosPerSecond,
300       micros % kMicrosPerSecond * kNanosPerMicrosecond);
301 }
302 
MillisecondsToTimestamp(int64 millis)303 Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
304   return CreateNormalized<Timestamp>(
305       millis / kMillisPerSecond,
306       millis % kMillisPerSecond * kNanosPerMillisecond);
307 }
308 
SecondsToTimestamp(int64 seconds)309 Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
310   return CreateNormalized<Timestamp>(seconds, 0);
311 }
312 
TimestampToNanoseconds(const Timestamp & timestamp)313 int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
314   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
315 }
316 
TimestampToMicroseconds(const Timestamp & timestamp)317 int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
318   return timestamp.seconds() * kMicrosPerSecond +
319          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
320 }
321 
TimestampToMilliseconds(const Timestamp & timestamp)322 int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
323   return timestamp.seconds() * kMillisPerSecond +
324          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
325 }
326 
TimestampToSeconds(const Timestamp & timestamp)327 int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
328   return timestamp.seconds();
329 }
330 
TimeTToTimestamp(time_t value)331 Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
332   return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
333 }
334 
TimestampToTimeT(const Timestamp & value)335 time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
336   return static_cast<time_t>(value.seconds());
337 }
338 
TimevalToTimestamp(const timeval & value)339 Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
340   return CreateNormalized<Timestamp>(value.tv_sec,
341                                      value.tv_usec * kNanosPerMicrosecond);
342 }
343 
TimestampToTimeval(const Timestamp & value)344 timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
345   timeval result;
346   result.tv_sec = value.seconds();
347   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
348   return result;
349 }
350 
TimevalToDuration(const timeval & value)351 Duration TimeUtil::TimevalToDuration(const timeval& value) {
352   return CreateNormalized<Duration>(value.tv_sec,
353                                     value.tv_usec * kNanosPerMicrosecond);
354 }
355 
DurationToTimeval(const Duration & value)356 timeval TimeUtil::DurationToTimeval(const Duration& value) {
357   timeval result;
358   result.tv_sec = value.seconds();
359   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
360   // timeval.tv_usec's range is [0, 1000000)
361   if (result.tv_usec < 0) {
362     result.tv_sec -= 1;
363     result.tv_usec += kMicrosPerSecond;
364   }
365   return result;
366 }
367 
368 }  // namespace util
369 }  // namespace protobuf
370 
371 
372 namespace protobuf {
373 namespace {
374 using google::protobuf::util::kNanosPerSecond;
375 using google::protobuf::util::CreateNormalized;
376 
377 // Convert a Timestamp to uint128.
ToUint128(const Timestamp & value,uint128 * result,bool * negative)378 void ToUint128(const Timestamp& value, uint128* result, bool* negative) {
379   if (value.seconds() < 0) {
380     *negative = true;
381     *result = static_cast<uint64>(-value.seconds());
382     *result = *result * kNanosPerSecond - static_cast<uint32>(value.nanos());
383   } else {
384     *negative = false;
385     *result = static_cast<uint64>(value.seconds());
386     *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
387   }
388 }
389 
390 // Convert a Duration to uint128.
ToUint128(const Duration & value,uint128 * result,bool * negative)391 void ToUint128(const Duration& value, uint128* result, bool* negative) {
392   if (value.seconds() < 0 || value.nanos() < 0) {
393     *negative = true;
394     *result = static_cast<uint64>(-value.seconds());
395     *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
396   } else {
397     *negative = false;
398     *result = static_cast<uint64>(value.seconds());
399     *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
400   }
401 }
402 
ToTimestamp(const uint128 & value,bool negative,Timestamp * timestamp)403 void ToTimestamp(const uint128& value, bool negative, Timestamp* timestamp) {
404   int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
405   int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
406   if (negative) {
407     seconds = -seconds;
408     nanos = -nanos;
409     if (nanos < 0) {
410       nanos += kNanosPerSecond;
411       seconds -= 1;
412     }
413   }
414   timestamp->set_seconds(seconds);
415   timestamp->set_nanos(nanos);
416 }
417 
ToDuration(const uint128 & value,bool negative,Duration * duration)418 void ToDuration(const uint128& value, bool negative, Duration* duration) {
419   int64 seconds = static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
420   int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
421   if (negative) {
422     seconds = -seconds;
423     nanos = -nanos;
424   }
425   duration->set_seconds(seconds);
426   duration->set_nanos(nanos);
427 }
428 }  // namespace
429 
operator +=(Duration & d1,const Duration & d2)430 Duration& operator+=(Duration& d1, const Duration& d2) {
431   d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
432                                   d1.nanos() + d2.nanos());
433   return d1;
434 }
435 
operator -=(Duration & d1,const Duration & d2)436 Duration& operator-=(Duration& d1, const Duration& d2) {  // NOLINT
437   d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
438                                   d1.nanos() - d2.nanos());
439   return d1;
440 }
441 
operator *=(Duration & d,int64 r)442 Duration& operator*=(Duration& d, int64 r) {  // NOLINT
443   bool negative;
444   uint128 value;
445   ToUint128(d, &value, &negative);
446   if (r > 0) {
447     value *= static_cast<uint64>(r);
448   } else {
449     negative = !negative;
450     value *= static_cast<uint64>(-r);
451   }
452   ToDuration(value, negative, &d);
453   return d;
454 }
455 
operator *=(Duration & d,double r)456 Duration& operator*=(Duration& d, double r) {  // NOLINT
457   double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
458   int64 seconds = static_cast<int64>(result);
459   int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
460   // Note that we normalize here not just because nanos can have a different
461   // sign from seconds but also that nanos can be any arbitrary value when
462   // overflow happens (i.e., the result is a much larger value than what
463   // int64 can represent).
464   d = CreateNormalized<Duration>(seconds, nanos);
465   return d;
466 }
467 
operator /=(Duration & d,int64 r)468 Duration& operator/=(Duration& d, int64 r) {  // NOLINT
469   bool negative;
470   uint128 value;
471   ToUint128(d, &value, &negative);
472   if (r > 0) {
473     value /= static_cast<uint64>(r);
474   } else {
475     negative = !negative;
476     value /= static_cast<uint64>(-r);
477   }
478   ToDuration(value, negative, &d);
479   return d;
480 }
481 
operator /=(Duration & d,double r)482 Duration& operator/=(Duration& d, double r) {  // NOLINT
483   return d *= 1.0 / r;
484 }
485 
operator %=(Duration & d1,const Duration & d2)486 Duration& operator%=(Duration& d1, const Duration& d2) {  // NOLINT
487   bool negative1, negative2;
488   uint128 value1, value2;
489   ToUint128(d1, &value1, &negative1);
490   ToUint128(d2, &value2, &negative2);
491   uint128 result = value1 % value2;
492   // When negative values are involved in division, we round the division
493   // result towards zero. With this semantics, sign of the remainder is the
494   // same as the dividend. For example:
495   //     -5 / 10    = 0, -5 % 10    = -5
496   //     -5 / (-10) = 0, -5 % (-10) = -5
497   //      5 / (-10) = 0,  5 % (-10) = 5
498   ToDuration(result, negative1, &d1);
499   return d1;
500 }
501 
operator /(const Duration & d1,const Duration & d2)502 int64 operator/(const Duration& d1, const Duration& d2) {
503   bool negative1, negative2;
504   uint128 value1, value2;
505   ToUint128(d1, &value1, &negative1);
506   ToUint128(d2, &value2, &negative2);
507   int64 result = Uint128Low64(value1 / value2);
508   if (negative1 != negative2) {
509     result = -result;
510   }
511   return result;
512 }
513 
operator +=(Timestamp & t,const Duration & d)514 Timestamp& operator+=(Timestamp& t, const Duration& d) {  // NOLINT
515   t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
516                                   t.nanos() + d.nanos());
517   return t;
518 }
519 
operator -=(Timestamp & t,const Duration & d)520 Timestamp& operator-=(Timestamp& t, const Duration& d) {  // NOLINT
521   t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
522                                   t.nanos() - d.nanos());
523   return t;
524 }
525 
operator -(const Timestamp & t1,const Timestamp & t2)526 Duration operator-(const Timestamp& t1, const Timestamp& t2) {
527   return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
528                                     t1.nanos() - t2.nanos());
529 }
530 }  // namespace protobuf
531 
532 }  // namespace google
533