Google Cloud Spanner C++ Client
A C++ Client Library for Google Cloud Spanner
timestamp.h
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TIMESTAMP_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TIMESTAMP_H
17 
19 #include "google/cloud/status_or.h"
20 #include <google/protobuf/timestamp.pb.h>
21 #include <chrono>
22 #include <cstdint>
23 #include <limits>
24 #include <ostream>
25 #include <string>
26 #include <tuple>
27 
28 namespace google {
29 namespace cloud {
30 namespace spanner {
31 inline namespace SPANNER_CLIENT_NS {
32 
33 class Timestamp; // defined below
34 
38 template <typename Duration>
39 using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
40 
47 template <typename Duration>
48 StatusOr<Timestamp> MakeTimestamp(sys_time<Duration> const&);
49 
50 namespace internal {
51 
52 // Internal forward declarations to befriend.
53 StatusOr<Timestamp> TimestampFromRFC3339(std::string const&);
54 std::string TimestampToRFC3339(Timestamp);
55 Timestamp TimestampFromProto(protobuf::Timestamp const&);
56 protobuf::Timestamp TimestampToProto(Timestamp);
57 
58 } // namespace internal
59 
73 class Timestamp {
74  public:
76  Timestamp() : Timestamp(0, 0) {}
77 
80  Timestamp(Timestamp&&) = default;
81  Timestamp& operator=(Timestamp&&) = default;
82  Timestamp(Timestamp const&) = default;
83  Timestamp& operator=(Timestamp const&) = default;
85 
88  friend bool operator==(Timestamp const& a, Timestamp const& b) {
89  return std::make_tuple(a.sec_, a.nsec_) == std::make_tuple(b.sec_, b.nsec_);
90  }
91  friend bool operator!=(Timestamp const& a, Timestamp const& b) {
92  return !(a == b);
93  }
94  friend bool operator<(Timestamp const& a, Timestamp const& b) {
95  return std::make_tuple(a.sec_, a.nsec_) < std::make_tuple(b.sec_, b.nsec_);
96  }
97  friend bool operator<=(Timestamp const& a, Timestamp const& b) {
98  return !(b < a);
99  }
100  friend bool operator>=(Timestamp const& a, Timestamp const& b) {
101  return !(a < b);
102  }
103  friend bool operator>(Timestamp const& a, Timestamp const& b) {
104  return b < a;
105  }
107 
109  friend std::ostream& operator<<(std::ostream& os, Timestamp ts) {
110  return os << ts.ToRFC3339();
111  }
112 
129  template <typename T>
130  StatusOr<T> get() const {
131  return ConvertTo(T{});
132  }
133 
134  private:
135  template <typename Duration>
136  friend StatusOr<Timestamp> MakeTimestamp(sys_time<Duration> const&);
137 
138  friend StatusOr<Timestamp> internal::TimestampFromRFC3339(std::string const&);
139  friend std::string internal::TimestampToRFC3339(Timestamp);
140  friend Timestamp internal::TimestampFromProto(protobuf::Timestamp const&);
141  friend protobuf::Timestamp internal::TimestampToProto(Timestamp);
142 
143  // Arguments must have already been normalized.
144  Timestamp(std::int64_t sec, std::int32_t nsec) : sec_(sec), nsec_(nsec) {}
145 
146  // Build a `Timestamp` from raw counts of seconds/nanoseconds since the Unix
147  // epoch (minus leap seconds), like a C++17 `std::timespec` but out-of-range
148  // `nsec` values are normalized. Fails if the time cannot be represented.
149  static StatusOr<Timestamp> FromCounts(std::intmax_t sec, std::intmax_t nsec);
150 
151  // Conversion from/to RFC3339 string.
152  static StatusOr<Timestamp> FromRFC3339(std::string const&);
153  std::string ToRFC3339() const;
154 
155  // Conversion from/to `protobuf::Timestamp`. These conversions never fail,
156  // but may accept/produce protobufs outside their documented range.
157  static Timestamp FromProto(protobuf::Timestamp const&);
158  protobuf::Timestamp ToProto() const;
159 
160  // Helpers for `std::chrono::time_point` conversions.
161  template <typename Duration>
162  static sys_time<Duration> UnixEpoch() {
163  return std::chrono::time_point_cast<Duration>(
164  sys_time<Duration>::clock::from_time_t(0));
165  }
166  static StatusOr<Timestamp> FromRatio(std::intmax_t count,
167  std::intmax_t numerator,
168  std::intmax_t denominator);
169  StatusOr<std::intmax_t> ToRatio(std::intmax_t min, std::intmax_t max,
170  std::intmax_t numerator,
171  std::intmax_t denominator) const;
172 
173  // Conversion to a `std::chrono::time_point` on the system clock. May
174  // produce out-of-range errors, depending on the properties of `Duration`
175  // and the `std::chrono::system_clock` epoch.
176  template <typename Duration>
177  StatusOr<sys_time<Duration>> ConvertTo(sys_time<Duration> const&) const {
178  auto const count =
179  ToRatio(std::numeric_limits<typename Duration::rep>::min(),
180  std::numeric_limits<typename Duration::rep>::max(),
181  Duration::period::num, Duration::period::den);
182  if (!count) return count.status();
183  return Timestamp::UnixEpoch<Duration>() +
184  Duration(static_cast<typename Duration::rep>(*count));
185  }
186 
187  std::int64_t sec_; // The number of seconds that have elapsed since
188  // 1970-01-01T00:00:00Z, minus leap seconds.
189  std::int32_t nsec_; // The number of nanoseconds [0..999999999] that
190  // have elapsed within that second.
191 };
192 
193 template <typename Duration>
194 StatusOr<Timestamp> MakeTimestamp(sys_time<Duration> const& tp) {
195  return Timestamp::FromRatio((tp - Timestamp::UnixEpoch<Duration>()).count(),
196  Duration::period::num, Duration::period::den);
197 }
198 
205  friend bool operator==(CommitTimestamp, CommitTimestamp) { return true; }
206  friend bool operator!=(CommitTimestamp, CommitTimestamp) { return false; }
207 };
208 
209 } // namespace SPANNER_CLIENT_NS
210 } // namespace spanner
211 } // namespace cloud
212 } // namespace google
213 
214 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TIMESTAMP_H
A sentinel type used to update a commit timestamp column.
Definition: timestamp.h:204
Timestamp()
Default construction yields 1970-01-01T00:00:00Z.
Definition: timestamp.h:76
friend bool operator!=(CommitTimestamp, CommitTimestamp)
Definition: timestamp.h:206
friend bool operator<(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:94
StatusOr< T > get() const
Convert the Timestamp to the user-specified template type.
Definition: timestamp.h:130
friend bool operator==(CommitTimestamp, CommitTimestamp)
Definition: timestamp.h:205
friend std::ostream & operator<<(std::ostream &os, Timestamp ts)
Definition: timestamp.h:109
Contains all the Cloud Spanner C++ client types and functions.
friend bool operator==(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:88
StatusOr< Timestamp > MakeTimestamp(sys_time< Duration > const &)
Construct a Timestamp from a std::chrono::time_point on the system clock.
Definition: timestamp.h:194
friend bool operator>(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:103
#define SPANNER_CLIENT_NS
Definition: version.h:22
friend bool operator>=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:100
std::chrono::time_point< std::chrono::system_clock, Duration > sys_time
Convenience alias.
Definition: timestamp.h:39
friend bool operator!=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:91
A representation of the Spanner TIMESTAMP type: An instant in time.
Definition: timestamp.h:73
friend bool operator<=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:97