diff options
author | nga <nga@yandex-team.ru> | 2022-02-10 16:48:09 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:48:09 +0300 |
commit | c2a1af049e9deca890e9923abe64fe6c59060348 (patch) | |
tree | b222e5ac2e2e98872661c51ccceee5da0d291e13 /util/datetime | |
parent | 1f553f46fb4f3c5eec631352cdd900a0709016af (diff) | |
download | ydb-c2a1af049e9deca890e9923abe64fe6c59060348.tar.gz |
Restoring authorship annotation for <nga@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'util/datetime')
-rw-r--r-- | util/datetime/base.cpp | 20 | ||||
-rw-r--r-- | util/datetime/base.h | 338 | ||||
-rw-r--r-- | util/datetime/base_ut.cpp | 128 | ||||
-rw-r--r-- | util/datetime/cputimer.cpp | 40 | ||||
-rw-r--r-- | util/datetime/cputimer.h | 40 | ||||
-rw-r--r-- | util/datetime/parser.h | 234 | ||||
-rw-r--r-- | util/datetime/parser.rl6 | 528 | ||||
-rw-r--r-- | util/datetime/parser_ut.cpp | 284 | ||||
-rw-r--r-- | util/datetime/systime.cpp | 8 |
9 files changed, 810 insertions, 810 deletions
diff --git a/util/datetime/base.cpp b/util/datetime/base.cpp index f61b7b889f..38ecc3ab96 100644 --- a/util/datetime/base.cpp +++ b/util/datetime/base.cpp @@ -1,26 +1,26 @@ #include "base.h" - -#include <util/string/cast.h> + +#include <util/string/cast.h> #include <util/stream/output.h> #include <util/stream/mem.h> -#include <util/system/compat.h> +#include <util/system/compat.h> #include <util/memory/tempbuf.h> #include <util/generic/string.h> #include <util/generic/strbuf.h> #include <util/generic/yexception.h> - + TString Strftime(const char* format, const struct tm* tm) { size_t size = Max<size_t>(strlen(format) * 2 + 1, 107); - for (;;) { + for (;;) { TTempBuf buf(size); - int r = strftime(buf.Data(), buf.Size(), format, tm); + int r = strftime(buf.Data(), buf.Size(), format, tm); if (r != 0) { return TString(buf.Data(), r); } - size *= 2; - } -} - + size *= 2; + } +} + template <> TDuration FromStringImpl<TDuration, char>(const char* s, size_t len) { return TDuration::Parse(TStringBuf(s, len)); diff --git a/util/datetime/base.h b/util/datetime/base.h index 152fa983bb..5e902b8f63 100644 --- a/util/datetime/base.h +++ b/util/datetime/base.h @@ -3,14 +3,14 @@ #include "systime.h" #include <util/str_stl.h> -#include <util/system/platform.h> -#include <util/system/datetime.h> +#include <util/system/platform.h> +#include <util/system/datetime.h> #include <util/generic/string.h> #include <util/generic/strbuf.h> -#include <util/generic/ylimits.h> +#include <util/generic/ylimits.h> #include <util/generic/utility.h> #include <util/generic/typetraits.h> -#include <util/generic/yexception.h> +#include <util/generic/yexception.h> #include <chrono> @@ -29,20 +29,20 @@ #pragma warning(disable : 4244) // conversion from 'time_t' to 'long', possible loss of data #endif // _MSC_VER -// Microseconds since epoch -class TInstant; +// Microseconds since epoch +class TInstant; -// Duration is microseconds. Could be used to store timeouts, for example. -class TDuration; - -/// Current time +// Duration is microseconds. Could be used to store timeouts, for example. +class TDuration; + +/// Current time static inline TInstant Now() noexcept; - -/// Use Now() method to obtain current time instead of *Seconds() unless you understand what are you doing. - -class TDateTimeParseException: public yexception { -}; - + +/// Use Now() method to obtain current time instead of *Seconds() unless you understand what are you doing. + +class TDateTimeParseException: public yexception { +}; + const int DATE_BUF_LEN = 4 + 2 + 2 + 1; // [YYYYMMDD*] constexpr long seconds(const struct tm& theTm) { @@ -73,8 +73,8 @@ bool ParseISO8601DateTime(const char* date, time_t& utcTime); bool ParseISO8601DateTime(const char* date, size_t dateLen, time_t& utcTime); bool ParseRFC822DateTime(const char* date, time_t& utcTime); bool ParseRFC822DateTime(const char* date, size_t dateLen, time_t& utcTime); -bool ParseHTTPDateTime(const char* date, time_t& utcTime); -bool ParseHTTPDateTime(const char* date, size_t dateLen, time_t& utcTime); +bool ParseHTTPDateTime(const char* date, time_t& utcTime); +bool ParseHTTPDateTime(const char* date, size_t dateLen, time_t& utcTime); bool ParseX509ValidityDateTime(const char* date, time_t& utcTime); bool ParseX509ValidityDateTime(const char* date, size_t dateLen, time_t& utcTime); @@ -83,7 +83,7 @@ constexpr long TVdiff(timeval r1, timeval r2) { } TString Strftime(const char* format, const struct tm* tm); - + // Use functions below instead of sprint_date (check IGNIETFERRO-892 for details) void DateToString(char* buf, const struct tm& theTm); void DateToString(char* buf, time_t when, long* sec = nullptr); @@ -93,17 +93,17 @@ TString DateToString(time_t when, long* sec = nullptr); TString YearToString(const struct tm& theTm); TString YearToString(time_t when); -template <class S> -class TTimeBase { -public: +template <class S> +class TTimeBase { +public: using TValue = ui64; - + protected: constexpr TTimeBase(const TValue& value) noexcept : Value_(value) - { - } - + { + } + public: constexpr TTimeBase() noexcept : Value_(0) @@ -112,40 +112,40 @@ public: constexpr TTimeBase(const struct timeval& tv) noexcept : Value_(tv.tv_sec * (ui64)1000000 + tv.tv_usec) - { - } - + { + } + constexpr TValue GetValue() const noexcept { return Value_; - } - + } + constexpr double SecondsFloat() const noexcept { return Value_ * (1 / 1000000.0); - } - + } + constexpr double MillisecondsFloat() const noexcept { return Value_ * (1 / 1000.0); } constexpr TValue MicroSeconds() const noexcept { return Value_; - } + } constexpr TValue MilliSeconds() const noexcept { - return MicroSeconds() / 1000; - } + return MicroSeconds() / 1000; + } constexpr TValue Seconds() const noexcept { - return MilliSeconds() / 1000; - } + return MilliSeconds() / 1000; + } constexpr TValue Minutes() const noexcept { - return Seconds() / 60; - } + return Seconds() / 60; + } constexpr TValue Hours() const noexcept { - return Minutes() / 60; - } + return Minutes() / 60; + } constexpr TValue Days() const noexcept { return Hours() / 24; @@ -153,16 +153,16 @@ public: constexpr TValue NanoSeconds() const noexcept { return MicroSeconds() >= (Max<TValue>() / (TValue)1000) ? Max<TValue>() : MicroSeconds() * (TValue)1000; - } + } constexpr ui32 MicroSecondsOfSecond() const noexcept { return MicroSeconds() % (TValue)1000000; - } + } constexpr ui32 MilliSecondsOfSecond() const noexcept { return MicroSecondsOfSecond() / (TValue)1000; - } - + } + constexpr ui32 NanoSecondsOfSecond() const noexcept { return MicroSecondsOfSecond() * (TValue)1000; } @@ -173,26 +173,26 @@ public: protected: TValue Value_; // microseconds count -}; - -namespace NDateTimeHelpers { - template <typename T> - struct TPrecisionHelper { +}; + +namespace NDateTimeHelpers { + template <typename T> + struct TPrecisionHelper { using THighPrecision = ui64; - }; - - template <> - struct TPrecisionHelper<float> { + }; + + template <> + struct TPrecisionHelper<float> { using THighPrecision = double; - }; - - template <> - struct TPrecisionHelper<double> { + }; + + template <> + struct TPrecisionHelper<double> { using THighPrecision = double; - }; + }; } - -class TDuration: public TTimeBase<TDuration> { + +class TDuration: public TTimeBase<TDuration> { using TBase = TTimeBase<TDuration>; private: @@ -201,18 +201,18 @@ private: */ constexpr explicit TDuration(TValue value) noexcept : TBase(value) - { - } - + { + } + public: constexpr TDuration() noexcept { } constexpr TDuration(const struct timeval& tv) noexcept - : TBase(tv) - { - } - + : TBase(tv) + { + } + /** * TDuration is compatible with std::chrono::duration: * it can be constructed and compared with std::chrono::duration. @@ -261,52 +261,52 @@ public: } static constexpr TDuration MicroSeconds(ui64 us) noexcept { - return TDuration(us); - } - + return TDuration(us); + } + /* noexcept(false) as conversion from T might throw, for example FromString("abc") */ - template <typename T> + template <typename T> static constexpr TDuration MilliSeconds(T ms) noexcept(false) { return MicroSeconds((ui64)(typename NDateTimeHelpers::TPrecisionHelper<T>::THighPrecision(ms) * 1000)); - } - + } + using TBase::Days; - using TBase::Hours; + using TBase::Hours; using TBase::MicroSeconds; using TBase::MilliSeconds; - using TBase::Minutes; - using TBase::Seconds; - - /// DeadLineFromTimeOut - inline TInstant ToDeadLine() const; + using TBase::Minutes; + using TBase::Seconds; + + /// DeadLineFromTimeOut + inline TInstant ToDeadLine() const; constexpr TInstant ToDeadLine(TInstant now) const; - + static constexpr TDuration Max() noexcept { return TDuration(::Max<TValue>()); - } - + } + static constexpr TDuration Zero() noexcept { return TDuration(); - } - + } + /* noexcept(false) as conversion from T might throw, for example FromString("abc") */ - template <typename T> + template <typename T> static constexpr TDuration Seconds(T s) noexcept(false) { - return MilliSeconds(typename NDateTimeHelpers::TPrecisionHelper<T>::THighPrecision(s) * 1000); - } - + return MilliSeconds(typename NDateTimeHelpers::TPrecisionHelper<T>::THighPrecision(s) * 1000); + } + static constexpr TDuration Minutes(ui64 m) noexcept { - return Seconds(m * 60); - } + return Seconds(m * 60); + } static constexpr TDuration Hours(ui64 h) noexcept { - return Minutes(h * 60); - } + return Minutes(h * 60); + } static constexpr TDuration Days(ui64 d) noexcept { - return Hours(d * 24); - } - + return Hours(d * 24); + } + /// parses strings like 10s, 15ms, 15.05s, 20us, or just 25 (s). See parser_ut.cpp for details static TDuration Parse(const TStringBuf input); @@ -333,10 +333,10 @@ public: inline TDuration& operator/=(const T& t) noexcept { return (*this = (*this / t)); } - + TString ToString() const; -}; - +}; + Y_DECLARE_PODTYPE(TDuration); template <> @@ -346,8 +346,8 @@ struct THash<TDuration> { } }; -/// TInstant and TDuration are guaranteed to have same precision -class TInstant: public TTimeBase<TInstant> { +/// TInstant and TDuration are guaranteed to have same precision +class TInstant: public TTimeBase<TInstant> { using TBase = TTimeBase<TInstant>; private: @@ -356,61 +356,61 @@ private: */ constexpr explicit TInstant(TValue value) noexcept : TBase(value) - { - } - + { + } + public: constexpr TInstant() noexcept { } constexpr TInstant(const struct timeval& tv) noexcept - : TBase(tv) - { - } - + : TBase(tv) + { + } + static constexpr TInstant FromValue(TValue value) noexcept { return TInstant(value); } - static inline TInstant Now() { + static inline TInstant Now() { return TInstant::MicroSeconds(::MicroSeconds()); - } - + } + using TBase::Days; - using TBase::Hours; + using TBase::Hours; using TBase::MicroSeconds; using TBase::MilliSeconds; - using TBase::Minutes; - using TBase::Seconds; - + using TBase::Minutes; + using TBase::Seconds; + static constexpr TInstant Max() noexcept { return TInstant(::Max<TValue>()); - } - + } + static constexpr TInstant Zero() noexcept { return TInstant(); - } - - /// us since epoch + } + + /// us since epoch static constexpr TInstant MicroSeconds(ui64 us) noexcept { - return TInstant(us); - } + return TInstant(us); + } - /// ms since epoch + /// ms since epoch static constexpr TInstant MilliSeconds(ui64 ms) noexcept { - return MicroSeconds(ms * 1000); - } + return MicroSeconds(ms * 1000); + } - /// seconds since epoch + /// seconds since epoch static constexpr TInstant Seconds(ui64 s) noexcept { - return MilliSeconds(s * 1000); - } + return MilliSeconds(s * 1000); + } - /// minutes since epoch + /// minutes since epoch static constexpr TInstant Minutes(ui64 m) noexcept { - return Seconds(m * 60); - } - + return Seconds(m * 60); + } + /// hours since epoch static constexpr TInstant Hours(ui64 h) noexcept { return Minutes(h * 60); @@ -423,26 +423,26 @@ public: constexpr time_t TimeT() const noexcept { return (time_t)Seconds(); - } - + } + inline struct timeval TimeVal() const noexcept { - struct timeval tv; - ::Zero(tv); - tv.tv_sec = TimeT(); - tv.tv_usec = MicroSecondsOfSecond(); - return tv; - } - + struct timeval tv; + ::Zero(tv); + tv.tv_sec = TimeT(); + tv.tv_usec = MicroSecondsOfSecond(); + return tv; + } + inline struct tm* LocalTime(struct tm* tm) const noexcept { - time_t clock = Seconds(); - return localtime_r(&clock, tm); - } + time_t clock = Seconds(); + return localtime_r(&clock, tm); + } inline struct tm* GmTime(struct tm* tm) const noexcept { - time_t clock = Seconds(); + time_t clock = Seconds(); return GmTimeR(&clock, tm); - } - + } + /** * Formats the instant using the UTC time zone, with microsecond precision. * @@ -464,7 +464,7 @@ public: * @returns An ISO 8601 formatted string, e.g. '2015-11-21T23:30:27Z'. */ TString ToStringUpToSeconds() const; - + /** * Formats the instant using the system time zone, with microsecond precision. * @@ -555,8 +555,8 @@ public: inline TInstant& operator-=(const T& t) noexcept { return (*this = (*this - t)); } -}; - +}; + Y_DECLARE_PODTYPE(TInstant); template <> @@ -631,22 +631,22 @@ static constexpr bool operator>=(const TTimeBase<S>& l, const TTimeBase<S>& r) n return l.GetValue() >= r.GetValue(); } -namespace NDateTimeHelpers { - template <typename T> +namespace NDateTimeHelpers { + template <typename T> static constexpr T SumWithSaturation(T a, T b) { static_assert(!std::numeric_limits<T>::is_signed, "expect !std::numeric_limits<T>::is_signed"); return Max<T>() - a < b ? Max<T>() : a + b; - } - - template <typename T> + } + + template <typename T> static constexpr T DiffWithSaturation(T a, T b) { static_assert(!std::numeric_limits<T>::is_signed, "expect !std::numeric_limits<T>::is_signed"); return a < b ? 0 : a - b; - } -} - + } +} + constexpr TDuration operator-(const TInstant& l, const TInstant& r) noexcept { return TDuration::FromValue(::NDateTimeHelpers::DiffWithSaturation(l.GetValue(), r.GetValue())); } @@ -804,20 +804,20 @@ constexpr double operator/(const TDuration& x, const TDuration& y) noexcept { } inline TInstant TDuration::ToDeadLine() const { - return ToDeadLine(TInstant::Now()); -} - + return ToDeadLine(TInstant::Now()); +} + constexpr TInstant TDuration::ToDeadLine(TInstant now) const { return now + *this; -} - -void Sleep(TDuration duration); +} + +void Sleep(TDuration duration); void SleepUntil(TInstant instant); - + static inline TInstant Now() noexcept { - return TInstant::Now(); -} - + return TInstant::Now(); +} + #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER diff --git a/util/datetime/base_ut.cpp b/util/datetime/base_ut.cpp index 18a7d41efe..afc3f802eb 100644 --- a/util/datetime/base_ut.cpp +++ b/util/datetime/base_ut.cpp @@ -1,15 +1,15 @@ #include "base.h" #include <library/cpp/testing/unittest/registar.h> - + #include <util/generic/utility.h> #include <util/generic/ylimits.h> #include <util/generic/ymath.h> #include <util/string/cast.h> #include <util/stream/output.h> -#include <util/system/compat.h> +#include <util/system/compat.h> #include <util/random/random.h> - + #include <limits.h> using namespace std::chrono_literals; @@ -220,18 +220,18 @@ Y_UNIT_TEST_SUITE(TDateTimeTest) { UNIT_ASSERT(CompareTM(e.Tm_, t)); /* - * strptime seems to be broken on Mac OS X: - * - * struct tm t; - * char *ret = strptime("Jul", "%b ", &t); - * printf("-%s-\n", ret); - * - * yields "- -": ret contains a pointer to a substring of the format string, - * that should never occur: function returns either NULL or pointer to buf substring. - * - * So this test fails on Mac OS X. - */ - + * strptime seems to be broken on Mac OS X: + * + * struct tm t; + * char *ret = strptime("Jul", "%b ", &t); + * printf("-%s-\n", ret); + * + * yields "- -": ret contains a pointer to a substring of the format string, + * that should never occur: function returns either NULL or pointer to buf substring. + * + * So this test fails on Mac OS X. + */ + struct tm t2; Zero(t2); char* ret = strptime(e.Date_, "%a %b %d %H:%M:%S %Y\n ", &t2); @@ -272,7 +272,7 @@ Y_UNIT_TEST_SUITE(TDateTimeTest) { UNIT_ASSERT(Abs(milliseconds - microseconds / 1000) < 100); UNIT_ASSERT(seconds > 1243008607); // > time when test was written } - + Y_UNIT_TEST(TestStrftime) { struct tm tm; Zero(tm); @@ -281,14 +281,14 @@ Y_UNIT_TEST_SUITE(TDateTimeTest) { tm.tm_mday = 29; UNIT_ASSERT_STRINGS_EQUAL("2009-05-29", Strftime("%Y-%m-%d", &tm)); } - + Y_UNIT_TEST(TestNanoSleep) { NanoSleep(0); NanoSleep(1); NanoSleep(1000); NanoSleep(1000000); } - + static bool TimeZoneEq(const char* zone0, const char* zone1) { if (strcmp(zone0, "GMT") == 0) { zone0 = "UTC"; @@ -340,37 +340,37 @@ Y_UNIT_TEST_SUITE(TDateTimeTest) { Y_UNIT_TEST_SUITE(DateTimeTest) { Y_UNIT_TEST(TestDurationFromFloat) { - UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5)); - UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5f)); - } - + UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5)); + UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5f)); + } + Y_UNIT_TEST(TestSecondsLargeValue) { - unsigned int seconds = UINT_MAX; + unsigned int seconds = UINT_MAX; UNIT_ASSERT_VALUES_EQUAL(((ui64)seconds) * 1000000, TDuration::Seconds(seconds).MicroSeconds()); - } - + } + Y_UNIT_TEST(TestToString) { #define CHECK_CONVERTIBLE(v) \ do { \ UNIT_ASSERT_VALUES_EQUAL(v, ToString(TDuration::Parse(v))); \ UNIT_ASSERT_VALUES_EQUAL(v, TDuration::Parse(v).ToString()); \ } while (0) -#if 0 - - CHECK_CONVERTIBLE("10s"); - CHECK_CONVERTIBLE("1234s"); - CHECK_CONVERTIBLE("1234ms"); - CHECK_CONVERTIBLE("12ms"); - CHECK_CONVERTIBLE("12us"); - CHECK_CONVERTIBLE("1234us"); -#endif - - CHECK_CONVERTIBLE("1.000000s"); - CHECK_CONVERTIBLE("11234.000000s"); - CHECK_CONVERTIBLE("0.011122s"); - CHECK_CONVERTIBLE("33.011122s"); - } - +#if 0 + + CHECK_CONVERTIBLE("10s"); + CHECK_CONVERTIBLE("1234s"); + CHECK_CONVERTIBLE("1234ms"); + CHECK_CONVERTIBLE("12ms"); + CHECK_CONVERTIBLE("12us"); + CHECK_CONVERTIBLE("1234us"); +#endif + + CHECK_CONVERTIBLE("1.000000s"); + CHECK_CONVERTIBLE("11234.000000s"); + CHECK_CONVERTIBLE("0.011122s"); + CHECK_CONVERTIBLE("33.011122s"); + } + Y_UNIT_TEST(TestFromString) { static const struct T { const char* const Str; @@ -404,31 +404,31 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { } Y_UNIT_TEST(TestSleep) { - // check does not throw - Sleep(TDuration::Seconds(0)); - Sleep(TDuration::MicroSeconds(1)); - Sleep(TDuration::MilliSeconds(1)); - } - + // check does not throw + Sleep(TDuration::Seconds(0)); + Sleep(TDuration::MicroSeconds(1)); + Sleep(TDuration::MilliSeconds(1)); + } + Y_UNIT_TEST(TestInstantToString) { UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), ToString(TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455))); UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToString()); UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToStringUpToSeconds()); - } - + } + Y_UNIT_TEST(TestInstantToRfc822String) { UNIT_ASSERT_VALUES_EQUAL(TString("Thu, 06 Aug 2009 15:19:06 GMT"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToRfc822String()); } Y_UNIT_TEST(TestInstantMath) { - UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1719), TInstant::Seconds(1700) + TDuration::Seconds(19)); - // overflow - UNIT_ASSERT_VALUES_EQUAL(TInstant::Max(), TInstant::Max() - TDuration::Seconds(10) + TDuration::Seconds(19)); - // underflow - UNIT_ASSERT_VALUES_EQUAL(TInstant::Zero(), TInstant::Seconds(1000) - TDuration::Seconds(2000)); - UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TInstant::Seconds(1000) - TInstant::Seconds(2000)); - } - + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1719), TInstant::Seconds(1700) + TDuration::Seconds(19)); + // overflow + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max(), TInstant::Max() - TDuration::Seconds(10) + TDuration::Seconds(19)); + // underflow + UNIT_ASSERT_VALUES_EQUAL(TInstant::Zero(), TInstant::Seconds(1000) - TDuration::Seconds(2000)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TInstant::Seconds(1000) - TInstant::Seconds(2000)); + } + Y_UNIT_TEST(TestDurationMath) { TDuration empty; UNIT_ASSERT(!empty); @@ -439,14 +439,14 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { TDuration nonEmpty = TDuration::MicroSeconds(1); UNIT_ASSERT(nonEmpty); - UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(110), TDuration::Seconds(77) + TDuration::Seconds(33)); - // overflow - UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration::Max() - TDuration::Seconds(1) + TDuration::Seconds(10)); - // underflow - UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration::Seconds(20) - TDuration::Seconds(200)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(110), TDuration::Seconds(77) + TDuration::Seconds(33)); + // overflow + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration::Max() - TDuration::Seconds(1) + TDuration::Seconds(10)); + // underflow + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration::Seconds(20) - TDuration::Seconds(200)); // division UNIT_ASSERT_DOUBLES_EQUAL(TDuration::Minutes(1) / TDuration::Seconds(10), 6.0, 1e-9); - } + } Y_UNIT_TEST(TestDurationGetters) { const TDuration value = TDuration::MicroSeconds(1234567); @@ -651,4 +651,4 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { static_assert(TDuration::Zero() + 1s == 1s); static_assert(TInstant::Seconds(1) + 1s == TInstant::Seconds(2)); } -} +} diff --git a/util/datetime/cputimer.cpp b/util/datetime/cputimer.cpp index 0d60296836..516d372c37 100644 --- a/util/datetime/cputimer.cpp +++ b/util/datetime/cputimer.cpp @@ -30,32 +30,32 @@ TTimer::~TTimer() { Cerr << Message_.Str(); } -static ui64 ManuallySetCyclesPerSecond = 0; - -static ui64 GetCyclesPerSecond() { +static ui64 ManuallySetCyclesPerSecond = 0; + +static ui64 GetCyclesPerSecond() { if (ManuallySetCyclesPerSecond != 0) { - return ManuallySetCyclesPerSecond; + return ManuallySetCyclesPerSecond; } else { return NHPTimer::GetCyclesPerSecond(); } } -void SetCyclesPerSecond(ui64 cycles) { - ManuallySetCyclesPerSecond = cycles; -} - -ui64 GetCyclesPerMillisecond() { - return GetCyclesPerSecond() / 1000; -} - -TDuration CyclesToDuration(ui64 cycles) { - return TDuration::MicroSeconds(cycles * 1000000 / GetCyclesPerSecond()); -} - -ui64 DurationToCycles(TDuration duration) { - return duration.MicroSeconds() * GetCyclesPerSecond() / 1000000; -} - +void SetCyclesPerSecond(ui64 cycles) { + ManuallySetCyclesPerSecond = cycles; +} + +ui64 GetCyclesPerMillisecond() { + return GetCyclesPerSecond() / 1000; +} + +TDuration CyclesToDuration(ui64 cycles) { + return TDuration::MicroSeconds(cycles * 1000000 / GetCyclesPerSecond()); +} + +ui64 DurationToCycles(TDuration duration) { + return duration.MicroSeconds() * GetCyclesPerSecond() / 1000000; +} + TPrecisionTimer::TPrecisionTimer() : Start(::GetCycleCount()) { diff --git a/util/datetime/cputimer.h b/util/datetime/cputimer.h index 1704b55dcc..7d38d5bdb3 100644 --- a/util/datetime/cputimer.h +++ b/util/datetime/cputimer.h @@ -2,13 +2,13 @@ #include "base.h" -#include <util/system/rusage.h> +#include <util/system/rusage.h> #include <util/generic/string.h> #include <util/stream/str.h> class TTimer { private: - TInstant Start_; + TInstant Start_; TStringStream Message_; public: @@ -17,51 +17,51 @@ public: }; class TSimpleTimer { - TInstant T; + TInstant T; public: TSimpleTimer() { Reset(); } TDuration Get() const { - return TInstant::Now() - T; + return TInstant::Now() - T; } void Reset() { - T = TInstant::Now(); + T = TInstant::Now(); } }; class TProfileTimer { - TDuration T; + TDuration T; public: TProfileTimer() { Reset(); } TDuration Get() const { - return TRusage::Get().Utime - T; + return TRusage::Get().Utime - T; } TDuration Step() { - TRusage r; - r.Fill(); - TDuration d = r.Utime - T; - T = r.Utime; + TRusage r; + r.Fill(); + TDuration d = r.Utime - T; + T = r.Utime; return d; } void Reset() { - T = TRusage::Get().Utime; + T = TRusage::Get().Utime; } }; -/// Return cached processor cycle count per second. Method takes 1 second at first invocation. -/// Note, on older systems cycle rate may change during program lifetime, -/// so returned value may be incorrect. Modern Intel and AMD processors keep constant TSC rate. +/// Return cached processor cycle count per second. Method takes 1 second at first invocation. +/// Note, on older systems cycle rate may change during program lifetime, +/// so returned value may be incorrect. Modern Intel and AMD processors keep constant TSC rate. ui64 GetCyclesPerMillisecond(); -void SetCyclesPerSecond(ui64 cycles); +void SetCyclesPerSecond(ui64 cycles); + +TDuration CyclesToDuration(ui64 cycles); +ui64 DurationToCycles(TDuration duration); -TDuration CyclesToDuration(ui64 cycles); -ui64 DurationToCycles(TDuration duration); - class TPrecisionTimer { private: ui64 Start = 0; @@ -91,7 +91,7 @@ public: ~TFuncTimer(); private: - const TInstant Start_; + const TInstant Start_; const char* Func_; }; diff --git a/util/datetime/parser.h b/util/datetime/parser.h index 7816bfd349..f0c1b4a0c7 100644 --- a/util/datetime/parser.h +++ b/util/datetime/parser.h @@ -1,160 +1,160 @@ #pragma once - -// probably you do not need to include this file directly, use "util/datetime/base.h" - -#include "base.h" - -struct TDateTimeFields { - TDateTimeFields() { - Zero(*this); + +// probably you do not need to include this file directly, use "util/datetime/base.h" + +#include "base.h" + +struct TDateTimeFields { + TDateTimeFields() { + Zero(*this); ZoneOffsetMinutes = 0; Hour = 0; - } - - ui32 Year; - ui32 Month; // 1..12 - ui32 Day; // 1 .. 31 - ui32 Hour; // 0 .. 23 - ui32 Minute; // 0 .. 59 - ui32 Second; // 0 .. 60 - ui32 MicroSecond; // 0 .. 999999 - i32 ZoneOffsetMinutes; - - void SetLooseYear(ui32 year) { - if (year < 60) - year += 100; - if (year < 160) - year += 1900; - Year = year; - } - + } + + ui32 Year; + ui32 Month; // 1..12 + ui32 Day; // 1 .. 31 + ui32 Hour; // 0 .. 23 + ui32 Minute; // 0 .. 59 + ui32 Second; // 0 .. 60 + ui32 MicroSecond; // 0 .. 999999 + i32 ZoneOffsetMinutes; + + void SetLooseYear(ui32 year) { + if (year < 60) + year += 100; + if (year < 160) + year += 1900; + Year = year; + } + bool IsOk() const noexcept { - if (Year < 1970) - return false; - if (Month < 1 || Month > 12) - return false; - - unsigned int maxMonthDay = 31; - if (Month == 4 || Month == 6 || Month == 9 || Month == 11) { - maxMonthDay = 30; - } else if (Month == 2) { - if (Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)) - // leap year - maxMonthDay = 29; - else - maxMonthDay = 28; - } - if (Day > maxMonthDay) - return false; - - if (Hour > 23) - return false; - - if (Minute > 59) - return false; - + if (Year < 1970) + return false; + if (Month < 1 || Month > 12) + return false; + + unsigned int maxMonthDay = 31; + if (Month == 4 || Month == 6 || Month == 9 || Month == 11) { + maxMonthDay = 30; + } else if (Month == 2) { + if (Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)) + // leap year + maxMonthDay = 29; + else + maxMonthDay = 28; + } + if (Day > maxMonthDay) + return false; + + if (Hour > 23) + return false; + + if (Minute > 59) + return false; + // handle leap second which is explicitly allowed by ISO 8601:2004(E) $2.2.2 // https://datatracker.ietf.org/doc/html/rfc3339#section-5.6 - if (Second > 60) - return false; - - if (MicroSecond > 999999) - return false; - + if (Second > 60) + return false; + + if (MicroSecond > 999999) + return false; + if (Year == 1970 && Month == 1 && Day == 1) { if ((i64)(3600 * Hour + 60 * Minute + Second) < (60 * ZoneOffsetMinutes)) return false; } - return true; - } - + return true; + } + TInstant ToInstant(TInstant defaultValue) const { - time_t tt = ToTimeT(-1); - if (tt == -1) - return defaultValue; - return TInstant::Seconds(tt) + TDuration::MicroSeconds(MicroSecond); - } - + time_t tt = ToTimeT(-1); + if (tt == -1) + return defaultValue; + return TInstant::Seconds(tt) + TDuration::MicroSeconds(MicroSecond); + } + time_t ToTimeT(time_t defaultValue) const { - if (!IsOk()) - return defaultValue; - struct tm tm; - Zero(tm); - tm.tm_year = Year - 1900; - tm.tm_mon = Month - 1; - tm.tm_mday = Day; - tm.tm_hour = Hour; - tm.tm_min = Minute; - tm.tm_sec = Second; + if (!IsOk()) + return defaultValue; + struct tm tm; + Zero(tm); + tm.tm_year = Year - 1900; + tm.tm_mon = Month - 1; + tm.tm_mday = Day; + tm.tm_hour = Hour; + tm.tm_min = Minute; + tm.tm_sec = Second; time_t tt = TimeGM(&tm); - if (tt == -1) - return defaultValue; - return tt - ZoneOffsetMinutes * 60; - } -}; - -class TDateTimeParserBase { + if (tt == -1) + return defaultValue; + return tt - ZoneOffsetMinutes * 60; + } +}; + +class TDateTimeParserBase { public: const TDateTimeFields& GetDateTimeFields() const { return DateTimeFields; } -protected: - TDateTimeFields DateTimeFields; +protected: + TDateTimeFields DateTimeFields; int cs; //for ragel - int Sign; - int I; - int Dc; - + int Sign; + int I; + int Dc; + protected: - TDateTimeParserBase() + TDateTimeParserBase() : DateTimeFields() , cs(0) , Sign(0) , I(0xDEADBEEF) // to guarantee unittest break if ragel code is incorrect , Dc(0xDEADBEEF) - { - } + { + } inline TInstant GetResult(int firstFinalState, TInstant defaultValue) const { if (cs < firstFinalState) return defaultValue; return DateTimeFields.ToInstant(defaultValue); } -}; - +}; + #define DECLARE_PARSER(CLASS) \ struct CLASS: public TDateTimeParserBase { \ CLASS(); \ bool ParsePart(const char* input, size_t len); \ TInstant GetResult(TInstant defaultValue) const; \ - }; - -DECLARE_PARSER(TIso8601DateTimeParser) -DECLARE_PARSER(TRfc822DateTimeParser) -DECLARE_PARSER(THttpDateTimeParser) + }; + +DECLARE_PARSER(TIso8601DateTimeParser) +DECLARE_PARSER(TRfc822DateTimeParser) +DECLARE_PARSER(THttpDateTimeParser) DECLARE_PARSER(TX509ValidityDateTimeParser) DECLARE_PARSER(TX509Validity4yDateTimeParser) - -#undef DECLARE_PARSER - -struct TDurationParser { - int cs; - - ui64 I; - ui32 Dc; - - i32 MultiplierPower; // 6 for seconds, 0 for microseconds, -3 for nanoseconds + +#undef DECLARE_PARSER + +struct TDurationParser { + int cs; + + ui64 I; + ui32 Dc; + + i32 MultiplierPower; // 6 for seconds, 0 for microseconds, -3 for nanoseconds i32 Multiplier; - ui64 IntegerPart; - ui32 FractionPart; - ui32 FractionDigits; - - TDurationParser(); - bool ParsePart(const char* input, size_t len); - TDuration GetResult(TDuration defaultValue) const; -}; + ui64 IntegerPart; + ui32 FractionPart; + ui32 FractionDigits; + + TDurationParser(); + bool ParsePart(const char* input, size_t len); + TDuration GetResult(TDuration defaultValue) const; +}; /** Depcrecated cause of default hour offset (+4 hours) diff --git a/util/datetime/parser.rl6 b/util/datetime/parser.rl6 index 5a8e3f48ad..931f09eae1 100644 --- a/util/datetime/parser.rl6 +++ b/util/datetime/parser.rl6 @@ -11,23 +11,23 @@ %%{ -machine DateTimeParserCommon; +machine DateTimeParserCommon; + +sp = ' '; -sp = ' '; - action clear_int { - I = 0; - Dc = 0; + I = 0; + Dc = 0; } action update_int { - I = I * 10 + (fc - '0'); - ++Dc; + I = I * 10 + (fc - '0'); + ++Dc; } -int = (digit+) - >clear_int - $update_int; +int = (digit+) + >clear_int + $update_int; int1 = digit >clear_int @@ -37,10 +37,10 @@ int2 = (digit digit) >clear_int $update_int; -int3 = (digit digit digit) - >clear_int - $update_int; - +int3 = (digit digit digit) + >clear_int + $update_int; + int4 = (digit digit digit digit) >clear_int $update_int; @@ -53,60 +53,60 @@ int24 = ( digit digit ( digit digit )? ) >clear_int $update_int; -# According to both RFC2822 and RFC2616 dates MUST be case-sensitive, -# but Andrey fomichev@ wants relaxed parser - -month3 = - 'Jan'i %{ DateTimeFields.Month = 1; } - | 'Feb'i %{ DateTimeFields.Month = 2; } - | 'Mar'i %{ DateTimeFields.Month = 3; } - | 'Apr'i %{ DateTimeFields.Month = 4; } - | 'May'i %{ DateTimeFields.Month = 5; } - | 'Jun'i %{ DateTimeFields.Month = 6; } - | 'Jul'i %{ DateTimeFields.Month = 7; } - | 'Aug'i %{ DateTimeFields.Month = 8; } - | 'Sep'i %{ DateTimeFields.Month = 9; } - | 'Oct'i %{ DateTimeFields.Month = 10; } - | 'Nov'i %{ DateTimeFields.Month = 11; } - | 'Dec'i %{ DateTimeFields.Month = 12; }; - -wkday = 'Mon'i | 'Tue'i | 'Wed'i | 'Thu'i | 'Fri'i | 'Sat'i | 'Sun'i; -weekday = 'Monday'i | 'Tuesday'i | 'Wednesday'i | 'Thursday'i - | 'Friday'i | 'Saturday'i | 'Sunday'i; - -action set_second { DateTimeFields.Second = I; } -action set_minute { DateTimeFields.Minute = I; } -action set_hour { DateTimeFields.Hour = I; } -action set_day { DateTimeFields.Day = I; } -action set_month { DateTimeFields.Month = I; } -action set_year { DateTimeFields.SetLooseYear(I); } -action set_zone_utc { DateTimeFields.ZoneOffsetMinutes = 0; } - -}%% - -%%{ - -machine RFC822DateParser; - -################# RFC 2822 3.3 Full Date ################### - -include DateTimeParserCommon; - -ws1 = (space+); -ws0 = (space*); -dow_spec = ( wkday ',' )?; - -day = int12 %set_day; +# According to both RFC2822 and RFC2616 dates MUST be case-sensitive, +# but Andrey fomichev@ wants relaxed parser + +month3 = + 'Jan'i %{ DateTimeFields.Month = 1; } + | 'Feb'i %{ DateTimeFields.Month = 2; } + | 'Mar'i %{ DateTimeFields.Month = 3; } + | 'Apr'i %{ DateTimeFields.Month = 4; } + | 'May'i %{ DateTimeFields.Month = 5; } + | 'Jun'i %{ DateTimeFields.Month = 6; } + | 'Jul'i %{ DateTimeFields.Month = 7; } + | 'Aug'i %{ DateTimeFields.Month = 8; } + | 'Sep'i %{ DateTimeFields.Month = 9; } + | 'Oct'i %{ DateTimeFields.Month = 10; } + | 'Nov'i %{ DateTimeFields.Month = 11; } + | 'Dec'i %{ DateTimeFields.Month = 12; }; + +wkday = 'Mon'i | 'Tue'i | 'Wed'i | 'Thu'i | 'Fri'i | 'Sat'i | 'Sun'i; +weekday = 'Monday'i | 'Tuesday'i | 'Wednesday'i | 'Thursday'i + | 'Friday'i | 'Saturday'i | 'Sunday'i; + +action set_second { DateTimeFields.Second = I; } +action set_minute { DateTimeFields.Minute = I; } +action set_hour { DateTimeFields.Hour = I; } +action set_day { DateTimeFields.Day = I; } +action set_month { DateTimeFields.Month = I; } +action set_year { DateTimeFields.SetLooseYear(I); } +action set_zone_utc { DateTimeFields.ZoneOffsetMinutes = 0; } + +}%% + +%%{ + +machine RFC822DateParser; + +################# RFC 2822 3.3 Full Date ################### + +include DateTimeParserCommon; + +ws1 = (space+); +ws0 = (space*); +dow_spec = ( wkday ',' )?; + +day = int12 %set_day; year = int24 %set_year; # actually it must be from 0 to 23 -hour = int2 %set_hour; +hour = int2 %set_hour; # actually it must be from 0 to 59 -min = int2 %set_minute; +min = int2 %set_minute; # actually it must be from 0 to 59 -sec = int2 %set_second; +sec = int2 %set_second; sec_spec = ( ':' . sec )?; @@ -114,7 +114,7 @@ sec_spec = ( ':' . sec )?; action set_mil_offset { char c = (char)toupper(fc); if (c == 'Z') - DateTimeFields.ZoneOffsetMinutes = 0; + DateTimeFields.ZoneOffsetMinutes = 0; else { if (c <= 'M') { // ['A'..'M'] \ 'J' @@ -140,8 +140,8 @@ mil_zone = /[A-IK-Za-ik-z]/ $set_mil_offset; # it is a bug in ragel 5 because ragel 6.2 works correctly with % at the end of string. # see http://www.complang.org/ragel/ChangeLog. -zone = 'UT' @{ DateTimeFields.ZoneOffsetMinutes = 0; } - | 'GMT' @{ DateTimeFields.ZoneOffsetMinutes = 0; } +zone = 'UT' @{ DateTimeFields.ZoneOffsetMinutes = 0; } + | 'GMT' @{ DateTimeFields.ZoneOffsetMinutes = 0; } | 'EST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(5).Minutes();} | 'EDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(4).Minutes(); } | 'CST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(6).Minutes();} @@ -151,29 +151,29 @@ zone = 'UT' @{ DateTimeFields.ZoneOffsetMinutes = 0; } | 'PST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(8).Minutes();} | 'PDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(7).Minutes(); }; -digit_offset = ('+' | '-') > { Sign = fc == '+' ? 1 : -1; } . int4 @set_digit_offset; +digit_offset = ('+' | '-') > { Sign = fc == '+' ? 1 : -1; } . int4 @set_digit_offset; offset = ( zone | mil_zone | digit_offset ); -rfc822datetime = ws0 . dow_spec . ws0 . day . ws1 . month3 . ws1 . year . ws1 . hour . ':' . min . sec_spec . ws1 . offset . ws0; +rfc822datetime = ws0 . dow_spec . ws0 . day . ws1 . month3 . ws1 . year . ws1 . hour . ':' . min . sec_spec . ws1 . offset . ws0; -main := rfc822datetime; +main := rfc822datetime; write data noerror; }%% TRfc822DateTimeParserDeprecated::TRfc822DateTimeParserDeprecated() { - %% write init; -} + %% write init; +} bool TRfc822DateTimeParserDeprecated::ParsePart(const char* input, size_t len) { - const char* p = input; - const char* pe = input + len; + const char* p = input; + const char* pe = input + len; - %% write exec; - return cs != %%{ write error; }%%; -} + %% write exec; + return cs != %%{ write error; }%%; +} TRfc822DateTimeParser::TRfc822DateTimeParser() { %% write init; @@ -187,53 +187,53 @@ bool TRfc822DateTimeParser::ParsePart(const char* input, size_t len) { return cs != %%{ write error; }%%; } -%%{ - -machine ISO8601DateTimeParser; - -include DateTimeParserCommon; - -year = int4 @set_year; -month = int2 @set_month; -day = int2 @set_day; -hour = int2 @set_hour; -minute = int2 @set_minute; -second = int2 @set_second; +%%{ + +machine ISO8601DateTimeParser; + +include DateTimeParserCommon; + +year = int4 @set_year; +month = int2 @set_month; +day = int2 @set_day; +hour = int2 @set_hour; +minute = int2 @set_minute; +second = int2 @set_second; secondFrac = digit {1,6} >clear_int $update_int @{ - ui32 us = I; - for (int k = Dc; k < 6; ++k) { - us *= 10; - } - DateTimeFields.MicroSecond = us; -}; + ui32 us = I; + for (int k = Dc; k < 6; ++k) { + us *= 10; + } + DateTimeFields.MicroSecond = us; +}; secondFracTail = (digit*); - -zoneZ = [Zz] @set_zone_utc; + +zoneZ = [Zz] @set_zone_utc; zoneOffset = space? . ('+' | '-') >{ Sign = fc == '+' ? 1 : -1; } . int2 @{ DateTimeFields.ZoneOffsetMinutes = Sign * (i32)TDuration::Hours(I).Minutes(); } . (':')? . (int2 @{ DateTimeFields.ZoneOffsetMinutes += I * Sign; })?; -zone = zoneZ | zoneOffset; - -iso8601date = (year . '-' . month . '-' . day) | (year . month . day); +zone = zoneZ | zoneOffset; + +iso8601date = (year . '-' . month . '-' . day) | (year . month . day); iso8601time = (hour . ':' . minute . (':' . second ('.' secondFrac secondFracTail)?)?) | (hour . minute . second?); - -iso8601datetime = iso8601date . ([Tt ] . iso8601time . zone?)?; - -main := iso8601datetime; - -write data noerror; - -}%% - + +iso8601datetime = iso8601date . ([Tt ] . iso8601time . zone?)?; + +main := iso8601datetime; + +write data noerror; + +}%% + TIso8601DateTimeParserDeprecated::TIso8601DateTimeParserDeprecated() { %% write init; -} - +} + bool TIso8601DateTimeParserDeprecated::ParsePart(const char* input, size_t len) { - const char* p = input; - const char* pe = input + len; - + const char* p = input; + const char* pe = input + len; + %% write exec; - return cs != %%{ write error; }%%; -} + return cs != %%{ write error; }%%; +} TIso8601DateTimeParser::TIso8601DateTimeParser() { %% write init; @@ -247,50 +247,50 @@ bool TIso8601DateTimeParser::ParsePart(const char* input, size_t len) { return cs != %%{ write error; }%%; } -%%{ - -machine HttpDateTimeParser; - -include DateTimeParserCommon; - -################# RFC 2616 3.3.1 Full Date ################# - -time = int2 %set_hour ':' int2 %set_minute ':' int2 %set_second; -date1 = int2 %set_day ' ' month3 ' ' int4 %set_year; -date2 = int2 %set_day '-' month3 '-' int2 %set_year; -date3 = month3 sp (int2 | sp int1) %set_day; - -rfc1123_date = wkday ',' sp date1 sp time sp 'GMT'i; -rfc850_date = weekday ',' sp date2 sp time sp 'GMT'i; -asctime_date = wkday sp date3 sp time sp int4 @set_year; -http_date = (rfc1123_date | rfc850_date | asctime_date) @set_zone_utc; - -}%% - -%%{ - -machine HttpDateTimeParserStandalone; - -include HttpDateTimeParser; - -main := http_date; - -write data noerror; - -}%% - +%%{ + +machine HttpDateTimeParser; + +include DateTimeParserCommon; + +################# RFC 2616 3.3.1 Full Date ################# + +time = int2 %set_hour ':' int2 %set_minute ':' int2 %set_second; +date1 = int2 %set_day ' ' month3 ' ' int4 %set_year; +date2 = int2 %set_day '-' month3 '-' int2 %set_year; +date3 = month3 sp (int2 | sp int1) %set_day; + +rfc1123_date = wkday ',' sp date1 sp time sp 'GMT'i; +rfc850_date = weekday ',' sp date2 sp time sp 'GMT'i; +asctime_date = wkday sp date3 sp time sp int4 @set_year; +http_date = (rfc1123_date | rfc850_date | asctime_date) @set_zone_utc; + +}%% + +%%{ + +machine HttpDateTimeParserStandalone; + +include HttpDateTimeParser; + +main := http_date; + +write data noerror; + +}%% + THttpDateTimeParserDeprecated::THttpDateTimeParserDeprecated() { - %% write init; -} - + %% write init; +} + bool THttpDateTimeParserDeprecated::ParsePart(const char* input, size_t len) { - const char* p = input; - const char* pe = input + len; - - %% write exec; - return cs != %%{ write error; }%%; -} - + const char* p = input; + const char* pe = input + len; + + %% write exec; + return cs != %%{ write error; }%%; +} + THttpDateTimeParser::THttpDateTimeParser() { %% write init; } @@ -334,7 +334,7 @@ bool TX509ValidityDateTimeParserDeprecated::ParsePart(const char *input, size_t const char *pe = input + len; %% write exec; - return cs != %%{ write error; }%%; + return cs != %%{ write error; }%%; } TX509ValidityDateTimeParser::TX509ValidityDateTimeParser() { @@ -379,7 +379,7 @@ bool TX509Validity4yDateTimeParserDeprecated::ParsePart(const char *input, size_ const char *pe = input + len; %% write exec; - return cs != %%{ write error; }%%; + return cs != %%{ write error; }%%; } TX509Validity4yDateTimeParser::TX509Validity4yDateTimeParser() { @@ -397,23 +397,23 @@ bool TX509Validity4yDateTimeParser::ParsePart(const char *input, size_t len) { TInstant TIso8601DateTimeParserDeprecated::GetResult(TInstant defaultValue) const { Y_UNUSED(ISO8601DateTimeParser_en_main); return TDateTimeParserBaseDeprecated::GetResult(ISO8601DateTimeParser_first_final, defaultValue); -} - +} + TInstant TRfc822DateTimeParserDeprecated::GetResult(TInstant defaultValue) const { Y_UNUSED(RFC822DateParser_en_main); return TDateTimeParserBaseDeprecated::GetResult(RFC822DateParser_first_final, defaultValue); -} - +} + TInstant THttpDateTimeParserDeprecated::GetResult(TInstant defaultValue) const { Y_UNUSED(HttpDateTimeParserStandalone_en_main); return TDateTimeParserBaseDeprecated::GetResult(HttpDateTimeParserStandalone_first_final, defaultValue); -} - +} + TInstant TX509ValidityDateTimeParserDeprecated::GetResult(TInstant defaultValue) const { Y_UNUSED(X509ValidityDateTimeParser_en_main); return TDateTimeParserBaseDeprecated::GetResult(X509ValidityDateTimeParser_first_final, defaultValue); } - + TInstant TX509Validity4yDateTimeParserDeprecated::GetResult(TInstant defaultValue) const { Y_UNUSED(X509Validity4yDateTimeParser_en_main); return TDateTimeParserBaseDeprecated::GetResult(X509Validity4yDateTimeParser_first_final, defaultValue); @@ -444,34 +444,34 @@ TInstant TX509Validity4yDateTimeParser::GetResult(TInstant defaultValue) const { return TDateTimeParserBase::GetResult(X509Validity4yDateTimeParser_first_final, defaultValue); } -template<class TParser, class TResult> -static inline TResult Parse(const char* input, size_t len, TResult defaultValue) { - TParser parser; - if (!parser.ParsePart(input, len)) - return defaultValue; - return parser.GetResult(defaultValue); -} - +template<class TParser, class TResult> +static inline TResult Parse(const char* input, size_t len, TResult defaultValue) { + TParser parser; + if (!parser.ParsePart(input, len)) + return defaultValue; + return parser.GetResult(defaultValue); +} + template<class TParser, class TResult, bool ThrowExceptionOnFailure = true> -static inline TResult ParseUnsafe(const char* input, size_t len) { - TResult r = Parse<TParser, TResult>(input, len, TResult::Max()); +static inline TResult ParseUnsafe(const char* input, size_t len) { + TResult r = Parse<TParser, TResult>(input, len, TResult::Max()); if (ThrowExceptionOnFailure && r == TResult::Max()) ythrow TDateTimeParseException() << "error in datetime parsing. Input data: " << TStringBuf(input, len); - return r; -} - + return r; +} + TInstant TInstant::ParseIso8601Deprecated(const TStringBuf input) { return ParseUnsafe<TIso8601DateTimeParserDeprecated, TInstant>(input.data(), input.size()); -} - +} + TInstant TInstant::ParseRfc822Deprecated(const TStringBuf input) { return ParseUnsafe<TRfc822DateTimeParserDeprecated, TInstant>(input.data(), input.size()); -} - +} + TInstant TInstant::ParseHttpDeprecated(const TStringBuf input) { return ParseUnsafe<THttpDateTimeParserDeprecated, TInstant>(input.data(), input.size()); -} - +} + TInstant TInstant::ParseX509ValidityDeprecated(const TStringBuf input) { switch (input.size()) { case 13: @@ -482,7 +482,7 @@ TInstant TInstant::ParseX509ValidityDeprecated(const TStringBuf input) { ythrow TDateTimeParseException(); } } - + bool TInstant::TryParseIso8601Deprecated(const TStringBuf input, TInstant& instant) { const auto parsed = ParseUnsafe<TIso8601DateTimeParserDeprecated, TInstant, false>(input.data(), input.size()); if (TInstant::Max() == parsed) { @@ -663,44 +663,44 @@ bool ParseRFC822DateTime(const char* input, time_t& utcTime) { return ParseRFC822DateTime(input, strlen(input), utcTime); } -bool ParseISO8601DateTime(const char* input, time_t& utcTime) { - return ParseISO8601DateTime(input, strlen(input), utcTime); -} - -bool ParseHTTPDateTime(const char* input, time_t& utcTime) { - return ParseHTTPDateTime(input, strlen(input), utcTime); -} - +bool ParseISO8601DateTime(const char* input, time_t& utcTime) { + return ParseISO8601DateTime(input, strlen(input), utcTime); +} + +bool ParseHTTPDateTime(const char* input, time_t& utcTime) { + return ParseHTTPDateTime(input, strlen(input), utcTime); +} + bool ParseX509ValidityDateTime(const char* input, time_t& utcTime) { return ParseX509ValidityDateTime(input, strlen(input), utcTime); } - + bool ParseRFC822DateTime(const char* input, size_t inputLen, time_t& utcTime) { - try { + try { utcTime = ParseUnsafe<TRfc822DateTimeParser, TInstant>(input, inputLen).TimeT(); - return true; - } catch (const TDateTimeParseException&) { + return true; + } catch (const TDateTimeParseException&) { return false; - } -} - + } +} + bool ParseISO8601DateTime(const char* input, size_t inputLen, time_t& utcTime) { - try { + try { utcTime = ParseUnsafe<TIso8601DateTimeParser, TInstant>(input, inputLen).TimeT(); return true; - } catch (const TDateTimeParseException&) { - return false; + } catch (const TDateTimeParseException&) { + return false; } } - -bool ParseHTTPDateTime(const char* input, size_t inputLen, time_t& utcTime) { - try { + +bool ParseHTTPDateTime(const char* input, size_t inputLen, time_t& utcTime) { + try { utcTime = ParseUnsafe<THttpDateTimeParser, TInstant>(input, inputLen).TimeT(); - return true; - } catch (const TDateTimeParseException&) { - return false; - } -} + return true; + } catch (const TDateTimeParseException&) { + return false; + } +} bool ParseX509ValidityDateTime(const char* input, size_t inputLen, time_t& utcTime) { TInstant r; @@ -720,15 +720,15 @@ bool ParseX509ValidityDateTime(const char* input, size_t inputLen, time_t& utcTi return true; } -%%{ - -machine TDurationParser; - -include DateTimeParserCommon; - - -multiplier - = '' # >{ MultiplierPower = 6; } # work around Ragel bugs +%%{ + +machine TDurationParser; + +include DateTimeParserCommon; + + +multiplier + = '' # >{ MultiplierPower = 6; } # work around Ragel bugs | 'w' @{ MultiplierPower = 6; Multiplier = 604800; } | 'd' @{ MultiplierPower = 6; Multiplier = 86400; } | 'h' @{ MultiplierPower = 6; Multiplier = 3600; } @@ -737,57 +737,57 @@ multiplier | 'ms' @{ MultiplierPower = 3; Multiplier = 1; } | 'us' @{ MultiplierPower = 0; Multiplier = 1; } | 'ns' @{ MultiplierPower = -3; Multiplier = 1; } - ; - -integer = int @{ IntegerPart = I; }; - -fraction = '.' digit {1,6} >clear_int $update_int @{ FractionPart = I; FractionDigits = Dc; } digit*; - -duration = integer fraction? multiplier; - -main := duration; - -write data noerror; - -}%% - -TDurationParser::TDurationParser() - : cs(0) - , I(0) - , Dc(0) - , MultiplierPower(6) + ; + +integer = int @{ IntegerPart = I; }; + +fraction = '.' digit {1,6} >clear_int $update_int @{ FractionPart = I; FractionDigits = Dc; } digit*; + +duration = integer fraction? multiplier; + +main := duration; + +write data noerror; + +}%% + +TDurationParser::TDurationParser() + : cs(0) + , I(0) + , Dc(0) + , MultiplierPower(6) , Multiplier(1) - , IntegerPart(0) - , FractionPart(0) - , FractionDigits(0) -{ + , IntegerPart(0) + , FractionPart(0) + , FractionDigits(0) +{ Y_UNUSED(TDurationParser_en_main); - %% write init; -} - -bool TDurationParser::ParsePart(const char* input, size_t len) { - const char* p = input; - const char* pe = input + len; - - %% write exec; - return cs != %%{ write error; }%%; -} - + %% write init; +} + +bool TDurationParser::ParsePart(const char* input, size_t len) { + const char* p = input; + const char* pe = input + len; + + %% write exec; + return cs != %%{ write error; }%%; +} + static inline ui64 DecPower(ui64 part, i32 power) { if (power >= 0) return part * Power(10, power); return part / Power(10, -power); -} - -TDuration TDurationParser::GetResult(TDuration defaultValue) const { - if (cs < TDurationParser_first_final) - return defaultValue; - ui64 us = 0; +} + +TDuration TDurationParser::GetResult(TDuration defaultValue) const { + if (cs < TDurationParser_first_final) + return defaultValue; + ui64 us = 0; us += Multiplier * DecPower(IntegerPart, MultiplierPower); us += Multiplier * DecPower(FractionPart, MultiplierPower - FractionDigits); - return TDuration::MicroSeconds(us); -} - + return TDuration::MicroSeconds(us); +} + bool TDuration::TryParse(const TStringBuf input, TDuration& result) { TDuration r = ::Parse<TDurationParser, TDuration>(input.data(), input.size(), TDuration::Max()); if (r == TDuration::Max()) @@ -795,7 +795,7 @@ bool TDuration::TryParse(const TStringBuf input, TDuration& result) { result = r; return true; } - + TDuration TDuration::Parse(const TStringBuf input) { return ParseUnsafe<TDurationParser, TDuration>(input.data(), input.size()); -} +} diff --git a/util/datetime/parser_ut.cpp b/util/datetime/parser_ut.cpp index 0fc4d4993a..61364af997 100644 --- a/util/datetime/parser_ut.cpp +++ b/util/datetime/parser_ut.cpp @@ -22,31 +22,31 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 EST", t); UNIT_ASSERT(r); - UNIT_ASSERT_VALUES_EQUAL(t, (time_t)1109964885 + 5 * SECONDS_PER_HOUR); + UNIT_ASSERT_VALUES_EQUAL(t, (time_t)1109964885 + 5 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 EDT", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 4 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 4 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 CST", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 6 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 6 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 CDT", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 5 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 5 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 MST", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 7 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 7 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 MDT", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 6 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 6 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 PST", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 8 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 8 * SECONDS_PER_HOUR); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 PDT", t); UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 7 * SECONDS_PER_HOUR); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 7 * SECONDS_PER_HOUR); // optinal century r = ParseRFC822DateTime("Fri, 4 Mar 05 19:34:45 UT", t); @@ -118,14 +118,14 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { r = ParseRFC822DateTime(" \t Fri, \t 4 \t Mar \t 2005 \t 19:34:45 \t UT \t ", t); // spaces with tabs UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964885); - + r = ParseRFC822DateTime("Thu, 01 Jan 1970 03:00:00 +0300", t); // spaces with tabs - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)0); - + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)0); + r = ParseRFC822DateTime("Sat, 14 Feb 2009 02:31:30 +0300", t); // spaces with tabs - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1234567890); + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)1234567890); } time_t GetOffset(char militaryZone) { @@ -143,7 +143,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { } } - void DoTestMilitaryZones(char firstChar, char lastChar) { + void DoTestMilitaryZones(char firstChar, char lastChar) { const time_t utcTime = 1109964885; // Fri, 4 Mar 2005 19:34:45 UT char text[] = "Fri, 4 Mar 2005 19:34:45 A"; const size_t zoneCharIndex = strlen(text) - 1; @@ -155,17 +155,17 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { text[zoneCharIndex] = militaryZone; UNIT_ASSERT(ParseRFC822DateTime(text, t)); - UNIT_ASSERT_EQUAL(t, utcTime - offset); + UNIT_ASSERT_EQUAL(t, utcTime - offset); } } Y_UNIT_TEST(TestRfc822MilitaryZones) { - DoTestMilitaryZones('A', 'I'); - DoTestMilitaryZones('K', 'Z'); - DoTestMilitaryZones('a', 'i'); - DoTestMilitaryZones('k', 'z'); - } - + DoTestMilitaryZones('A', 'I'); + DoTestMilitaryZones('K', 'Z'); + DoTestMilitaryZones('a', 'i'); + DoTestMilitaryZones('k', 'z'); + } + Y_UNIT_TEST(TestRfc822IncorrectDates) { bool r = true; time_t t = 0; @@ -219,7 +219,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { r = ParseRFC822DateTime("17 Nov 2008 19:34:123 UT", t); UNIT_ASSERT(!r); r = ParseRFC822DateTime("17 Nov 2008 19:34:12.12 UT", t); // fractions of second are now allowed - UNIT_ASSERT(!r); + UNIT_ASSERT(!r); r = ParseRFC822DateTime("Mon , 17 Nov 2005 19:34:45 UT", t); // space after day before the comma UNIT_ASSERT(!r); @@ -254,113 +254,113 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { r = ParseRFC822DateTime("Mon, 17 Nov 2008 19:34:45 -03030", t); UNIT_ASSERT(!r); } - + Y_UNIT_TEST(TestRfc822Partial) { TRfc822DateTimeParser p; - const char* part1 = "Fri, 4 Mar 05 1"; - const char* part2 = "9:34:45 +0300"; - UNIT_ASSERT(p.ParsePart(part1, strlen(part1))); - UNIT_ASSERT(p.ParsePart(part2, strlen(part2))); - UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1109954085), p.GetResult(TInstant::Max())); + const char* part1 = "Fri, 4 Mar 05 1"; + const char* part2 = "9:34:45 +0300"; + UNIT_ASSERT(p.ParsePart(part1, strlen(part1))); + UNIT_ASSERT(p.ParsePart(part2, strlen(part2))); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1109954085), p.GetResult(TInstant::Max())); p = TRfc822DateTimeParser(); const char* part3 = "Fri, 4 Mar 05 19:34:46 +0300"; UNIT_ASSERT(p.ParsePart(part3, strlen(part3))); UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1109954086), p.GetResult(TInstant::Zero())); - } + } Y_UNIT_TEST(TestIso8601Partial) { TIso8601DateTimeParser p; - const char* part1 = "1990-03-15T15:1"; - const char* part2 = "6:17+0732"; - UNIT_ASSERT(p.ParsePart(part1, strlen(part1))); - UNIT_ASSERT(p.ParsePart(part2, strlen(part2))); - UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(637487057), p.GetResult(TInstant::Max())); + const char* part1 = "1990-03-15T15:1"; + const char* part2 = "6:17+0732"; + UNIT_ASSERT(p.ParsePart(part1, strlen(part1))); + UNIT_ASSERT(p.ParsePart(part2, strlen(part2))); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(637487057), p.GetResult(TInstant::Max())); p = TIso8601DateTimeParser(); const char* part3 = "1990-03-15T15:16:18+0732"; UNIT_ASSERT(p.ParsePart(part3, strlen(part3))); UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(637487058), p.GetResult(TInstant::Zero())); - } - + } + Y_UNIT_TEST(TestIso8601Correct) { - bool ret; - time_t t; - - // ISO 8601 actually does not allow time without time zone + bool ret; + time_t t; + + // ISO 8601 actually does not allow time without time zone ret = ParseISO8601DateTime("1990-03-15", t); - UNIT_ASSERT(ret); + UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 637459200); - - // some normal dates + + // some normal dates ret = ParseISO8601DateTime("1990-03-15T15:16:17Z", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637514177); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637514177); + ret = ParseISO8601DateTime("1990-03-15t15:16:17z", t); // lower-case must be allowed too - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637514177); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637514177); + ret = ParseISO8601DateTime("1990-03-15 15:16:17Z", t); // space as separator should be allowed - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637514177); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637514177); + ret = ParseISO8601DateTime("1990-03-15T15:16:17.18Z", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637514177); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637514177); + ret = ParseISO8601DateTime("1990-03-15T15:16:17.18+07:32", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637487057); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637487057); + ret = ParseISO8601DateTime("1990-03-15T15:16:17.18+0732", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 637487057); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 637487057); + ret = ParseISO8601DateTime("1970-01-01T00:00:00Z", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 0); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 0); + ret = ParseISO8601DateTime("1970-01-01T00:01:02Z", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 62); - -#if 0 - // these tests are disabled, because time zones are handled differently - // in old util/ parser and agalakhov@ parser + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 62); + +#if 0 + // these tests are disabled, because time zones are handled differently + // in old util/ parser and agalakhov@ parser ret = ParseISO8601DateTime("1970-01-01", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, -4 * 3600); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, -4 * 3600); + ret = ParseISO8601DateTime("1970-01-02", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 86400 - 3 * 3600); -#endif - - // this is wrong because of timezone + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 86400 - 3 * 3600); +#endif + + // this is wrong because of timezone ret = ParseISO8601DateTime("2009-02-14T03:31:30", t); - UNIT_ASSERT(ret); + UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 1234582290); - + ret = ParseISO8601DateTime("2009-02-14t03:31:30", t); - UNIT_ASSERT(ret); + UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 1234582290); - + ret = ParseISO8601DateTime("2009-02-14T02:31:30+0300", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); + ret = ParseISO8601DateTime("2009-02-14T02:31:30+03:00", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); - + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); + ret = ParseISO8601DateTime("2009-02-14 02:31:30+03:00", t); - UNIT_ASSERT(ret); - UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); + UNIT_ASSERT(ret); + UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); ret = ParseISO8601DateTime("2010-03-28T04:27:00.000-07:00", t); UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 1269775620); - } - + } + Y_UNIT_TEST(TestIso8601TimeZone) { time_t t1, t2, t3, t4; UNIT_ASSERT(ParseISO8601DateTime("2010-03-28T04:27:00.000+07:00", t1)); @@ -373,54 +373,54 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { } Y_UNIT_TEST(TestIso8601Incorrect) { - bool ret; - time_t t; - + bool ret; + time_t t; + t = 12345; ret = ParseISO8601DateTime("", t); UNIT_ASSERT(!ret); UNIT_ASSERT_EQUAL(t, (time_t)12345); - // some bad dates + // some bad dates t = 54321; ret = ParseISO8601DateTime("a990-01-15", t); - UNIT_ASSERT(!ret); + UNIT_ASSERT(!ret); UNIT_ASSERT_EQUAL(t, (time_t)54321); - + ret = ParseISO8601DateTime("1970-01-01T03:00:00+04:00", t); // this is 1969 GMT UNIT_ASSERT(!ret); ret = ParseISO8601DateTime("1987-13-16", t); - UNIT_ASSERT(!ret); - + UNIT_ASSERT(!ret); + ret = ParseISO8601DateTime("1987-02-29", t); - UNIT_ASSERT(!ret); - + UNIT_ASSERT(!ret); + ret = ParseISO8601DateTime("1990-03-151Y15:16:17.18", t); - UNIT_ASSERT(!ret); - + UNIT_ASSERT(!ret); + ret = ParseISO8601DateTime("1990-03-151T15:16:17:43.18", t); - UNIT_ASSERT(!ret); - + UNIT_ASSERT(!ret); + ret = ParseISO8601DateTime("1990-03-151T15:16:17.18Z+21:32", t); - UNIT_ASSERT(!ret); - } - + UNIT_ASSERT(!ret); + } + Y_UNIT_TEST(TestIso8601Fractions) { - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:08.1+04:00"), TInstant::Seconds(1253317028) + TDuration::MilliSeconds(100)); - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.926+04:00"), TInstant::Seconds(1253317023) + TDuration::MilliSeconds(926)); - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.92622+04:00"), TInstant::Seconds(1253317023) + TDuration::MicroSeconds(926220)); - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.012331+04:00"), TInstant::Seconds(1253317023) + TDuration::MicroSeconds(12331)); - } - + } + Y_UNIT_TEST(TestIso8601FractionsBelowMicro) { UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("1970-01-01 00:00:00.0000000+00:00"), @@ -472,26 +472,26 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { } Y_UNIT_TEST(TestHttpDate) { - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseHttp("Sun, 06 Nov 1994 08:49:37 GMT"), TInstant::ParseIso8601("1994-11-06T08:49:37Z")); - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseHttp("Sunday, 06-Nov-94 08:49:37 GMT"), TInstant::ParseIso8601("1994-11-06T08:49:37Z")); - UNIT_ASSERT_VALUES_EQUAL( + UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseHttp("Sun Nov 6 08:49:37 1994"), TInstant::ParseIso8601("1994-11-06T08:49:37Z")); UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseHttp("Mon, 19 Jan 2037 08:49:37 GMT"), TInstant::ParseIso8601("2037-01-19T08:49:37Z")); - } - + } + Y_UNIT_TEST(TestHttpDateIncorrect) { - bool ret; - time_t t = 0; + bool ret; + time_t t = 0; ret = ParseHTTPDateTime("1990-03-15T15:16:17Z", t); - UNIT_ASSERT(!ret); - } + UNIT_ASSERT(!ret); + } Y_UNIT_TEST(TestX509ValidityTime) { UNIT_ASSERT_VALUES_EQUAL( @@ -568,8 +568,8 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { UNIT_ASSERT(!TInstant::TryParseX509(s, iTry)); } } -} - +} + Y_UNIT_TEST_SUITE(TDurationParseTest) { Y_UNIT_TEST(TestParse) { UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(60 * 60 * 24 * 7), TDuration::Parse("1w")); @@ -605,23 +605,23 @@ Y_UNIT_TEST_SUITE(TDurationParseTest) { UNIT_ASSERT_VALUES_EQUAL(TDuration::Hours(36), TDuration::Parse("1d12h")); #endif - UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(10), TDuration::Parse("10s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(10), TDuration::Parse("10.000s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(4), TDuration::Parse("0.000004s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3456), TDuration::Parse("3.456s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.450s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.45000000s")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.45s")); - - UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(1), TDuration::Parse("1ms")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(1100), TDuration::Parse("1.1ms")); - - UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(112), TDuration::Parse("112")); - UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(14456), TDuration::Parse("14456us")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(10), TDuration::Parse("10s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(10), TDuration::Parse("10.000s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(4), TDuration::Parse("0.000004s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3456), TDuration::Parse("3.456s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.450s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.45000000s")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(3450), TDuration::Parse("3.45s")); + + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(1), TDuration::Parse("1ms")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(1100), TDuration::Parse("1.1ms")); + + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(112), TDuration::Parse("112")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(14456), TDuration::Parse("14456us")); UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(1), TDuration::Parse("1000ns")); UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(1), TDuration::Parse("0.000001s")); UNIT_ASSERT_EQUAL(TDuration(), TDuration::Parse("10ns")); // TDuration has 1us precision. - } -} + } +} diff --git a/util/datetime/systime.cpp b/util/datetime/systime.cpp index 21f106e9da..6ee7e8fc6e 100644 --- a/util/datetime/systime.cpp +++ b/util/datetime/systime.cpp @@ -1,10 +1,10 @@ #include "systime.h" - + #include <util/system/yassert.h> #include <util/system/defaults.h> -#ifdef _win_ - +#ifdef _win_ + void FileTimeToTimeval(const FILETIME* ft, timeval* tv) { const i64 NANOINTERVAL = LL(116444736000000000); // Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 union { @@ -34,7 +34,7 @@ tm* localtime_r(const time_t* clock, tm* result) { } tm* gmtime_r(const time_t* clock, tm* result) { - return gmtime_s(result, clock) == 0 ? result : 0; + return gmtime_s(result, clock) == 0 ? result : 0; } char* ctime_r(const time_t* clock, char* buf) { |