6namespace Stroika::Foundation::Time {
13 template <
typename DURATION_REP,
typename DURATION_PERIOD>
14 constexpr Duration::Duration (
const chrono::duration<DURATION_REP, DURATION_PERIOD>& d)
15 : inherited{chrono::duration<InternalNumericFormatType_> (d).count ()}
16 , fRepType_{eNumeric_}
19 if (not is_constant_evaluated ()) {
20 if constexpr (floating_point<DURATION_REP>) {
21 Require (not isnan (d.count ()));
25 constexpr Duration::Duration ()
26 : inherited{kValueWhenEmptyRenderedAsNumber_}
33 , fRepType_{src.fRepType_}
35 if (fRepType_ == eString_) {
36 Assert (not src.fStringRep_.empty ());
37 new (&fStringRep_)
string{src.fStringRep_};
41 : inherited{move (src)}
42 , fRepType_{src.fRepType_}
44 if (src.fRepType_ == eString_) {
45 Assert (fRepType_ == eString_);
46 new (&fStringRep_)
string{move (src.fStringRep_)};
48 src.fRepType_ = eEmpty_;
50 template <Characters::IConvertibleToString STRINGISH_T>
52 : inherited{kValueWhenEmptyRenderedAsNumber_}
55 Assert (fRepType_ == eEmpty_);
57 if constexpr (same_as<STRINGISH_T, string>) {
58 asciiRep = durationStr;
61 asciiRep = Characters::String{durationStr}.AsASCII ();
63 if (not asciiRep.empty ()) {
64 (*(inherited*)
this) = inherited{ParseTime_ (asciiRep)};
65 new (&fStringRep_)
string{asciiRep};
70 : inherited{durationInSeconds}
71 , fRepType_{eNumeric_}
76 : inherited{durationInSeconds}
77 , fRepType_{eNumeric_}
82 : inherited{static_cast<InternalNumericFormatType_> (durationInSeconds)}
83 , fRepType_{eNumeric_}
88 : inherited{durationInSeconds}
89 , fRepType_{eNumeric_}
92 if (not is_constant_evaluated ()) {
93 Require (not isnan (durationInSeconds));
97 : inherited{durationInSeconds}
98 , fRepType_{eNumeric_}
101 if (not is_constant_evaluated ()) {
102 Require (not isnan (durationInSeconds));
106 : inherited{
static_cast<InternalNumericFormatType_
> (durationInSeconds)}
107 , fRepType_{eNumeric_}
110 if (not is_constant_evaluated ()) {
111 Require (not isnan (durationInSeconds));
116 return As<Characters::String> ().AsUTF8 ();
118 inline constexpr Duration::~Duration ()
122 inline void Duration::clear ()
126 constexpr bool Duration::empty ()
const
129 return fRepType_ == eEmpty_;
131 inline Duration& Duration::operator= (
const Duration& rhs)
134 if (fRepType_ == rhs.fRepType_) {
135 if (rhs.fRepType_ == eString_) {
137 fStringRep_ = rhs.fStringRep_;
143 if (rhs.fRepType_ == eString_) {
144 new (&fStringRep_)
string{rhs.fStringRep_};
148 inherited::operator= (rhs);
149 fRepType_ = rhs.fRepType_;
153 inline Duration& Duration::operator= (Duration&& rhs)
noexcept
156 if (fRepType_ == rhs.fRepType_) {
158 if (rhs.fRepType_ == eString_) {
159 fStringRep_ = move (rhs.fStringRep_);
166 if (rhs.fRepType_ == eString_) {
167 new (&fStringRep_)
string{move (rhs.fStringRep_)};
170 inherited::operator= (move (rhs));
171 fRepType_ = rhs.fRepType_;
172 rhs.fRepType_ = eEmpty_;
176 inline constexpr void Duration::destroy_ ()
178 if (fRepType_ == eString_) {
179 fStringRep_.~basic_string ();
183 template <
typename T>
185 requires (Common::IAnyOf<T, timeval, Characters::String> or integral<T> or floating_point<T> or Common::IDuration<T> or Common::ITimePoint<T>)
187 if constexpr (integral<T> or floating_point<T>) {
188 return static_cast<T
> (count ());
190 else if constexpr (same_as<T, timeval>) {
192 decltype (timeval::tv_sec) seconds =
static_cast<long> (r);
194 return timeval{seconds,
static_cast<decltype (timeval::tv_usec)
> (r * 1000 * 1000)};
196 else if constexpr (same_as<T, Characters::String>) {
197 using Characters::String;
202 return String{fStringRep_};
204 return UnParseTime_ (count (), Characters::FloatConversion::Precision{});
209 else if constexpr (Common::IDuration<T>) {
210 return chrono::duration_cast<T> (*
this);
212 else if constexpr (Common::ITimePoint<T>) {
213 return T{this->As<typename T::duration> ()};
216 template <
typename T>
217 inline T
Duration::As (Characters::FloatConversion::Precision p)
const
218 requires (Common::IAnyOf<T, Characters::String>)
220 if constexpr (same_as<T, Characters::String>) {
221 using Characters::String;
227 return UnParseTime_ (count (), p);
233 template <
typename T>
235 requires (same_as<T, timeval> or integral<T> or floating_point<T> or same_as<T, Characters::String> or Common::IDuration<T> or
236 Common::ITimePoint<T>)
238 if constexpr (integral<T> or floating_point<T>) {
239 if (this->count () < numeric_limits<T>::min ()) [[unlikely]] {
240 return numeric_limits<T>::min ();
242 else if (this->count () > numeric_limits<T>::max ()) [[unlikely]] {
243 return numeric_limits<T>::max ();
247 else if constexpr (same_as<T, timeval>) {
248 if (this->count () >
static_cast<rep
> (numeric_limits<long>::max ())) [[unlikely]] {
249 return timeval{numeric_limits<long>::max (), 0};
253 else if constexpr (same_as<T, Characters::String>) {
256 else if constexpr (Common::IDuration<T>) {
257#if (defined(__clang_major__) && !defined(__APPLE__) && (__clang_major__ >= 10)) || \
258 (defined(__clang_major__) && defined(__APPLE__) && (__clang_major__ >= 12))
259 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wimplicit-int-float-conversion\"");
269 using TRatio =
typename T::period;
270 auto targetRes = (
static_cast<long double> (this->count ()) * period::num / period::den) * TRatio ::den / TRatio::num;
271 if (targetRes < T::min ().count ()) [[unlikely]] {
274 if (targetRes > T::max ().count ()) [[unlikely]] {
277#if (defined(__clang_major__) && !defined(__APPLE__) && (__clang_major__ >= 10)) || \
278 (defined(__clang_major__) && defined(__APPLE__) && (__clang_major__ >= 12))
279 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wimplicit-int-float-conversion\"");
283 else if constexpr (Common::ITimePoint<T>) {
284 return T{this->AsPinned<typename T::duration> ()};
297 return inherited::min ();
301 return inherited::max ();
309 inline namespace Literals {
310 [[nodiscard]]
inline Duration operator""_duration (
const char* str,
size_t len)
312 return Duration{
string{str, str + len}};
314 [[nodiscard]]
inline Duration operator""_duration (
const wchar_t* str,
size_t len)
318 [[nodiscard]]
inline Duration
operator""_duration (
const char8_t* str,
size_t len)
320 return Duration{Characters::String{span{str, len}}};
322 [[nodiscard]]
inline Duration
operator""_duration (
const char16_t* str,
size_t len)
324 return Duration{Characters::String{span{str, len}}};
326 [[nodiscard]]
inline Duration
operator""_duration (
const char32_t* str,
size_t len)
328 return Duration{Characters::String{span{str, len}}};
330 [[nodiscard]]
inline Duration
operator""_duration (
long double _Val)
noexcept
332 return Duration{_Val};
364 return Duration{::nextafter (i.
As<Duration::rep> (), numeric_limits<Duration::rep>::max ())};
366 inline Time::Duration Default<Time::Duration>::GetPrevious (Time::Duration i)
368 using Time::Duration;
369 return Duration{::nextafter (i.As<Duration::rep> (), numeric_limits<Duration::rep>::min ())};
#define AssertNotReached()
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Duration is a chrono::duration<double> (=.
nonvirtual T AsPinned() const
nonvirtual Characters::String ToString() const
nonvirtual Characters::String Format(const PrettyPrintInfo &prettyPrintInfo=kDefaultPrettyPrintInfo) const
like javascript 'humanize' APIs
nonvirtual u8string AsUTF8() const
nonvirtual Characters::String PrettyPrint(const PrettyPrintInfo &prettyPrintInfo=kDefaultPrettyPrintInfo) const
static constexpr Duration min()
static constexpr Duration max()