15 #include "google/cloud/spanner/timestamp.h"
16 #include "google/cloud/status.h"
17 #include <google/protobuf/util/time_util.h>
27 Status OutOfRange(std::string message) {
31 Status PositiveOverflow(std::string
const& type) {
32 return OutOfRange(type +
" positive overflow");
35 Status NegativeOverflow(std::string
const& type) {
36 return OutOfRange(type +
" negative overflow");
41 StatusOr<protobuf::Timestamp>
Timestamp::ConvertTo(
42 protobuf::Timestamp
const&)
const {
43 auto constexpr kDestType =
"google::protobuf::Timestamp";
44 auto const s = absl::ToUnixSeconds(t_);
45 if (s >
google::protobuf::util::TimeUtil::kTimestampMaxSeconds)
46 return PositiveOverflow(kDestType);
47 if (s <
google::protobuf::util::TimeUtil::kTimestampMinSeconds)
48 return NegativeOverflow(kDestType);
49 auto const ns = absl::ToInt64Nanoseconds(t_ - absl::FromUnixSeconds(s));
50 google::protobuf::Timestamp proto;
52 proto.set_nanos(
static_cast<std::int32_t>(ns));
56 StatusOr<std::int64_t>
Timestamp::ToRatio(std::int64_t min, std::int64_t max,
58 std::int64_t den)
const {
59 auto constexpr kDestType =
"std::chrono::time_point";
60 auto const period = absl::Seconds(num) / den;
61 auto const duration = absl::Floor(t_ - absl::UnixEpoch(), period);
62 if (duration > max * period)
return PositiveOverflow(kDestType);
63 if (duration < min * period)
return NegativeOverflow(kDestType);
64 return duration / period;
68 auto constexpr kDestType =
"google::cloud::spanner::Timestamp";
69 auto constexpr kMinTime = absl::FromUnixSeconds(
70 google::protobuf::util::TimeUtil::kTimestampMinSeconds);
71 auto constexpr kMaxTime = absl::FromUnixSeconds(
72 google::protobuf::util::TimeUtil::kTimestampMaxSeconds + 1);
73 if (t >= kMaxTime)
return PositiveOverflow(kDestType);
74 if (t < kMinTime)
return NegativeOverflow(kDestType);
80 absl::Nanoseconds(proto.nanos())
);
83 std::ostream& operator<<(std::ostream& os,
Timestamp ts) {
84 return os << spanner_internal::TimestampToRFC3339(ts);
90 namespace spanner_internal {
98 auto constexpr kFormatSpec =
"%E4Y-%m-%d%ET%H:%M:%E*SZ";
99 auto constexpr kParseSpec =
"%Y-%m-%d%ET%H:%M:%E*S%Ez";
101 Status InvalidArgument(std::string message) {
110 if (absl::ParseTime(kParseSpec, s, &t, &err)) {
113 return InvalidArgument(s +
": " + err);
118 return absl::FormatTime(kFormatSpec, t, absl::UTCTimeZone());