aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/util/time_util.h
blob: bbda5380e4f1c41f3f434189998e003f76357135 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Defines utilities for the Timestamp and Duration well known types.

#ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
#define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__

#include <ctime>
#include <ostream>
#include <string>
#ifdef _MSC_VER
#include <winsock2.h>
#else
#include <sys/time.h>
#endif

#include <google/protobuf/duration.pb.h>
#include <google/protobuf/timestamp.pb.h>

#include <google/protobuf/port_def.inc>

namespace google {
namespace protobuf {
namespace util {

// Utility functions for Timestamp and Duration.
class PROTOBUF_EXPORT TimeUtil {
  typedef google::protobuf::Timestamp Timestamp;
  typedef google::protobuf::Duration Duration;

 public:
  // The min/max Timestamp/Duration values we support.
  //
  // For "0001-01-01T00:00:00Z".
  static const int64 kTimestampMinSeconds = -62135596800LL;
  // For "9999-12-31T23:59:59.999999999Z".
  static const int64 kTimestampMaxSeconds = 253402300799LL;
  static const int64 kDurationMinSeconds = -315576000000LL;
  static const int64 kDurationMaxSeconds = 315576000000LL;

  // Converts Timestamp to/from RFC 3339 date string format.
  // Generated output will always be Z-normalized and uses 3, 6 or 9
  // fractional digits as required to represent the exact time. When
  // parsing, any fractional digits (or none) and any offset are
  // accepted as long as they fit into nano-seconds precision.
  // Note that Timestamp can only represent time from
  // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting
  // a Timestamp outside of this range is undefined behavior.
  // See https://www.ietf.org/rfc/rfc3339.txt
  //
  // Example of generated format:
  //   "1972-01-01T10:00:20.021Z"
  //
  // Example of accepted format:
  //   "1972-01-01T10:00:20.021-05:00"
  static std::string ToString(const Timestamp& timestamp);
  static bool FromString(const std::string& value, Timestamp* timestamp);

  // Converts Duration to/from string format. The string format will contains
  // 3, 6, or 9 fractional digits depending on the precision required to
  // represent the exact Duration value. For example:
  //   "1s", "1.010s", "1.000000100s", "-3.100s"
  // The range that can be represented by Duration is from -315,576,000,000
  // to +315,576,000,000 inclusive (in seconds).
  static std::string ToString(const Duration& duration);
  static bool FromString(const std::string& value, Duration* timestamp);

#ifdef GetCurrentTime
#undef GetCurrentTime  // Visual Studio has macro GetCurrentTime
#endif
  // Gets the current UTC time.
  static Timestamp GetCurrentTime();
  // Returns the Time representing "1970-01-01 00:00:00".
  static Timestamp GetEpoch();

  // Converts between Duration and integer types. The behavior is undefined if
  // the input value is not in the valid range of Duration.
  static Duration NanosecondsToDuration(int64 nanos);
  static Duration MicrosecondsToDuration(int64 micros);
  static Duration MillisecondsToDuration(int64 millis);
  static Duration SecondsToDuration(int64 seconds);
  static Duration MinutesToDuration(int64 minutes);
  static Duration HoursToDuration(int64 hours);
  // Result will be truncated towards zero. For example, "-1.5s" will be
  // truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
  // It's undefined behavior if the input duration is not valid or the result
  // exceeds the range of int64. A duration is not valid if it's not in the
  // valid range of Duration, or have an invalid nanos value (i.e., larger
  // than 999999999, less than -999999999, or have a different sign from the
  // seconds part).
  static int64 DurationToNanoseconds(const Duration& duration);
  static int64 DurationToMicroseconds(const Duration& duration);
  static int64 DurationToMilliseconds(const Duration& duration);
  static int64 DurationToSeconds(const Duration& duration);
  static int64 DurationToMinutes(const Duration& duration);
  static int64 DurationToHours(const Duration& duration);
  // Creates Timestamp from integer types. The integer value indicates the
  // time elapsed from Epoch time. The behavior is undefined if the input
  // value is not in the valid range of Timestamp.
  static Timestamp NanosecondsToTimestamp(int64 nanos);
  static Timestamp MicrosecondsToTimestamp(int64 micros);
  static Timestamp MillisecondsToTimestamp(int64 millis);
  static Timestamp SecondsToTimestamp(int64 seconds);
  // Result will be truncated down to the nearest integer value. For example,
  // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
  // and TimestampToSeconds() returns -1. It's undefined behavior if the input
  // Timestamp is not valid (i.e., its seconds part or nanos part does not fall
  // in the valid range) or the return value doesn't fit into int64.
  static int64 TimestampToNanoseconds(const Timestamp& timestamp);
  static int64 TimestampToMicroseconds(const Timestamp& timestamp);
  static int64 TimestampToMilliseconds(const Timestamp& timestamp);
  static int64 TimestampToSeconds(const Timestamp& timestamp);

