Google Cloud Spanner C++ Client 2.13.0
A C++ Client Library for Google Cloud Spanner
Loading...
Searching...
No Matches
timestamp.h
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// https://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
18#include "google/cloud/spanner/version.h"
19#include "google/cloud/status_or.h"
20#include "absl/time/time.h"
21#include <google/protobuf/timestamp.pb.h>
22#include <chrono>
23#include <cstdint>
24#include <limits>
25#include <ostream>
26#include <string>
27
28namespace google {
29namespace cloud {
30namespace spanner {
31GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
32
33/**
34 * Convenience alias. `std::chrono::sys_time` since C++20.
35 */
36template <typename Duration>
37using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
38
39/**
40 * A representation of the Spanner TIMESTAMP type: An instant in time.
41 *
42 * A `Timestamp` represents an absolute point in time (i.e., is independent of
43 * any time zone), with at least nanosecond precision, and with a range of
44 * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z, inclusive.
45 *
46 * The `MakeTimestamp(src)` factory function(s) should be used to construct
47 * `Timestamp` values from standard representations of absolute time.
48 *
49 * A `Timestamp` can be converted back to a standard representation using
50 * `ts.get<T>()`.
51 *
52 * @see https://cloud.google.com/spanner/docs/data-types#timestamp_type
53 */
54class Timestamp {
55 public:
56 /// Default construction yields 1970-01-01T00:00:00Z.
57 Timestamp() : Timestamp(absl::UnixEpoch()) {}
58
59 /// @name Regular value type, supporting copy, assign, move.
60 ///@{
61 Timestamp(Timestamp&&) = default;
62 Timestamp& operator=(Timestamp&&) = default;
63 Timestamp(Timestamp const&) = default;
64 Timestamp& operator=(Timestamp const&) = default;
65 ///@}
66
67 /// @name Relational operators
68 ///@{
69 friend bool operator==(Timestamp const& a, Timestamp const& b) {
70 return a.t_ == b.t_;
71 }
72 friend bool operator!=(Timestamp const& a, Timestamp const& b) {
73 return !(a == b);
74 }
75 friend bool operator<(Timestamp const& a, Timestamp const& b) {
76 return a.t_ < b.t_;
77 }
78 friend bool operator<=(Timestamp const& a, Timestamp const& b) {
79 return !(b < a);
80 }
81 friend bool operator>=(Timestamp const& a, Timestamp const& b) {
82 return !(a < b);
83 }
84 friend bool operator>(Timestamp const& a, Timestamp const& b) {
85 return b < a;
86 }
87 ///@}
88
89 /// @name Output streaming
90 friend std::ostream& operator<<(std::ostream& os, Timestamp ts);
91
92 /**
93 * Convert the `Timestamp` to the user-specified template type. Fails if
94 * `*this` cannot be represented as a `T`.
95 *
96 * Supported destination types are:
97 * - `absl::Time` - Since `absl::Time` can represent all possible
98 * `Timestamp` values, `get<absl::Time>()` never returns an error.
99 * - `google::protobuf::Timestamp` - Never returns an error, but any
100 * sub-nanosecond precision will be lost.
101 * - `google::cloud::spanner::sys_time<Duration>` - `Duration::rep` may
102 * not be wider than `std::int64_t`, and `Duration::period` may be no
103 * more precise than `std::nano`.
104 *
105 * @par Example
106 *
107 * @code
108 * sys_time<std::chrono::nanoseconds> tp = ...;
109 * Timestamp ts = MakeTimestamp(tp).value();
110 * assert(tp == ts.get<sys_time<std::chrono::nanoseconds>>().value());
111 * @endcode
112 */
113 template <typename T>
114 StatusOr<T> get() const {
115 // All `ConvertTo()` overloads return a `StatusOr<T>` even when they
116 // cannot actually fail (e.g., when the destination type can represent
117 // all `Timestamp` values). See individual comments below.
118 return ConvertTo(T{});
119 }
120
121 private:
122 friend StatusOr<Timestamp> MakeTimestamp(absl::Time);
123
124 StatusOr<std::int64_t> ToRatio(std::int64_t min, std::int64_t max,
125 std::int64_t num, std::int64_t den) const;
126
127 // Conversion to a `std::chrono::time_point` on the system clock. May
128 // produce out-of-range errors, depending on the properties of `Duration`
129 // and the `std::chrono::system_clock` epoch.
130 template <typename Duration>
131 StatusOr<sys_time<Duration>> ConvertTo(sys_time<Duration> const&) const {
132 using Rep = typename Duration::rep;
133 using Period = typename Duration::period;
134 static_assert(std::ratio_greater_equal<Period, std::nano>::value,
135 "Duration must be no more precise than std::nano");
136 auto count =
137 ToRatio(std::numeric_limits<Rep>::min(),
138 std::numeric_limits<Rep>::max(), Period::num, Period::den);
139 if (!count) return std::move(count).status();
140 auto const unix_epoch = std::chrono::time_point_cast<Duration>(
141 sys_time<Duration>::clock::from_time_t(0));
142 return unix_epoch + Duration(static_cast<Rep>(*count));
143 }
144
145 // Conversion to an `absl::Time`. Can never fail.
146 StatusOr<absl::Time> ConvertTo(absl::Time) const { return t_; }
147
148 // Conversion to a `google::protobuf::Timestamp`. Can never fail, but
149 // any sub-nanosecond precision will be lost.
150 StatusOr<protobuf::Timestamp> ConvertTo(protobuf::Timestamp const&) const;
151
152 explicit Timestamp(absl::Time t) : t_(t) {}
153
154 absl::Time t_;
155};
156
157/**
158 * Construct a `Timestamp` from an `absl::Time`. May produce out-of-range
159 * errors if the given time is beyond the range supported by `Timestamp` (see
160 * class comments above).
161 */
162StatusOr<Timestamp> MakeTimestamp(absl::Time);
163
164/**
165 * Construct a `Timestamp` from a `google::protobuf::Timestamp`. May produce
166 * out-of-range errors if the given protobuf is beyond the range supported by
167 * `Timestamp` (which a valid protobuf never will).
168 */
169StatusOr<Timestamp> MakeTimestamp(protobuf::Timestamp const&);
170
171/**
172 * Construct a `Timestamp` from a `std::chrono::time_point` on the system
173 * clock. May produce out-of-range errors, depending on the properties of
174 * `Duration` and the `std::chrono::system_clock` epoch. `Duration::rep` may
175 * not be wider than `std::int64_t`. Requires that `Duration::period` is no
176 * more precise than `std::nano`.
177 */
178template <typename Duration>
179StatusOr<Timestamp> MakeTimestamp(sys_time<Duration> const& tp) {
180 using Period = typename Duration::period;
181 static_assert(std::ratio_greater_equal<Period, std::nano>::value,
182 "Duration must be no more precise than std::nano");
183 auto const unix_epoch = std::chrono::time_point_cast<Duration>(
184 sys_time<Duration>::clock::from_time_t(0));
185 auto const period = absl::Seconds(Period::num) / Period::den;
186 auto const count = (tp - unix_epoch).count();
187 return MakeTimestamp(absl::UnixEpoch() + count * period);
188}
189
190/**
191 * A sentinel type used to update a commit timestamp column.
192 *
193 * @see https://cloud.google.com/spanner/docs/commit-timestamp
194 */
195struct CommitTimestamp {
196 friend bool operator==(CommitTimestamp, CommitTimestamp) { return true; }
197 friend bool operator!=(CommitTimestamp, CommitTimestamp) { return false; }
198};
199
200GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
201} // namespace spanner
202
203namespace spanner_internal {
204GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
205StatusOr<spanner::Timestamp> TimestampFromRFC3339(std::string const&);
206std::string TimestampToRFC3339(spanner::Timestamp);
207GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
208} // namespace spanner_internal
209
210} // namespace cloud
211} // namespace google
212
213#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_TIMESTAMP_H
A representation of the Spanner TIMESTAMP type: An instant in time.
Definition: timestamp.h:54
friend bool operator<=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:78
friend bool operator!=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:72
Timestamp()
Default construction yields 1970-01-01T00:00:00Z.
Definition: timestamp.h:57
friend bool operator>(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:84
Timestamp(Timestamp const &)=default
friend bool operator==(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:69
Timestamp & operator=(Timestamp &&)=default
StatusOr< T > get() const
Convert the Timestamp to the user-specified template type.
Definition: timestamp.h:114
Timestamp(Timestamp &&)=default
Timestamp & operator=(Timestamp const &)=default
friend StatusOr< Timestamp > MakeTimestamp(absl::Time)
Construct a Timestamp from an absl::Time.
friend bool operator>=(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:81
friend bool operator<(Timestamp const &a, Timestamp const &b)
Definition: timestamp.h:75
Contains all the Cloud Spanner C++ client types and functions.
Definition: backoff_policy.h:23
StatusOr< Timestamp > MakeTimestamp(protobuf::Timestamp const &)
Construct a Timestamp from a google::protobuf::Timestamp.
StatusOr< Timestamp > MakeTimestamp(sys_time< Duration > const &tp)
Construct a Timestamp from a std::chrono::time_point on the system clock.
Definition: timestamp.h:179
A sentinel type used to update a commit timestamp column.
Definition: timestamp.h:195
friend bool operator!=(CommitTimestamp, CommitTimestamp)
Definition: timestamp.h:197
friend bool operator==(CommitTimestamp, CommitTimestamp)
Definition: timestamp.h:196