|
|
|
@ -22,6 +22,7 @@ |
|
|
|
|
|
|
|
|
|
#include <chrono> |
|
|
|
|
#include <cstdint> |
|
|
|
|
#include <limits> |
|
|
|
|
#include <string> |
|
|
|
|
#include <utility> |
|
|
|
|
|
|
|
|
@ -41,20 +42,9 @@ using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. |
|
|
|
|
|
|
|
|
|
namespace detail { |
|
|
|
|
template <typename D> |
|
|
|
|
inline std::pair<time_point<seconds>, D> split_seconds( |
|
|
|
|
const time_point<D>& tp) { |
|
|
|
|
auto sec = std::chrono::time_point_cast<seconds>(tp); |
|
|
|
|
auto sub = tp - sec; |
|
|
|
|
if (sub.count() < 0) { |
|
|
|
|
sec -= seconds(1); |
|
|
|
|
sub += seconds(1); |
|
|
|
|
} |
|
|
|
|
return {sec, std::chrono::duration_cast<D>(sub)}; |
|
|
|
|
} |
|
|
|
|
inline std::pair<time_point<seconds>, seconds> split_seconds( |
|
|
|
|
const time_point<seconds>& tp) { |
|
|
|
|
return {tp, seconds::zero()}; |
|
|
|
|
} |
|
|
|
|
std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp); |
|
|
|
|
std::pair<time_point<seconds>, seconds> split_seconds( |
|
|
|
|
const time_point<seconds>& tp); |
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
|
|
// cctz::time_zone is an opaque, small, value-type class representing a
|
|
|
|
@ -279,6 +269,20 @@ std::string format(const std::string&, const time_point<seconds>&, |
|
|
|
|
const femtoseconds&, const time_zone&); |
|
|
|
|
bool parse(const std::string&, const std::string&, const time_zone&, |
|
|
|
|
time_point<seconds>*, femtoseconds*, std::string* err = nullptr); |
|
|
|
|
template <typename Rep, std::intmax_t Denom> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds& fs, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp); |
|
|
|
|
template <typename Rep, std::intmax_t Num> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds& fs, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp); |
|
|
|
|
template <typename Rep> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds& fs, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp); |
|
|
|
|
bool join_seconds(const time_point<seconds>& sec, const femtoseconds&, |
|
|
|
|
time_point<seconds>* tpp); |
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
|
|
// Formats the given time_point in the given cctz::time_zone according to
|
|
|
|
@ -369,15 +373,84 @@ inline bool parse(const std::string& fmt, const std::string& input, |
|
|
|
|
const time_zone& tz, time_point<D>* tpp) { |
|
|
|
|
time_point<seconds> sec; |
|
|
|
|
detail::femtoseconds fs; |
|
|
|
|
const bool b = detail::parse(fmt, input, tz, &sec, &fs); |
|
|
|
|
if (b) { |
|
|
|
|
// TODO: Return false if unrepresentable as a time_point<D>.
|
|
|
|
|
*tpp = std::chrono::time_point_cast<D>(sec); |
|
|
|
|
*tpp += std::chrono::duration_cast<D>(fs); |
|
|
|
|
return detail::parse(fmt, input, tz, &sec, &fs) && |
|
|
|
|
detail::join_seconds(sec, fs, tpp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace detail { |
|
|
|
|
|
|
|
|
|
// Split a time_point<D> into a time_point<seconds> and a D subseconds.
|
|
|
|
|
// Undefined behavior if time_point<seconds> is not of sufficient range.
|
|
|
|
|
// Note that this means it is UB to call cctz::time_zone::lookup(tp) or
|
|
|
|
|
// cctz::format(fmt, tp, tz) with a time_point that is outside the range
|
|
|
|
|
// of a 64-bit std::time_t.
|
|
|
|
|
template <typename D> |
|
|
|
|
std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp) { |
|
|
|
|
auto sec = std::chrono::time_point_cast<seconds>(tp); |
|
|
|
|
auto sub = tp - sec; |
|
|
|
|
if (sub.count() < 0) { |
|
|
|
|
sec -= seconds(1); |
|
|
|
|
sub += seconds(1); |
|
|
|
|
} |
|
|
|
|
return b; |
|
|
|
|
return {sec, std::chrono::duration_cast<D>(sub)}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline std::pair<time_point<seconds>, seconds> split_seconds( |
|
|
|
|
const time_point<seconds>& tp) { |
|
|
|
|
return {tp, seconds::zero()}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Join a time_point<seconds> and femto subseconds into a time_point<D>.
|
|
|
|
|
// Floors to the resolution of time_point<D>. Returns false if time_point<D>
|
|
|
|
|
// is not of sufficient range.
|
|
|
|
|
template <typename Rep, std::intmax_t Denom> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds& fs, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp) { |
|
|
|
|
using D = std::chrono::duration<Rep, std::ratio<1, Denom>>; |
|
|
|
|
// TODO(#199): Return false if result unrepresentable as a time_point<D>.
|
|
|
|
|
*tpp = std::chrono::time_point_cast<D>(sec); |
|
|
|
|
*tpp += std::chrono::duration_cast<D>(fs); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename Rep, std::intmax_t Num> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds&, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp) { |
|
|
|
|
using D = std::chrono::duration<Rep, std::ratio<Num, 1>>; |
|
|
|
|
auto count = sec.time_since_epoch().count(); |
|
|
|
|
if (count >= 0 || count % Num == 0) { |
|
|
|
|
count /= Num; |
|
|
|
|
} else { |
|
|
|
|
count /= Num; |
|
|
|
|
count -= 1; |
|
|
|
|
} |
|
|
|
|
if (count > (std::numeric_limits<Rep>::max)()) return false; |
|
|
|
|
if (count < (std::numeric_limits<Rep>::min)()) return false; |
|
|
|
|
*tpp = time_point<D>() + D{static_cast<Rep>(count)}; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename Rep> |
|
|
|
|
bool join_seconds( |
|
|
|
|
const time_point<seconds>& sec, const femtoseconds&, |
|
|
|
|
time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp) { |
|
|
|
|
using D = std::chrono::duration<Rep, std::ratio<1, 1>>; |
|
|
|
|
auto count = sec.time_since_epoch().count(); |
|
|
|
|
if (count > (std::numeric_limits<Rep>::max)()) return false; |
|
|
|
|
if (count < (std::numeric_limits<Rep>::min)()) return false; |
|
|
|
|
*tpp = time_point<D>() + D{static_cast<Rep>(count)}; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline bool join_seconds(const time_point<seconds>& sec, const femtoseconds&, |
|
|
|
|
time_point<seconds>* tpp) { |
|
|
|
|
*tpp = sec; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
} // namespace cctz
|
|
|
|
|
} // namespace time_internal
|
|
|
|
|
ABSL_NAMESPACE_END |
|
|
|
|