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_}
20 constexpr Duration::Duration ()
21 : inherited{kValueWhenEmptyRenderedAsNumber_}
28 , fRepType_{src.fRepType_}
30 if (fRepType_ == eString_) {
31 Assert (not src.fStringRep_.empty ());
32 new (&fStringRep_)
string{src.fStringRep_};
36 : inherited{move (src)}
37 , fRepType_{src.fRepType_}
39 if (src.fRepType_ == eString_) {
40 Assert (fRepType_ == eString_);
41 new (&fStringRep_)
string{move (src.fStringRep_)};
43 src.fRepType_ = eEmpty_;
45 template <Characters::IConvertibleToString STRINGISH_T>
47 : inherited{kValueWhenEmptyRenderedAsNumber_}
50 Assert (fRepType_ == eEmpty_);
52 if constexpr (same_as<STRINGISH_T, string>) {
53 asciiRep = durationStr;
56 asciiRep = Characters::String{durationStr}.AsASCII ();
58 if (not asciiRep.empty ()) {
59 (*(inherited*)
this) = inherited{ParseTime_ (asciiRep)};
60 new (&fStringRep_)
string{asciiRep};
65 : inherited{durationInSeconds}
66 , fRepType_{eNumeric_}
71 : inherited{durationInSeconds}
72 , fRepType_{eNumeric_}
77 : inherited{static_cast<InternalNumericFormatType_> (durationInSeconds)}
78 , fRepType_{eNumeric_}
83 : inherited{durationInSeconds}
84 , fRepType_{eNumeric_}
90 : inherited{durationInSeconds}
91 , fRepType_{eNumeric_}
97 : inherited{
static_cast<InternalNumericFormatType_
> (durationInSeconds)}
98 , fRepType_{eNumeric_}
105 return As<Characters::String> ().AsUTF8 ();
107 inline constexpr Duration::~Duration ()
111 inline void Duration::clear ()
115 constexpr bool Duration::empty ()
const
118 return fRepType_ == eEmpty_;
120 inline Duration& Duration::operator= (
const Duration& rhs)
123 if (fRepType_ == rhs.fRepType_) {
124 if (rhs.fRepType_ == eString_) {
126 fStringRep_ = rhs.fStringRep_;
132 if (rhs.fRepType_ == eString_) {
133 new (&fStringRep_)
string{rhs.fStringRep_};
137 inherited::operator= (rhs);
138 fRepType_ = rhs.fRepType_;
142 inline Duration& Duration::operator= (Duration&& rhs)
noexcept
145 if (fRepType_ == rhs.fRepType_) {
147 if (rhs.fRepType_ == eString_) {
148 fStringRep_ = move (rhs.fStringRep_);
155 if (rhs.fRepType_ == eString_) {
156 new (&fStringRep_)
string{move (rhs.fStringRep_)};
159 inherited::operator= (move (rhs));
160 fRepType_ = rhs.fRepType_;
161 rhs.fRepType_ = eEmpty_;
165 inline constexpr void Duration::destroy_ ()
167 if (fRepType_ == eString_) {
168 fStringRep_.~basic_string ();
172 template <
typename T>
174 requires (Common::IAnyOf<T, timeval, Characters::String> or integral<T> or floating_point<T> or Common::IDuration<T> or Common::ITimePoint<T>)
176 if constexpr (integral<T> or floating_point<T>) {
177 return static_cast<T
> (count ());
179 else if constexpr (same_as<T, timeval>) {
181 decltype (timeval::tv_sec) seconds =
static_cast<long> (r);
183 return timeval{seconds,
static_cast<decltype (timeval::tv_usec)
> (r * 1000 * 1000)};
185 else if constexpr (same_as<T, Characters::String>) {
186 using Characters::String;
191 return String{fStringRep_};
193 return UnParseTime_ (count (), Characters::FloatConversion::Precision{});
198 else if constexpr (Common::IDuration<T>) {
199 return chrono::duration_cast<T> (*
this);
201 else if constexpr (Common::ITimePoint<T>) {
202 return T{this->As<typename T::duration> ()};
205 template <
typename T>
206 inline T
Duration::As (Characters::FloatConversion::Precision p)
const
207 requires (Common::IAnyOf<T, Characters::String>)
209 if constexpr (same_as<T, Characters::String>) {
210 using Characters::String;
216 return UnParseTime_ (count (), p);
222 template <
typename T>
224 requires (same_as<T, timeval> or integral<T> or floating_point<T> or same_as<T, Characters::String> or Common::IDuration<T> or
225 Common::ITimePoint<T>)
227 if constexpr (integral<T> or floating_point<T>) {
228 if (this->count () < numeric_limits<T>::min ()) [[unlikely]] {
229 return numeric_limits<T>::min ();
231 else if (this->count () > numeric_limits<T>::max ()) [[unlikely]] {
232 return numeric_limits<T>::max ();
236 else if constexpr (same_as<T, timeval>) {
237 if (this->count () >
static_cast<rep
> (numeric_limits<long>::max ())) [[unlikely]] {
238 return timeval{numeric_limits<long>::max (), 0};
242 else if constexpr (same_as<T, Characters::String>) {
245 else if constexpr (Common::IDuration<T>) {
246#if (defined(__clang_major__) && !defined(__APPLE__) && (__clang_major__ >= 10)) || \
247 (defined(__clang_major__) && defined(__APPLE__) && (__clang_major__ >= 12))
248 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wimplicit-int-float-conversion\"");
258 using TRatio =
typename T::period;
259 auto targetRes = (
static_cast<long double> (this->count ()) * period::num / period::den) * TRatio ::den / TRatio::num;
260 if (targetRes < T::min ().count ()) [[unlikely]] {
263 if (targetRes > T::max ().count ()) [[unlikely]] {
266#if (defined(__clang_major__) && !defined(__APPLE__) && (__clang_major__ >= 10)) || \
267 (defined(__clang_major__) && defined(__APPLE__) && (__clang_major__ >= 12))
268 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wimplicit-int-float-conversion\"");
272 else if constexpr (Common::ITimePoint<T>) {
273 return T{this->AsPinned<typename T::duration> ()};
286 return inherited::min ();
290 return inherited::max ();
298 inline namespace Literals {
299 [[nodiscard]]
inline Duration operator"" _duration (
const char* str,
size_t len)
301 return Duration{
string{str, str + len}};
303 [[nodiscard]]
inline Duration operator"" _duration (
const wchar_t* str,
size_t len)
307 [[nodiscard]]
inline Duration
operator"" _duration (
const char8_t* str,
size_t len)
309 return Duration{Characters::String{span{str, len}}};
311 [[nodiscard]]
inline Duration
operator"" _duration (
const char16_t* str,
size_t len)
313 return Duration{Characters::String{span{str, len}}};
315 [[nodiscard]]
inline Duration
operator"" _duration (
const char32_t* str,
size_t len)
317 return Duration{Characters::String{span{str, len}}};
319 [[nodiscard]]
inline Duration
operator"" _duration (
long double _Val)
noexcept
321 return Duration{_Val};
353 return Duration{::nextafter (i.
As<Duration::rep> (), numeric_limits<Duration::rep>::max ())};
355 inline Time::Duration Default<Time::Duration>::GetPrevious (Time::Duration i)
357 using Time::Duration;
358 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()