text: // Copyright 2020 Google LLC
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     https://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  #include "google/cloud/internal/time_utils.h"
  #include <google/protobuf/timestamp.pb.h>
  #include <chrono>
  
  namespace google {
  namespace cloud {
  GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
  namespace internal {
  
  absl::Time ToAbslTime(google::protobuf::Timestamp const& proto) {
    return absl::FromUnixSeconds(proto.seconds()) +
           absl::Nanoseconds(proto.nanos());
  }
  
  google::protobuf::Timestamp ToProtoTimestamp(absl::Time t) {
    // The min/max values that are allowed to be encoded in a Timestamp proto:
    // ["0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999999Z"]
    // Note: These values can be computed with `date +%s --date="YYYY-MM-...Z"`
    auto constexpr kMinTime = absl::FromUnixSeconds(-62135596800);
    auto const kMaxTime =  // NOLINT(readability-identifier-naming)
        absl::FromUnixSeconds(253402300799) + absl::Nanoseconds(999999999);
    if (t < kMinTime) {
      t = kMinTime;
    } else if (t > kMaxTime) {
      t = kMaxTime;
    }
    auto const s = absl::ToUnixSeconds(t);
    auto const ns = absl::ToInt64Nanoseconds(t - absl::FromUnixSeconds(s));
    google::protobuf::Timestamp proto;
    proto.set_seconds(s);
    proto.set_nanos(static_cast<std::int32_t>(ns));
    return proto;
  }
  
  std::chrono::system_clock::time_point ToChronoTimePoint(
      google::protobuf::Timestamp const& proto) {
    return absl::ToChronoTime(ToAbslTime(proto));
  }
  
  google::protobuf::Timestamp ToProtoTimestamp(
      std::chrono::system_clock::time_point const& tp) {
    return ToProtoTimestamp(absl::FromChrono(tp));
  }
  
  }  // namespace internal
  GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
  }  // namespace cloud
  }  // namespace google
  