/* * Copyright (C) 2017-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #pragma once #include #include #include #include #include // Wrapper for a value with a type-tag for differentiating instances. template class cql_duration_counter final { public: using value_type = Value; explicit constexpr cql_duration_counter(value_type count) noexcept : _count(count) {} constexpr operator value_type() const noexcept { return _count; } private: value_type _count; }; using months_counter = cql_duration_counter; using days_counter = cql_duration_counter; using nanoseconds_counter = cql_duration_counter; class cql_duration_error : public std::invalid_argument { public: explicit cql_duration_error(std::string_view what) : std::invalid_argument(what.data()) {} virtual ~cql_duration_error() = default; }; // // A duration of time. // // Three counters represent the time: the number of months, of days, and of nanoseconds. This is necessary because // the number hours in a day can vary during daylight savings and because the number of days in a month vary. // // As a consequence of this representation, there can exist no total ordering relation on durations. To see why, // consider a duration `1mo5s` (1 month and 5 seconds). In a month with 30 days, this represents a smaller duration of // time than in a month with 31 days. // // The primary use of this type is to manipulate absolute time-stamps with relative offsets. For example, // `"Jan. 31 2005 at 23:15" + 3mo5d`. // class cql_duration final { public: using common_counter_type = int64_t; static_assert( (sizeof(common_counter_type) >= sizeof(months_counter::value_type)) && (sizeof(common_counter_type) >= sizeof(days_counter::value_type)) && (sizeof(common_counter_type) >= sizeof(nanoseconds_counter::value_type)), "The common counter type is smaller than one of the component counter types."); // A zero-valued duration. constexpr cql_duration() noexcept = default; // Construct a duration with explicit values for its three counters. constexpr cql_duration(months_counter m, days_counter d, nanoseconds_counter n) noexcept : months(m), days(d), nanoseconds(n) {} // // Parse a duration string. // // Three formats for durations are supported: // // 1. "Standard" format. This consists of one or more pairs of a count and a unit specifier. Examples are "23d1mo" // and "5h23m10s". Components of the total duration must be written in decreasing order. That is, "5h2y" is // an invalid duration string. // // The allowed units are: // - "y": years // - "mo": months // - "w": weeks // - "d": days // - "h": hours // - "m": minutes // - "s": seconds // - "ms": milliseconds // - "us" or "µs": microseconds // - "ns": nanoseconds // // Units are case-insensitive. // // 2. ISO-8601 format. "P[n]Y[n]M[n]DT[n]H[n]M[n]S" or "P[n]W". All specifiers are optional. Examples are // "P23Y1M" or "P10W". // // 3. ISO-8601 alternate format. "P[YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]". All specifiers are mandatory. An example is // "P2000-10-14T07:22:30". // // For all formats, a negative duration is indicated by beginning the string with the '-' symbol. For example, // "-2y10ns". // // Throws `cql_duration_error` in the event of a parsing error. // explicit cql_duration(std::string_view s); months_counter::value_type months{0}; days_counter::value_type days{0}; nanoseconds_counter::value_type nanoseconds{0}; // // Note that equality comparison is based on exact counter matches. It is not valid to expect equivalency across // counters like months and days. See the documentation for `duration` for more. // friend bool operator==(const cql_duration&, const cql_duration&) noexcept = default; }; // // Pretty-print a duration using the standard format. // // Durations are simplified during printing so that `duration(24, 0, 0)` is printed as "2y". // std::ostream& operator<<(std::ostream& os, const cql_duration& d); // See above. seastar::sstring to_string(const cql_duration&);