  // Conversion to/from other time/date types. Note that these types may
  // have a different precision and time range from Timestamp/Duration.
  // When converting to a lower precision type, the value will be truncated
  // to the nearest value that can be represented. If the value is
  // out of the range of the result type, the return value is undefined.
  //
  // Conversion to/from time_t
  static Timestamp TimeTToTimestamp(time_t value);
  static time_t TimestampToTimeT(const Timestamp& value);

  // Conversion to/from timeval
  static Timestamp TimevalToTimestamp(const timeval& value);
  static timeval TimestampToTimeval(const Timestamp& value);
  static Duration TimevalToDuration(const timeval& value);
  static timeval DurationToTimeval(const Duration& value);
};

}  // namespace util
}  // namespace protobuf
}  // namespace google

namespace google {
namespace protobuf {
// Overloaded operators for Duration.
//
// Assignment operators.
PROTOBUF_EXPORT Duration& operator+=(Duration& d1,
                                     const Duration& d2);  // NOLINT
PROTOBUF_EXPORT Duration& operator-=(Duration& d1,
                                     const Duration& d2);     // NOLINT
PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64 r);   // NOLINT
PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r);  // NOLINT
PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64 r);   // NOLINT
PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r);  // NOLINT
// Overload for other integer types.
template <typename T>
Duration& operator*=(Duration& d, T r) {  // NOLINT
  int64 x = r;
  return d *= x;
}
template <typename T>
Duration& operator/=(Duration& d, T r) {  // NOLINT
  int64 x = r;
  return d /= x;
}
PROTOBUF_EXPORT Duration& operator%=(Duration& d1,
                                     const Duration& d2);  // NOLINT
// Relational operators.
inline bool operator<(const Duration& d1, const Duration& d2) {
  if (d1.seconds() == d2.seconds()) {
    return d1.nanos() < d2.nanos();
  }
  return d1.seconds() < d2.seconds();
}
inline bool operator>(const Duration& d1, const Duration& d2) {
  return d2 < d1;
}
inline bool operator>=(const Duration& d1, const Duration& d2) {
  return !(d1 < d2);
}
inline bool operator<=(const Duration& d1, const Duration& d2) {
  return !(d2 < d1);
}
inline bool operator==(const Duration& d1, const Duration& d2) {
  return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos();
}
inline bool operator!=(const Duration& d1, const Duration& d2) {
  return !(d1 == d2);
}
// Additive operators
inline Duration operator-(const Duration& d) {
  Duration result;
  result.set_seconds(-d.seconds());
  result.set_nanos(-d.nanos());
  return result;
}
inline Duration operator+(const Duration& d1, const Duration& d2) {
  Duration result = d1;
  return result += d2;
}
inline Duration operator-(const Duration& d1, const Duration& d2) {
  Duration result = d1;
  return result -= d2;
}
// Multiplicative operators
template<typename T>
inline Duration operator*(Duration d, T r) {
  return d *= r;
}
template<typename T>
inline Duration operator*(T r, Duration d) {
  return d *= r;
}
template<typename T>
inline Duration operator/(Duration d, T r) {
  return d /= r;
}
PROTOBUF_EXPORT int64 operator/(const Duration& d1, const Duration& d2);

inline Duration operator%(const Duration& d1, const Duration& d2) {
  Duration result = d1;
  return result %= d2;
}

inline std::ostream& operator<<(std::ostream& out, const Duration& d) {
  out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(d);
  return out;
}

// Overloaded operators for Timestamp
//
// Assignement operators.
PROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t,
                                      const Duration& d);  // NOLINT
PROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t,
                                      const Duration& d);  // NOLINT
// Relational operators.
inline bool operator<(const Timestamp& t1, const Timestamp& t2) {
  if (t1.seconds() == t2.seconds()) {
    return t1.nanos() < t2.nanos();
  }
  return t1.seconds() < t2.seconds();
}
inline bool operator>(const Timestamp& t1, const Timestamp& t2) {
  return t2 < t1;
}
inline bool operator>=(const Timestamp& t1, const Timestamp& t2) {
  return !(t1 < t2);
}
inline bool operator<=(const Timestamp& t1, const Timestamp& t2) {
  return !(t2 < t1);
}
inline bool operator==(const Timestamp& t1, const Timestamp& t2) {
  return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos();
}
inline bool operator!=(const Timestamp& t1, const Timestamp& t2) {
  return !(t1 == t2);
}
// Additive operators.
inline Timestamp operator+(const Timestamp& t, const Duration& d) {
  Timestamp result = t;
  return result += d;
}
inline Timestamp operator+(const Duration& d, const Timestamp& t) {
  Timestamp result = t;
  return result += d;
}
inline Timestamp operator-(const Timestamp& t, const Duration& d) {
  Timestamp result = t;
  return result -= d;
}
PROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2);

inline std::ostream& operator<<(std::ostream& out, const Timestamp& t) {
  out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(t);
  return out;
}

}  // namespace protobuf
}  // namespace google

#include <google/protobuf/port_undef.inc>

#endif  // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__