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 // Defines utilities for the Timestamp and Duration well known types. 9 10 #ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ 11 #define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ 12 13 #include <cstdint> 14 #include <ctime> 15 #include <ostream> 16 #include <string> 17 #ifdef _MSC_VER 18 #ifdef _XBOX_ONE 19 struct timeval { 20 int64_t tv_sec; /* seconds */ 21 int64_t tv_usec; /* and microseconds */ 22 }; 23 #else 24 #include <winsock2.h> 25 #endif // _XBOX_ONE 26 #else 27 #include <sys/time.h> 28 #endif 29 30 #include "google/protobuf/duration.pb.h" 31 #include "google/protobuf/timestamp.pb.h" 32 33 // Must be included last. 34 #include "google/protobuf/port_def.inc" 35 36 namespace google { 37 namespace protobuf { 38 namespace util { 39 40 // Utility functions for Timestamp and Duration. 41 class PROTOBUF_EXPORT TimeUtil { 42 typedef google::protobuf::Timestamp Timestamp; 43 typedef google::protobuf::Duration Duration; 44 45 public: 46 // The min/max Timestamp/Duration values we support. 47 // 48 // For "0001-01-01T00:00:00Z". 49 static constexpr int64_t kTimestampMinSeconds = -62135596800LL; 50 // For "9999-12-31T23:59:59.999999999Z". 51 static constexpr int64_t kTimestampMaxSeconds = 253402300799LL; 52 static constexpr int32_t kTimestampMinNanoseconds = 0; 53 static constexpr int32_t kTimestampMaxNanoseconds = 999999999; 54 static constexpr int64_t kDurationMinSeconds = -315576000000LL; 55 static constexpr int64_t kDurationMaxSeconds = 315576000000LL; 56 static constexpr int32_t kDurationMinNanoseconds = -999999999; 57 static constexpr int32_t kDurationMaxNanoseconds = 999999999; 58 IsTimestampValid(const Timestamp & timestamp)59 static bool IsTimestampValid(const Timestamp& timestamp) { 60 return timestamp.seconds() <= kTimestampMaxSeconds && 61 timestamp.seconds() >= kTimestampMinSeconds && 62 timestamp.nanos() <= kTimestampMaxNanoseconds && 63 timestamp.nanos() >= kTimestampMinNanoseconds; 64 } 65 IsDurationValid(const Duration & duration)66 static bool IsDurationValid(const Duration& duration) { 67 return duration.seconds() <= kDurationMaxSeconds && 68 duration.seconds() >= kDurationMinSeconds && 69 duration.nanos() <= kDurationMaxNanoseconds && 70 duration.nanos() >= kDurationMinNanoseconds && 71 !(duration.seconds() >= 1 && duration.nanos() < 0) && 72 !(duration.seconds() <= -1 && duration.nanos() > 0); 73 } 74 75 // Converts Timestamp to/from RFC 3339 date string format. 76 // Generated output will always be Z-normalized and uses 3, 6 or 9 77 // fractional digits as required to represent the exact time. When 78 // parsing, any fractional digits (or none) and any offset are 79 // accepted as long as they fit into nano-seconds precision. 80 // Note that Timestamp can only represent time from 81 // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting 82 // a Timestamp outside of this range is undefined behavior. 83 // See https://www.ietf.org/rfc/rfc3339.txt 84 // 85 // Example of generated format: 86 // "1972-01-01T10:00:20.021Z" 87 // 88 // Example of accepted format: 89 // "1972-01-01T10:00:20.021-05:00" 90 static std::string ToString(const Timestamp& timestamp); 91 static bool FromString(absl::string_view value, Timestamp* timestamp); 92 93 // Converts Duration to/from string format. The string format will contains 94 // 3, 6, or 9 fractional digits depending on the precision required to 95 // represent the exact Duration value. For example: 96 // "1s", "1.010s", "1.000000100s", "-3.100s" 97 // The range that can be represented by Duration is from -315,576,000,000 98 // to +315,576,000,000 inclusive (in seconds). 99 static std::string ToString(const Duration& duration); 100 static bool FromString(absl::string_view value, Duration* duration); 101 102 // Gets the current UTC time. 103 static Timestamp GetCurrentTime(); 104 // Returns the Time representing "1970-01-01 00:00:00". 105 static Timestamp GetEpoch(); 106 107 // Converts between Duration and integer types. The behavior is undefined if 108 // the input value is not in the valid range of Duration. 109 static Duration NanosecondsToDuration(int64_t nanos); 110 static Duration MicrosecondsToDuration(int64_t micros); 111 static Duration MillisecondsToDuration(int64_t millis); 112 static Duration SecondsToDuration(int64_t seconds); 113 static Duration MinutesToDuration(int64_t minutes); 114 static Duration HoursToDuration(int64_t hours); 115 // Result will be truncated towards zero. For example, "-1.5s" will be 116 // truncated to "-1s", and "1.5s" to "1s" when converting to seconds. 117 // It's undefined behavior if the input duration is not valid or the result 118 // exceeds the range of int64. A duration is not valid if it's not in the 119 // valid range of Duration, or have an invalid nanos value (i.e., larger 120 // than 999999999, less than -999999999, or have a different sign from the 121 // seconds part). 122 static int64_t DurationToNanoseconds(const Duration& duration); 123 static int64_t DurationToMicroseconds(const Duration& duration); 124 static int64_t DurationToMilliseconds(const Duration& duration); 125 static int64_t DurationToSeconds(const Duration& duration); 126 static int64_t DurationToMinutes(const Duration& duration); 127 static int64_t DurationToHours(const Duration& duration); 128 // Creates Timestamp from integer types. The integer value indicates the 129 // time elapsed from Epoch time. The behavior is undefined if the input 130 // value is not in the valid range of Timestamp. 131 static Timestamp NanosecondsToTimestamp(int64_t nanos); 132 static Timestamp MicrosecondsToTimestamp(int64_t micros); 133 static Timestamp MillisecondsToTimestamp(int64_t millis); 134 static Timestamp SecondsToTimestamp(int64_t seconds); 135 // Result will be truncated down to the nearest integer value. For example, 136 // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100 137 // and TimestampToSeconds() returns -1. It's undefined behavior if the input 138 // Timestamp is not valid (i.e., its seconds part or nanos part does not fall 139 // in the valid range) or the return value doesn't fit into int64. 140 static int64_t TimestampToNanoseconds(const Timestamp& timestamp); 141 static int64_t TimestampToMicroseconds(const Timestamp& timestamp); 142 static int64_t TimestampToMilliseconds(const Timestamp& timestamp); 143 static int64_t TimestampToSeconds(const Timestamp& timestamp); 144 145 // Conversion to/from other time/date types. Note that these types may 146 // have a different precision and time range from Timestamp/Duration. 147 // When converting to a lower precision type, the value will be truncated 148 // to the nearest value that can be represented. If the value is 149 // out of the range of the result type, the return value is undefined. 150 // 151 // Conversion to/from time_t 152 static Timestamp TimeTToTimestamp(time_t value); 153 static time_t TimestampToTimeT(const Timestamp& value); 154 155 // Conversion to/from timeval 156 static Timestamp TimevalToTimestamp(const timeval& value); 157 static timeval TimestampToTimeval(const Timestamp& value); 158 static Duration TimevalToDuration(const timeval& value); 159 static timeval DurationToTimeval(const Duration& value); 160 }; 161 162 } // namespace util 163 } // namespace protobuf 164 } // namespace google 165 166 namespace google { 167 namespace protobuf { 168 // Overloaded operators for Duration. 169 // 170 // Assignment operators. 171 PROTOBUF_EXPORT Duration& operator+=(Duration& d1, 172 const Duration& d2); // NOLINT 173 PROTOBUF_EXPORT Duration& operator-=(Duration& d1, 174 const Duration& d2); // NOLINT 175 PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64_t r); // NOLINT 176 PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r); // NOLINT 177 PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64_t r); // NOLINT 178 PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r); // NOLINT 179 // Overload for other integer types. 180 template <typename T> 181 Duration& operator*=(Duration& d, T r) { // NOLINT 182 int64_t x = r; 183 return d *= x; 184 } 185 template <typename T> 186 Duration& operator/=(Duration& d, T r) { // NOLINT 187 int64_t x = r; 188 return d /= x; 189 } 190 PROTOBUF_EXPORT Duration& operator%=(Duration& d1, 191 const Duration& d2); // NOLINT 192 // Relational operators. 193 inline bool operator<(const Duration& d1, const Duration& d2) { 194 if (d1.seconds() == d2.seconds()) { 195 return d1.nanos() < d2.nanos(); 196 } 197 return d1.seconds() < d2.seconds(); 198 } 199 inline bool operator>(const Duration& d1, const Duration& d2) { 200 return d2 < d1; 201 } 202 inline bool operator>=(const Duration& d1, const Duration& d2) { 203 return !(d1 < d2); 204 } 205 inline bool operator<=(const Duration& d1, const Duration& d2) { 206 return !(d2 < d1); 207 } 208 inline bool operator==(const Duration& d1, const Duration& d2) { 209 return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos(); 210 } 211 inline bool operator!=(const Duration& d1, const Duration& d2) { 212 return !(d1 == d2); 213 } 214 // Additive operators 215 inline Duration operator-(const Duration& d) { 216 Duration result; 217 result.set_seconds(-d.seconds()); 218 result.set_nanos(-d.nanos()); 219 return result; 220 } 221 inline Duration operator+(const Duration& d1, const Duration& d2) { 222 Duration result = d1; 223 return result += d2; 224 } 225 inline Duration operator-(const Duration& d1, const Duration& d2) { 226 Duration result = d1; 227 return result -= d2; 228 } 229 // Multiplicative operators 230 template <typename T> 231 inline Duration operator*(Duration d, T r) { 232 return d *= r; 233 } 234 template <typename T> 235 inline Duration operator*(T r, Duration d) { 236 return d *= r; 237 } 238 template <typename T> 239 inline Duration operator/(Duration d, T r) { 240 return d /= r; 241 } 242 PROTOBUF_EXPORT int64_t operator/(const Duration& d1, const Duration& d2); 243 244 inline Duration operator%(const Duration& d1, const Duration& d2) { 245 Duration result = d1; 246 return result %= d2; 247 } 248 249 inline std::ostream& operator<<(std::ostream& out, const Duration& d) { 250 out << google::protobuf::util::TimeUtil::ToString(d); 251 return out; 252 } 253 254 // Overloaded operators for Timestamp 255 // 256 // Assignment operators. 257 PROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t, 258 const Duration& d); // NOLINT 259 PROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t, 260 const Duration& d); // NOLINT 261 // Relational operators. 262 inline bool operator<(const Timestamp& t1, const Timestamp& t2) { 263 if (t1.seconds() == t2.seconds()) { 264 return t1.nanos() < t2.nanos(); 265 } 266 return t1.seconds() < t2.seconds(); 267 } 268 inline bool operator>(const Timestamp& t1, const Timestamp& t2) { 269 return t2 < t1; 270 } 271 inline bool operator>=(const Timestamp& t1, const Timestamp& t2) { 272 return !(t1 < t2); 273 } 274 inline bool operator<=(const Timestamp& t1, const Timestamp& t2) { 275 return !(t2 < t1); 276 } 277 inline bool operator==(const Timestamp& t1, const Timestamp& t2) { 278 return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos(); 279 } 280 inline bool operator!=(const Timestamp& t1, const Timestamp& t2) { 281 return !(t1 == t2); 282 } 283 // Additive operators. 284 inline Timestamp operator+(const Timestamp& t, const Duration& d) { 285 Timestamp result = t; 286 return result += d; 287 } 288 inline Timestamp operator+(const Duration& d, const Timestamp& t) { 289 Timestamp result = t; 290 return result += d; 291 } 292 inline Timestamp operator-(const Timestamp& t, const Duration& d) { 293 Timestamp result = t; 294 return result -= d; 295 } 296 PROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2); 297 298 inline std::ostream& operator<<(std::ostream& out, const Timestamp& t) { 299 out << google::protobuf::util::TimeUtil::ToString(t); 300 return out; 301 } 302 303 } // namespace protobuf 304 } // namespace google 305 306 #include "google/protobuf/port_undef.inc" 307 308 #endif // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ 309