LCOV - code coverage report
Current view: top level - core/core/utils - SPTime.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 65 95.4 %
Date: 2024-05-12 00:16:13 Functions: 42 43 97.7 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_CORE_UTILS_SPTIME_H_
      25             : #define STAPPLER_CORE_UTILS_SPTIME_H_
      26             : 
      27             : #include "SPStringView.h"
      28             : 
      29             : #define SP_COMPILE_TIME (STAPPLER_VERSIONIZED_NAMESPACE::Time::fromCompileTime(__DATE__, __TIME__))
      30             : 
      31             : namespace STAPPLER_VERSIONIZED stappler {
      32             : 
      33             : class Time;
      34             : 
      35             : struct sp_time_exp_t {
      36             :         enum tm_gmt_e {
      37             :                 gmt_unset,
      38             :                 gmt_local,
      39             :                 gmt_set,
      40             :         };
      41             : 
      42             :         int32_t tm_usec; /** microseconds past tm_sec */
      43             :         int32_t tm_sec; /** (0-61) seconds past tm_min */
      44             :         int32_t tm_min; /** (0-59) minutes past tm_hour */
      45             :         int32_t tm_hour; /** (0-23) hours past midnight */
      46             :         int32_t tm_mday; /** (1-31) day of the month */
      47             :         int32_t tm_mon; /** (0-11) month of the year */
      48             :         int32_t tm_year; /** year since 1900 */
      49             :         int32_t tm_wday; /** (0-6) days since Sunday */
      50             :         int32_t tm_yday; /** (0-365) days since January 1 */
      51             :         int32_t tm_isdst; /** daylight saving time */
      52             :         int32_t tm_gmtoff; /** seconds east of UTC */
      53             :         tm_gmt_e tm_gmt_type = gmt_unset;
      54             : 
      55             :         sp_time_exp_t();
      56             :         sp_time_exp_t(int64_t t, int32_t offset, bool use_localtime);
      57             :         sp_time_exp_t(int64_t t, int32_t offs);
      58             :         sp_time_exp_t(int64_t t);
      59             :         sp_time_exp_t(int64_t t, bool use_localtime);
      60             : 
      61             :         sp_time_exp_t(Time t, int32_t offset, bool use_localtime);
      62             :         sp_time_exp_t(Time t, int32_t offs);
      63             :         sp_time_exp_t(Time t);
      64             :         sp_time_exp_t(Time t, bool use_localtime);
      65             : 
      66             :         /*
      67             :          * Parses an HTTP date in one of three standard forms:
      68             :          *
      69             :          *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
      70             :          *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
      71             :          *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
      72             :          *     2011-04-28T06:34:00+09:00      ; Atom time format
      73             :          */
      74             :         bool read(StringView);
      75             : 
      76             :         Time get() const;
      77             :         Time gmt_get() const;
      78             :         Time ltz_get() const;
      79             : 
      80             :         int64_t geti() const;
      81             :         int64_t gmt_geti() const;
      82             :         int64_t ltz_geti() const;
      83             : 
      84             :         size_t encodeRfc822(char *) const;
      85             :         size_t encodeCTime(char *) const;
      86             :         size_t encodeIso8601(char *, size_t precision) const;
      87             : };
      88             : 
      89             : class TimeStorage {
      90             : public:
      91             :         uint64_t toMicroseconds() const;
      92             :         uint64_t toMilliseconds() const;
      93             :         uint64_t toSeconds() const;
      94             :         float toFloatSeconds() const;
      95             : 
      96      595225 :         uint64_t toMicros() const { return toMicroseconds(); }
      97             :         uint64_t toMillis() const { return toMilliseconds(); }
      98             : 
      99         336 :         uint64_t mksec() const { return toMicroseconds(); }
     100             :         uint64_t msec() const { return toMilliseconds(); }
     101           0 :         uint64_t sec() const { return toSeconds(); }
     102             :         float fsec() const { return toFloatSeconds(); }
     103             : 
     104             :         struct tm asLocal() const;
     105             :         struct tm asGmt() const;
     106             : 
     107          25 :         void setMicros(uint64_t value) { setMicroseconds(value); }
     108          25 :         void setMillis(uint64_t value) { setMilliseconds(value); }
     109             : 
     110             :         void setMicroseconds(uint64_t);
     111             :         void setMilliseconds(uint64_t);
     112             :         void setSeconds(time_t);
     113             : 
     114             :         void clear();
     115             : 
     116       95252 :         constexpr explicit operator bool () const noexcept { return _value != 0; }
     117             : 
     118         175 :         TimeStorage() = default;
     119             :         TimeStorage(const TimeStorage &) = default;
     120             :         TimeStorage(TimeStorage &&) = default;
     121             :         TimeStorage & operator= (const TimeStorage &) = default;
     122             :         TimeStorage & operator= (TimeStorage &&) = default;
     123             : 
     124     1783747 :     constexpr TimeStorage(uint64_t v) : _value(v) { }
     125             : 
     126             : protected:
     127             :         uint64_t _value = 0;
     128             : };
     129             : 
     130             : class TimeInterval : public TimeStorage {
     131             : public:
     132             :         static TimeInterval between(const Time &, const Time &);
     133             : 
     134      466278 :         constexpr static TimeInterval microseconds(uint64_t mksec) {
     135      466278 :                 return TimeInterval(mksec);
     136             :         }
     137         336 :         constexpr static TimeInterval milliseconds(uint64_t msec) {
     138         336 :                 return TimeInterval(msec * 1000ULL);
     139             :         }
     140        7131 :         constexpr static TimeInterval seconds(time_t sec) {
     141        7131 :                 return TimeInterval(sec * 1000000ULL);
     142             :         }
     143           2 :         constexpr static TimeInterval floatSeconds(float sec) {
     144           2 :                 return TimeInterval(uint64_t(sec * 1000000.0f));
     145             :         }
     146             : 
     147             :     inline const Time operator+(const Time& v) const;
     148             : 
     149             :     inline const TimeInterval operator+(const TimeInterval& v) const;
     150             :     inline TimeInterval& operator+=(const TimeInterval& v);
     151             : 
     152             :     inline const TimeInterval operator-(const TimeInterval& v) const;
     153             :     inline TimeInterval& operator-=(const TimeInterval& v);
     154             : 
     155             :     inline const TimeInterval operator*(float s) const;
     156             :     inline TimeInterval& operator*=(float s);
     157             : 
     158             :     inline const TimeInterval operator/(float s) const;
     159             :     inline TimeInterval& operator/=(float s);
     160             : 
     161             :     inline bool operator<(const TimeInterval& v) const;
     162             :     inline bool operator>(const TimeInterval& v) const;
     163             :     inline bool operator<=(const TimeInterval& v) const;
     164             :     inline bool operator>=(const TimeInterval& v) const;
     165             :     inline bool operator==(const TimeInterval& v) const;
     166             :     inline bool operator!=(const TimeInterval& v) const;
     167             : 
     168             :         TimeInterval(nullptr_t);
     169             :         TimeInterval & operator= (nullptr_t);
     170             : 
     171        2806 :         constexpr TimeInterval() : TimeStorage(0) { }
     172      561280 :         constexpr TimeInterval(const TimeInterval &other) : TimeStorage(other._value) { }
     173         120 :         constexpr TimeInterval(TimeInterval &&other) : TimeStorage(other._value) { }
     174        1128 :         constexpr TimeInterval & operator= (const TimeInterval &other) { _value = other._value; return *this; }
     175         966 :         constexpr TimeInterval & operator= (TimeInterval &&other) { _value = other._value; return *this; }
     176             : 
     177             : protected:
     178             :     friend class Time;
     179             : 
     180             :     using TimeStorage::TimeStorage;
     181             : };
     182             : 
     183             : class Time : public TimeStorage {
     184             : public:
     185             :         static Time now();
     186             : 
     187             :         static Time fromCompileTime(const char *, const char *);
     188             : 
     189             :         /*
     190             :          * Parses an HTTP date in one of three standard forms:
     191             :          *
     192             :          *     Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
     193             :          *     Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
     194             :          *     Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
     195             :          *     2011-04-28T06:34:00+09:00      ; Atom time format
     196             :          */
     197             :         static Time fromHttp(StringView);
     198             : 
     199             :         static Time microseconds(uint64_t mksec);
     200             :         static Time milliseconds(uint64_t msec);
     201             :         static Time seconds(time_t sec);
     202             :         static Time floatSeconds(float sec);
     203             : 
     204             :         template <typename Interface>
     205        1450 :         auto toHttp() const -> typename Interface::StringType {
     206        1450 :                 return toRfc822<Interface>();
     207             :         }
     208             : 
     209             :         template <typename Interface>
     210             :         auto toAtomXml() const -> typename Interface::StringType {
     211             :                 return toIso8601<Interface>(0);
     212             :         }
     213             : 
     214             :         template <typename Interface>
     215        1450 :         auto toRfc822() const -> typename Interface::StringType {
     216        1450 :                 sp_time_exp_t xt(*this);
     217        1450 :                 char buf[30] = { 0 };
     218        1450 :                 return typename Interface::StringType(buf, xt.encodeRfc822(buf));
     219             :         }
     220             : 
     221             :         template <typename Interface>
     222         275 :         auto toCTime() const -> typename Interface::StringType {
     223         275 :                 sp_time_exp_t xt(*this, true);
     224         275 :                 char buf[25] = { 0 };
     225         275 :                 return typename Interface::StringType(buf, xt.encodeCTime(buf));
     226             :         }
     227             : 
     228             :         // ISO 8601 dateTime format, used by XML/Atom
     229             :         // - YYYY-MM-DDThh:mm:ss[.sss]
     230             :         // precision defined as digit after decimal sep
     231             :         // min - 0 - no decimal
     232             :         //       3 - milliseconds precision
     233             :         // max - 6 - microseconds precision
     234             :         template <typename Interface>
     235         550 :         auto toIso8601(size_t precision = 0) const -> typename Interface::StringType {
     236         550 :                 sp_time_exp_t xt(*this, false);
     237         550 :                 char buf[30] = { 0 };
     238         550 :                 return typename Interface::StringType(buf, xt.encodeIso8601(buf, precision));
     239             :         }
     240             : 
     241             :         template <typename Interface>
     242          25 :         auto toFormat(const char *fmt) const -> typename Interface::StringType {
     243          25 :                 char buf[256] = { 0 }; // should be enough
     244          25 :                 return typename Interface::StringType(buf, encodeToFormat(buf, 256, fmt));
     245             :         }
     246             : 
     247             :     inline const Time operator+(const TimeInterval& v) const;
     248             :     inline Time& operator+=(const TimeInterval& v);
     249             : 
     250             :     inline const TimeInterval operator-(const Time& v) const;
     251             :     inline const Time operator-(const TimeInterval& v) const;
     252             :     inline Time& operator-=(const TimeInterval& v);
     253             : 
     254             :     inline bool operator<(const Time& v) const;
     255             :     inline bool operator>(const Time& v) const;
     256             :     inline bool operator<=(const Time& v) const;
     257             :     inline bool operator>=(const Time& v) const;
     258             :     inline bool operator==(const Time& v) const;
     259             :     inline bool operator!=(const Time& v) const;
     260             : 
     261             :         Time(nullptr_t);
     262             :         Time & operator= (nullptr_t);
     263             : 
     264       33906 :         Time() : TimeStorage(0) { }
     265       29180 :         Time(const Time &other) : TimeStorage(other._value) { }
     266       13150 :         Time(Time &&other) : TimeStorage(other._value) { }
     267        7467 :         Time & operator= (const Time &other) { _value = other._value; return *this; }
     268       15364 :         Time & operator= (Time &&other) { _value = other._value; return *this; }
     269             : 
     270             :         size_t encodeToFormat(char *, size_t, const char *fmt) const;
     271             : 
     272             : protected:
     273             :     friend class TimeInterval;
     274             : 
     275             :     using TimeStorage::TimeStorage;
     276             : };
     277             : 
     278        5625 : constexpr TimeInterval operator"" _sec ( unsigned long long int val ) { return TimeInterval::seconds((time_t)val); }
     279          24 : constexpr TimeInterval operator"" _msec ( unsigned long long int val ) { return TimeInterval::milliseconds(val); }
     280             : constexpr TimeInterval operator"" _mksec ( unsigned long long int val ) { return TimeInterval::microseconds(val); }
     281             : 
     282             : 
     283             : inline const Time TimeInterval::operator+(const Time& v) const {
     284             :         return v + *this;
     285             : }
     286             : 
     287             : inline const TimeInterval TimeInterval::operator+(const TimeInterval& v) const {
     288             :         return TimeInterval(_value + v._value);
     289             : }
     290             : inline TimeInterval& TimeInterval::operator+=(const TimeInterval& v) {
     291             :         _value += v._value;
     292             :         return *this;
     293             : }
     294             : 
     295       47568 : inline const TimeInterval TimeInterval::operator-(const TimeInterval& v) const {
     296       47568 :         if (_value < v._value) {
     297           0 :                 return TimeInterval();
     298             :         } else {
     299       47568 :                 return TimeInterval(_value - v._value);
     300             :         }
     301             : }
     302             : inline TimeInterval& TimeInterval::operator-=(const TimeInterval& v) {
     303             :         if (_value < v._value) {
     304             :                 _value = 0;
     305             :         } else {
     306             :                 _value -= v._value;
     307             :         }
     308             :         return *this;
     309             : }
     310             : 
     311             : inline const TimeInterval TimeInterval::operator*(float s) const {
     312             :         return TimeInterval(_value * fabsf(s));
     313             : }
     314             : inline TimeInterval& TimeInterval::operator*=(float s) {
     315             :         _value *= fabsf(s);
     316             :         return *this;
     317             : }
     318             : 
     319             : inline const TimeInterval TimeInterval::operator/(float s) const {
     320             :         return TimeInterval(_value / fabsf(s));
     321             : }
     322             : inline TimeInterval& TimeInterval::operator/=(float s) {
     323             :         _value /= fabsf(s);
     324             :         return *this;
     325             : }
     326             : 
     327         774 : inline bool TimeInterval::operator<(const TimeInterval& v) const { return _value < v._value; }
     328       59686 : inline bool TimeInterval::operator>(const TimeInterval& v) const { return _value > v._value; }
     329             : inline bool TimeInterval::operator<=(const TimeInterval& v) const { return _value <= v._value; }
     330       71704 : inline bool TimeInterval::operator>=(const TimeInterval& v) const { return _value >= v._value; }
     331         106 : inline bool TimeInterval::operator==(const TimeInterval& v) const { return _value == v._value; }
     332         175 : inline bool TimeInterval::operator!=(const TimeInterval& v) const { return _value != v._value; }
     333             : 
     334        2381 : inline const Time Time::operator+(const TimeInterval& v) const {
     335        2381 :         return Time(_value + v._value);
     336             : }
     337             : inline Time& Time::operator+=(const TimeInterval& v) {
     338             :         _value += v._value;
     339             :         return *this;
     340             : }
     341             : 
     342       13814 : inline const TimeInterval Time::operator-(const Time& v) const {
     343       13814 :         return TimeInterval::between(*this, v);
     344             : }
     345         583 : inline const Time Time::operator-(const TimeInterval& v) const {
     346         583 :         if (_value < v._value) {
     347           0 :                 return Time();
     348             :         }
     349         583 :         return Time(_value - v._value);
     350             : }
     351             : inline Time& Time::operator-=(const TimeInterval& v) {
     352             :         if (_value < v._value) {
     353             :                 _value = 0;
     354             :         }
     355             :         _value -= v._value;
     356             :         return *this;
     357             : }
     358             : 
     359        1644 : inline bool Time::operator<(const Time& v) const { return _value < v._value; }
     360       11638 : inline bool Time::operator>(const Time& v) const { return _value > v._value; }
     361             : inline bool Time::operator<=(const Time& v) const { return _value <= v._value; }
     362             : inline bool Time::operator>=(const Time& v) const { return _value >= v._value; }
     363             : inline bool Time::operator==(const Time& v) const { return _value == v._value; }
     364         375 : inline bool Time::operator!=(const Time& v) const { return _value != v._value; }
     365             : 
     366             : }
     367             : 
     368             : #endif /* STAPPLER_CORE_UTILS_SPTIME_H_ */

Generated by: LCOV version 1.14