• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/util/time_util.h"
9 
10 #include <cstdint>
11 #include <cstdlib>
12 
13 #include "google/protobuf/duration.pb.h"
14 #include "google/protobuf/timestamp.pb.h"
15 #include "absl/log/absl_check.h"
16 #include "absl/numeric/int128.h"
17 #include "absl/strings/str_cat.h"
18 #include "absl/strings/str_format.h"
19 #include "absl/strings/string_view.h"
20 #include "absl/time/clock.h"
21 #include "absl/time/time.h"
22 
23 // Must go after other includes.
24 #include "google/protobuf/port_def.inc"
25 
26 namespace google {
27 namespace protobuf {
28 namespace util {
29 
30 using google::protobuf::Duration;
31 using google::protobuf::Timestamp;
32 
33 namespace {
34 static constexpr int32_t kNanosPerSecond = 1000000000;
35 static constexpr int32_t kMicrosPerSecond = 1000000;
36 static constexpr int32_t kMillisPerSecond = 1000;
37 static constexpr int32_t kNanosPerMillisecond = 1000000;
38 static constexpr int32_t kNanosPerMicrosecond = 1000;
39 static constexpr int32_t kSecondsPerMinute =
40     60;  // Note that we ignore leap seconds.
41 static constexpr int32_t kSecondsPerHour = 3600;
42 
43 template <typename T>
44 T CreateNormalized(int64_t seconds, int32_t nanos);
45 
46 template <>
CreateNormalized(int64_t seconds,int32_t nanos)47 Timestamp CreateNormalized(int64_t seconds, int32_t nanos) {
48   ABSL_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
49               seconds <= TimeUtil::kTimestampMaxSeconds)
50       << "Timestamp seconds are outside of the valid range";
51 
52   // Make sure nanos is in the range.
53   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
54     seconds += nanos / kNanosPerSecond;
55     nanos = nanos % kNanosPerSecond;
56   }
57   // For Timestamp nanos should be in the range [0, 999999999]
58   if (nanos < 0) {
59     seconds -= 1;
60     nanos += kNanosPerSecond;
61   }
62 
63   ABSL_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
64               seconds <= TimeUtil::kTimestampMaxSeconds &&
65               nanos >= TimeUtil::kTimestampMinNanoseconds &&
66               nanos <= TimeUtil::kTimestampMaxNanoseconds)
67       << "Timestamp is outside of the valid range";
68   Timestamp result;
69   result.set_seconds(seconds);
70   result.set_nanos(static_cast<int32_t>(nanos));
71   return result;
72 }
73 
74 template <>
CreateNormalized(int64_t seconds,int32_t nanos)75 Duration CreateNormalized(int64_t seconds, int32_t nanos) {
76   ABSL_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
77               seconds <= TimeUtil::kDurationMaxSeconds)
78       << "Duration seconds are outside of the valid range";
79 
80   // Make sure nanos is in the range.
81   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
82     seconds += nanos / kNanosPerSecond;
83     nanos = nanos % kNanosPerSecond;
84   }
85   // nanos should have the same sign as seconds.
86   if (seconds < 0 && nanos > 0) {
87     seconds += 1;
88     nanos -= kNanosPerSecond;
89   } else if (seconds > 0 && nanos < 0) {
90     seconds -= 1;
91     nanos += kNanosPerSecond;
92   }
93 
94   ABSL_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
95               seconds <= TimeUtil::kDurationMaxSeconds &&
96               nanos >= TimeUtil::kDurationMinNanoseconds &&
97               nanos <= TimeUtil::kDurationMaxNanoseconds)
98       << "Duration is outside of the valid range";
99   Duration result;
100   result.set_seconds(seconds);
101   result.set_nanos(static_cast<int32_t>(nanos));
102   return result;
103 }
104 
105 // Format nanoseconds with either 3, 6, or 9 digits depending on the required
106 // precision to represent the exact value.
FormatNanos(int32_t nanos)107 std::string FormatNanos(int32_t nanos) {
108   if (nanos % kNanosPerMillisecond == 0) {
109     return absl::StrFormat("%03d", nanos / kNanosPerMillisecond);
110   } else if (nanos % kNanosPerMicrosecond == 0) {
111     return absl::StrFormat("%06d", nanos / kNanosPerMicrosecond);
112   } else {
113     return absl::StrFormat("%09d", nanos);
114   }
115 }
116 
FormatTime(int64_t seconds,int32_t nanos)117 std::string FormatTime(int64_t seconds, int32_t nanos) {
118   static constexpr absl::string_view kTimestampFormat = "%E4Y-%m-%dT%H:%M:%S";
119 
120   timespec spec;
121   spec.tv_sec = seconds;
122   // We only use absl::FormatTime to format the seconds part because we need
123   // finer control over the precision of nanoseconds.
124   spec.tv_nsec = 0;
125   std::string result = absl::FormatTime(
126       kTimestampFormat, absl::TimeFromTimespec(spec), absl::UTCTimeZone());
127   // We format the nanoseconds part separately to meet the precision
128   // requirement.
129   if (nanos != 0) {
130     absl::StrAppend(&result, ".", FormatNanos(nanos));
131   }
132   absl::StrAppend(&result, "Z");
133   return result;
134 }
135 
ParseTime(absl::string_view value,int64_t * seconds,int32_t * nanos)136 bool ParseTime(absl::string_view value, int64_t* seconds, int32_t* nanos) {
137   absl::Time result;
138   if (!absl::ParseTime(absl::RFC3339_full, value, &result, nullptr)) {
139     return false;
140   }
141   timespec spec = absl::ToTimespec(result);
142   *seconds = spec.tv_sec;
143   *nanos = spec.tv_nsec;
144   return true;
145 }
146 
CurrentTime(int64_t * seconds,int32_t * nanos)147 void CurrentTime(int64_t* seconds, int32_t* nanos) {
148   absl::Time now = absl::Now();
149   timespec spec = absl::ToTimespec(now);
150   *seconds = spec.tv_sec;
151   *nanos = spec.tv_nsec;
152 }
153 
154 // Truncates the remainder part after division.
RoundTowardZero(int64_t value,int64_t divider)155 int64_t RoundTowardZero(int64_t value, int64_t divider) {
156   int64_t result = value / divider;
157   int64_t remainder = value % divider;
158   // Before C++11, the sign of the remainder is implementation dependent if
159   // any of the operands is negative. Here we try to enforce C++11's "rounded
160   // toward zero" semantics. For example, for (-5) / 2 an implementation may
161   // give -3 as the result with the remainder being 1. This function ensures
162   // we always return -2 (closer to zero) regardless of the implementation.
163   if (result < 0 && remainder > 0) {
164     return result + 1;
165   } else {
166     return result;
167   }
168 }
169 }  // namespace
170 
171 // Actually define these static const integers. Required by C++ standard (but
172 // some compilers don't like it).
173 #ifndef _MSC_VER
174 constexpr int64_t TimeUtil::kTimestampMinSeconds;
175 constexpr int64_t TimeUtil::kTimestampMaxSeconds;
176 constexpr int32_t TimeUtil::kTimestampMinNanoseconds;
177 constexpr int32_t TimeUtil::kTimestampMaxNanoseconds;
178 constexpr int64_t TimeUtil::kDurationMaxSeconds;
179 constexpr int64_t TimeUtil::kDurationMinSeconds;
180 constexpr int32_t TimeUtil::kDurationMaxNanoseconds;
181 constexpr int32_t TimeUtil::kDurationMinNanoseconds;
182 #endif  // !_MSC_VER
183 
ToString(const Timestamp & timestamp)184 std::string TimeUtil::ToString(const Timestamp& timestamp) {
185   return FormatTime(timestamp.seconds(), timestamp.nanos());
186 }
187 
FromString(absl::string_view value,Timestamp * timestamp)188 bool TimeUtil::FromString(absl::string_view value, Timestamp* timestamp) {
189   int64_t seconds;
190   int32_t nanos;
191   if (!ParseTime(value, &seconds, &nanos)) {
192     return false;
193   }
194   *timestamp = CreateNormalized<Timestamp>(seconds, nanos);
195   return true;
196 }
197 
GetCurrentTime()198 Timestamp TimeUtil::GetCurrentTime() {
199   int64_t seconds;
200   int32_t nanos;
201   CurrentTime(&seconds, &nanos);
202   return CreateNormalized<Timestamp>(seconds, nanos);
203 }
204 
GetEpoch()205 Timestamp TimeUtil::GetEpoch() { return Timestamp(); }
206 
ToString(const Duration & duration)207 std::string TimeUtil::ToString(const Duration& duration) {
208   std::string result;
209   int64_t seconds = duration.seconds();
210   int32_t nanos = duration.nanos();
211   if (seconds < 0 || nanos < 0) {
212     result = "-";
213     seconds = -seconds;
214     nanos = -nanos;
215   }
216   absl::StrAppend(&result, seconds);
217   if (nanos != 0) {
218     absl::StrAppend(&result, ".", FormatNanos(nanos));
219   }
220   absl::StrAppend(&result, "s");
221   return result;
222 }
223 
Pow(int64_t x,int y)224 static int64_t Pow(int64_t x, int y) {
225   int64_t result = 1;
226   for (int i = 0; i < y; ++i) {
227     result *= x;
228   }
229   return result;
230 }
231 
FromString(absl::string_view value,Duration * duration)232 bool TimeUtil::FromString(absl::string_view value, Duration* duration) {
233   if (value.length() <= 1 || value[value.length() - 1] != 's') {
234     return false;
235   }
236   bool negative = (value[0] == '-');
237   size_t sign_length = (negative ? 1 : 0);
238   // Parse the duration value as two integers rather than a float value
239   // to avoid precision loss.
240   std::string seconds_part, nanos_part;
241   size_t pos = value.find_last_of('.');
242   if (pos == std::string::npos) {
243     seconds_part = std::string(
244         value.substr(sign_length, value.length() - 1 - sign_length));
245     nanos_part = "0";
246   } else {
247     seconds_part = std::string(value.substr(sign_length, pos - sign_length));
248     nanos_part = std::string(value.substr(pos + 1, value.length() - pos - 2));
249   }
250   char* end;
251   static_assert(sizeof(int64_t) == sizeof(long long),
252                 "sizeof int64_t is not sizeof long long");
253   int64_t seconds = std::strtoll(seconds_part.c_str(), &end, 10);
254   if (end != seconds_part.c_str() + seconds_part.length()) {
255     return false;
256   }
257   int64_t nanos = std::strtoll(nanos_part.c_str(), &end, 10);
258   if (end != nanos_part.c_str() + nanos_part.length()) {
259     return false;
260   }
261   nanos = nanos * Pow(10, static_cast<int>(9 - nanos_part.length()));
262   if (negative) {
263     // If a Duration is negative, both seconds and nanos should be negative.
264     seconds = -seconds;
265     nanos = -nanos;
266   }
267   duration->set_seconds(seconds);
268   duration->set_nanos(static_cast<int32_t>(nanos));
269   return true;
270 }
271 
NanosecondsToDuration(int64_t nanos)272 Duration TimeUtil::NanosecondsToDuration(int64_t nanos) {
273   return CreateNormalized<Duration>(nanos / kNanosPerSecond,
274                                     nanos % kNanosPerSecond);
275 }
276 
MicrosecondsToDuration(int64_t micros)277 Duration TimeUtil::MicrosecondsToDuration(int64_t micros) {
278   return CreateNormalized<Duration>(
279       micros / kMicrosPerSecond,
280       (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
281 }
282 
MillisecondsToDuration(int64_t millis)283 Duration TimeUtil::MillisecondsToDuration(int64_t millis) {
284   return CreateNormalized<Duration>(
285       millis / kMillisPerSecond,
286       (millis % kMillisPerSecond) * kNanosPerMillisecond);
287 }
288 
SecondsToDuration(int64_t seconds)289 Duration TimeUtil::SecondsToDuration(int64_t seconds) {
290   return CreateNormalized<Duration>(seconds, 0);
291 }
292 
MinutesToDuration(int64_t minutes)293 Duration TimeUtil::MinutesToDuration(int64_t minutes) {
294   ABSL_DCHECK(minutes >= TimeUtil::kDurationMinSeconds / kSecondsPerMinute &&
295               minutes <= TimeUtil::kDurationMaxSeconds / kSecondsPerMinute)
296       << "Duration minutes are outside of the valid range";
297   return SecondsToDuration(minutes * kSecondsPerMinute);
298 }
299 
HoursToDuration(int64_t hours)300 Duration TimeUtil::HoursToDuration(int64_t hours) {
301   ABSL_DCHECK(hours >= TimeUtil::kDurationMinSeconds / kSecondsPerHour &&
302               hours <= TimeUtil::kDurationMaxSeconds / kSecondsPerHour)
303       << "Duration hours are outside of the valid range";
304   return SecondsToDuration(hours * kSecondsPerHour);
305 }
306 
DurationToNanoseconds(const Duration & duration)307 int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) {
308   ABSL_DCHECK(IsDurationValid(duration))
309       << "Duration is outside of the valid range";
310   return duration.seconds() * kNanosPerSecond + duration.nanos();
311 }
312 
DurationToMicroseconds(const Duration & duration)313 int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) {
314   return DurationToSeconds(duration) * kMicrosPerSecond +
315          RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
316 }
317 
DurationToMilliseconds(const Duration & duration)318 int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) {
319   return DurationToSeconds(duration) * kMillisPerSecond +
320          RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
321 }
322 
DurationToSeconds(const Duration & duration)323 int64_t TimeUtil::DurationToSeconds(const Duration& duration) {
324   ABSL_DCHECK(IsDurationValid(duration))
325       << "Duration is outside of the valid range";
326   return duration.seconds();
327 }
328 
DurationToMinutes(const Duration & duration)329 int64_t TimeUtil::DurationToMinutes(const Duration& duration) {
330   return RoundTowardZero(DurationToSeconds(duration), kSecondsPerMinute);
331 }
332 
DurationToHours(const Duration & duration)333 int64_t TimeUtil::DurationToHours(const Duration& duration) {
334   return RoundTowardZero(DurationToSeconds(duration), kSecondsPerHour);
335 }
336 
NanosecondsToTimestamp(int64_t nanos)337 Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) {
338   return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
339                                      nanos % kNanosPerSecond);
340 }
341 
MicrosecondsToTimestamp(int64_t micros)342 Timestamp TimeUtil::MicrosecondsToTimestamp(int64_t micros) {
343   return CreateNormalized<Timestamp>(
344       micros / kMicrosPerSecond,
345       micros % kMicrosPerSecond * kNanosPerMicrosecond);
346 }
347 
MillisecondsToTimestamp(int64_t millis)348 Timestamp TimeUtil::MillisecondsToTimestamp(int64_t millis) {
349   return CreateNormalized<Timestamp>(
350       millis / kMillisPerSecond,
351       millis % kMillisPerSecond * kNanosPerMillisecond);
352 }
353 
SecondsToTimestamp(int64_t seconds)354 Timestamp TimeUtil::SecondsToTimestamp(int64_t seconds) {
355   return CreateNormalized<Timestamp>(seconds, 0);
356 }
357 
TimestampToNanoseconds(const Timestamp & timestamp)358 int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
359   ABSL_DCHECK(IsTimestampValid(timestamp))
360       << "Timestamp is outside of the valid range";
361   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
362 }
363 
TimestampToMicroseconds(const Timestamp & timestamp)364 int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
365   ABSL_DCHECK(IsTimestampValid(timestamp))
366       << "Timestamp is outside of the valid range";
367   return timestamp.seconds() * kMicrosPerSecond +
368          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
369 }
370 
TimestampToMilliseconds(const Timestamp & timestamp)371 int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
372   ABSL_DCHECK(IsTimestampValid(timestamp))
373       << "Timestamp is outside of the valid range";
374   return timestamp.seconds() * kMillisPerSecond +
375          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
376 }
377 
TimestampToSeconds(const Timestamp & timestamp)378 int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
379   ABSL_DCHECK(IsTimestampValid(timestamp))
380       << "Timestamp is outside of the valid range";
381   return timestamp.seconds();
382 }
383 
TimeTToTimestamp(time_t value)384 Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
385   return CreateNormalized<Timestamp>(static_cast<int64_t>(value), 0);
386 }
387 
TimestampToTimeT(const Timestamp & value)388 time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
389   return static_cast<time_t>(value.seconds());
390 }
391 
TimevalToTimestamp(const timeval & value)392 Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) {
393   return CreateNormalized<Timestamp>(value.tv_sec,
394                                      value.tv_usec * kNanosPerMicrosecond);
395 }
396 
TimestampToTimeval(const Timestamp & value)397 timeval TimeUtil::TimestampToTimeval(const Timestamp& value) {
398   timeval result;
399   result.tv_sec = value.seconds();
400   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
401   return result;
402 }
403 
TimevalToDuration(const timeval & value)404 Duration TimeUtil::TimevalToDuration(const timeval& value) {
405   return CreateNormalized<Duration>(value.tv_sec,
406                                     value.tv_usec * kNanosPerMicrosecond);
407 }
408 
DurationToTimeval(const Duration & value)409 timeval TimeUtil::DurationToTimeval(const Duration& value) {
410   timeval result;
411   result.tv_sec = value.seconds();
412   result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond);
413   // timeval.tv_usec's range is [0, 1000000)
414   if (result.tv_usec < 0) {
415     result.tv_sec -= 1;
416     result.tv_usec += kMicrosPerSecond;
417   }
418   return result;
419 }
420 
421 }  // namespace util
422 }  // namespace protobuf
423 }  // namespace google
424 
425 namespace google {
426 namespace protobuf {
427 namespace {
428 using ::google::protobuf::util::CreateNormalized;
429 using ::google::protobuf::util::kNanosPerSecond;
430 
431 // Convert a Duration to uint128.
ToUint128(const Duration & value,absl::uint128 * result,bool * negative)432 void ToUint128(const Duration& value, absl::uint128* result, bool* negative) {
433   if (value.seconds() < 0 || value.nanos() < 0) {
434     *negative = true;
435     *result = static_cast<uint64_t>(-value.seconds());
436     *result = *result * kNanosPerSecond + static_cast<uint32_t>(-value.nanos());
437   } else {
438     *negative = false;
439     *result = static_cast<uint64_t>(value.seconds());
440     *result = *result * kNanosPerSecond + static_cast<uint32_t>(value.nanos());
441   }
442 }
443 
ToDuration(const absl::uint128 & value,bool negative,Duration * duration)444 void ToDuration(const absl::uint128& value, bool negative, Duration* duration) {
445   int64_t seconds =
446       static_cast<int64_t>(absl::Uint128Low64(value / kNanosPerSecond));
447   int32_t nanos =
448       static_cast<int32_t>(absl::Uint128Low64(value % kNanosPerSecond));
449   if (negative) {
450     seconds = -seconds;
451     nanos = -nanos;
452   }
453   duration->set_seconds(seconds);
454   duration->set_nanos(nanos);
455 }
456 }  // namespace
457 
operator +=(Duration & d1,const Duration & d2)458 Duration& operator+=(Duration& d1, const Duration& d2) {
459   d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(),
460                                   d1.nanos() + d2.nanos());
461   return d1;
462 }
463 
operator -=(Duration & d1,const Duration & d2)464 Duration& operator-=(Duration& d1, const Duration& d2) {  // NOLINT
465   d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(),
466                                   d1.nanos() - d2.nanos());
467   return d1;
468 }
469 
operator *=(Duration & d,int64_t r)470 Duration& operator*=(Duration& d, int64_t r) {  // NOLINT
471   bool negative;
472   absl::uint128 value;
473   ToUint128(d, &value, &negative);
474   if (r > 0) {
475     value *= static_cast<uint64_t>(r);
476   } else {
477     negative = !negative;
478     value *= static_cast<uint64_t>(-r);
479   }
480   ToDuration(value, negative, &d);
481   return d;
482 }
483 
operator *=(Duration & d,double r)484 Duration& operator*=(Duration& d, double r) {  // NOLINT
485   double result =
486       (static_cast<double>(d.seconds()) + d.nanos() * (1.0 / kNanosPerSecond)) *
487       r;
488   int64_t seconds = static_cast<int64_t>(result);
489   int32_t nanos = static_cast<int32_t>((result - static_cast<double>(seconds)) *
490                                        kNanosPerSecond);
491   // Note that we normalize here not just because nanos can have a different
492   // sign from seconds but also that nanos can be any arbitrary value when
493   // overflow happens (i.e., the result is a much larger value than what
494   // int64 can represent).
495   d = CreateNormalized<Duration>(seconds, nanos);
496   return d;
497 }
498 
operator /=(Duration & d,int64_t r)499 Duration& operator/=(Duration& d, int64_t r) {  // NOLINT
500   bool negative;
501   absl::uint128 value;
502   ToUint128(d, &value, &negative);
503   if (r > 0) {
504     value /= static_cast<uint64_t>(r);
505   } else {
506     negative = !negative;
507     value /= static_cast<uint64_t>(-r);
508   }
509   ToDuration(value, negative, &d);
510   return d;
511 }
512 
operator /=(Duration & d,double r)513 Duration& operator/=(Duration& d, double r) {  // NOLINT
514   return d *= 1.0 / r;
515 }
516 
operator %=(Duration & d1,const Duration & d2)517 Duration& operator%=(Duration& d1, const Duration& d2) {  // NOLINT
518   bool negative1, negative2;
519   absl::uint128 value1, value2;
520   ToUint128(d1, &value1, &negative1);
521   ToUint128(d2, &value2, &negative2);
522   absl::uint128 result = value1 % value2;
523   // When negative values are involved in division, we round the division
524   // result towards zero. With this semantics, sign of the remainder is the
525   // same as the dividend. For example:
526   //     -5 / 10    = 0, -5 % 10    = -5
527   //     -5 / (-10) = 0, -5 % (-10) = -5
528   //      5 / (-10) = 0,  5 % (-10) = 5
529   ToDuration(result, negative1, &d1);
530   return d1;
531 }
532 
operator /(const Duration & d1,const Duration & d2)533 int64_t operator/(const Duration& d1, const Duration& d2) {
534   bool negative1, negative2;
535   absl::uint128 value1, value2;
536   ToUint128(d1, &value1, &negative1);
537   ToUint128(d2, &value2, &negative2);
538   int64_t result = absl::Uint128Low64(value1 / value2);
539   if (negative1 != negative2) {
540     result = -result;
541   }
542   return result;
543 }
544 
operator +=(Timestamp & t,const Duration & d)545 Timestamp& operator+=(Timestamp& t, const Duration& d) {  // NOLINT
546   t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(),
547                                   t.nanos() + d.nanos());
548   return t;
549 }
550 
operator -=(Timestamp & t,const Duration & d)551 Timestamp& operator-=(Timestamp& t, const Duration& d) {  // NOLINT
552   t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(),
553                                   t.nanos() - d.nanos());
554   return t;
555 }
556 
operator -(const Timestamp & t1,const Timestamp & t2)557 Duration operator-(const Timestamp& t1, const Timestamp& t2) {
558   return CreateNormalized<Duration>(t1.seconds() - t2.seconds(),
559                                     t1.nanos() - t2.nanos());
560 }
561 }  // namespace protobuf
562 }  // namespace google
563 
564 #include "google/protobuf/port_undef.inc"
565