|
|
|||
File indexing completed on 2025-12-15 09:58:33
0001 // 0002 // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 0008 #ifndef BOOST_MYSQL_DATE_HPP 0009 #define BOOST_MYSQL_DATE_HPP 0010 0011 #include <boost/mysql/days.hpp> 0012 0013 #include <boost/mysql/detail/config.hpp> 0014 #include <boost/mysql/detail/datetime.hpp> 0015 0016 #include <boost/assert.hpp> 0017 #include <boost/config.hpp> 0018 #include <boost/throw_exception.hpp> 0019 0020 #include <chrono> 0021 #include <cstdint> 0022 #include <iosfwd> 0023 #include <stdexcept> 0024 0025 namespace boost { 0026 namespace mysql { 0027 0028 /** 0029 * \brief Type representing MySQL `DATE` data type. 0030 * \details 0031 * Represents a Gregorian date broken by its year, month and day components, without a time zone. 0032 * \n 0033 * This type is close to the protocol and should not be used as a vocabulary type. 0034 * Instead, cast it to a `std::chrono::time_point` by calling \ref as_time_point, 0035 * \ref get_time_point, \ref as_local_time_point or \ref get_local_time_point. 0036 * \n 0037 * Dates retrieved from MySQL don't include any time zone information. Determining the time zone 0038 * is left to the application. Thus, any time point obtained from this class should be 0039 * interpreted as a local time in an unspecified time zone, like `std::chrono::local_time`. 0040 * For compatibility with older compilers, \ref as_time_point and \ref get_time_point return 0041 * `system_clock` time points. These should be interpreted as local times rather 0042 * than UTC. Prefer using \ref as_local_time_point or \ref get_local_time_point 0043 * if your compiler supports them, as they provide more accurate semantics. 0044 * \n 0045 * As opposed to `time_point`, this type allows representing MySQL invalid and zero dates. 0046 * These values are allowed by MySQL but don't represent real dates. 0047 * \n 0048 * Note: using `std::chrono` time zone functionality under MSVC may cause memory leaks to be reported. 0049 * See <a href="https://github.com/microsoft/STL/issues/2047">this issue</a> for an explanation and 0050 * <a href="https://github.com/microsoft/STL/issues/2504">this other issue</a> for a workaround. 0051 */ 0052 class date 0053 { 0054 public: 0055 /** 0056 * \brief A `std::chrono::time_point` that can represent any valid `date`. 0057 * \details 0058 * Time points used by this class are always local times, even if defined 0059 * to use the system clock. 0060 */ 0061 using time_point = std::chrono::time_point<std::chrono::system_clock, days>; 0062 0063 /** 0064 * \brief Constructs a zero date. 0065 * \details 0066 * Results in a date with all of its components set to zero. 0067 * The resulting object has `this->valid() == false`. 0068 * 0069 * \par Exception safety 0070 * No-throw guarantee. 0071 */ 0072 constexpr date() noexcept = default; 0073 0074 /** 0075 * \brief Constructs a date from its year, month and date components. 0076 * \details 0077 * Component values that yield invalid dates (like zero or out-of-range 0078 * values) are allowed, resulting in an object with `this->valid() == false`. 0079 * 0080 * \par Exception safety 0081 * No-throw guarantee. 0082 */ 0083 constexpr date(std::uint16_t year, std::uint8_t month, std::uint8_t day) noexcept 0084 : year_(year), month_(month), day_(day) 0085 { 0086 } 0087 0088 /** 0089 * \brief Constructs a date from a `time_point`. 0090 * \details 0091 * The time point is interpreted as a local time. No time zone conversion is performed. 0092 * 0093 * \par Exception safety 0094 * Strong guarantee. Throws on invalid input. 0095 * \throws std::out_of_range If the resulting `date` would be 0096 * out of the [\ref min_date, \ref max_date] range. 0097 */ 0098 BOOST_CXX14_CONSTEXPR explicit date(time_point tp) 0099 { 0100 bool ok = detail::days_to_ymd(tp.time_since_epoch().count(), year_, month_, day_); 0101 if (!ok) 0102 BOOST_THROW_EXCEPTION(std::out_of_range("date::date: time_point was out of range")); 0103 } 0104 0105 #ifdef BOOST_MYSQL_HAS_LOCAL_TIME 0106 /** 0107 * \brief Constructs a date from a local time point. 0108 * \details 0109 * Equivalent to constructing a `date` from a `time_point` with the same 0110 * `time_since_epoch()` as `tp`. 0111 * \n 0112 * Requires C++20 calendar types. 0113 * 0114 * \par Exception safety 0115 * Strong guarantee. Throws on invalid input. 0116 * \throws std::out_of_range If the resulting `date` would be 0117 * out of the [\ref min_date, \ref max_date] range. 0118 */ 0119 constexpr explicit date(std::chrono::local_days tp) : date(time_point(tp.time_since_epoch())) {} 0120 #endif 0121 0122 /** 0123 * \brief Retrieves the year component. 0124 * \details 0125 * Represents the year number in the Gregorian calendar. 0126 * If `this->valid() == true`, this value is within the `[0, 9999]` range. 0127 * 0128 * \par Exception safety 0129 * No-throw guarantee. 0130 */ 0131 constexpr std::uint16_t year() const noexcept { return year_; } 0132 0133 /** 0134 * \brief Retrieves the month component (1-based). 0135 * \details 0136 * A value of 1 represents January. 0137 * If `this->valid() == true`, this value is within the `[1, 12]` range. 0138 * 0139 * \par Exception safety 0140 * No-throw guarantee. 0141 */ 0142 constexpr std::uint8_t month() const noexcept { return month_; } 0143 0144 /** 0145 * \brief Retrieves the day component (1-based). 0146 * \details 0147 * A value of 1 represents the first day of the month. 0148 * If `this->valid() == true`, this value is within the `[1, last_month_day]` range 0149 * (where `last_month_day` is the last day of the month). 0150 * 0151 * \par Exception safety 0152 * No-throw guarantee. 0153 */ 0154 constexpr std::uint8_t day() const noexcept { return day_; } 0155 0156 /** 0157 * \brief Returns `true` if `*this` represents a valid `time_point`. 0158 * \details If any of the individual components is out of range, the date 0159 * doesn't represent an actual `time_point` (e.g. `date(2020, 2, 30)`) or 0160 * the date is not in the [\ref min_date, \ref max_date] validity range, 0161 * returns `false`. Otherwise, returns `true`. 0162 * \par Exception safety 0163 * No-throw guarantee. 0164 */ 0165 constexpr bool valid() const noexcept { return detail::is_valid(year_, month_, day_); } 0166 0167 /** 0168 * \brief Converts `*this` into a `time_point` (unchecked access). 0169 * \details 0170 * If your compiler supports it, prefer using \ref get_local_time_point, 0171 * as it provides more accurate semantics. 0172 * 0173 * \par Preconditions 0174 * `this->valid() == true` (if violated, results in undefined behavior). 0175 * 0176 * \par Exception safety 0177 * No-throw guarantee. 0178 */ 0179 BOOST_CXX14_CONSTEXPR time_point get_time_point() const noexcept 0180 { 0181 BOOST_ASSERT(valid()); 0182 return time_point(unch_get_days()); 0183 } 0184 0185 /** 0186 * \brief Converts `*this` into a `time_point` (checked access). 0187 * \details 0188 * If your compiler supports it, prefer using \ref as_local_time_point, 0189 * as it provides more accurate semantics. 0190 * 0191 * \par Exception safety 0192 * Strong guarantee. 0193 * \throws std::invalid_argument If `!this->valid()`. 0194 */ 0195 BOOST_CXX14_CONSTEXPR time_point as_time_point() const 0196 { 0197 if (!valid()) 0198 BOOST_THROW_EXCEPTION(std::invalid_argument("date::as_time_point: invalid date")); 0199 return time_point(unch_get_days()); 0200 } 0201 0202 #ifdef BOOST_MYSQL_HAS_LOCAL_TIME 0203 /** 0204 * \brief Converts `*this` into a local time point (unchecked access). 0205 * \details 0206 * The returned object has the same `time_since_epoch()` as `this->get_time_point()`, 0207 * but uses the `std::chrono::local_t` pseudo-clock to better represent 0208 * the absence of time zone information. 0209 * \n 0210 * Requires C++20 calendar types. 0211 * 0212 * \par Preconditions 0213 * `this->valid() == true` (if violated, results in undefined behavior). 0214 * 0215 * \par Exception safety 0216 * No-throw guarantee. 0217 */ 0218 constexpr std::chrono::local_days get_local_time_point() const noexcept 0219 { 0220 BOOST_ASSERT(valid()); 0221 return std::chrono::local_days(unch_get_days()); 0222 } 0223 0224 /** 0225 * \brief Converts `*this` into a local time point (checked access). 0226 * \details 0227 * The returned object has the same `time_since_epoch()` as `this->as_time_point()`, 0228 * but uses the `std::chrono::local_t` pseudo-clock to better represent 0229 * the absence of time zone information. 0230 * \n 0231 * Requires C++20 calendar types. 0232 * 0233 * \par Exception safety 0234 * Strong guarantee. 0235 * \throws std::invalid_argument If `!this->valid()`. 0236 */ 0237 constexpr std::chrono::local_days as_local_time_point() const 0238 { 0239 if (!valid()) 0240 BOOST_THROW_EXCEPTION(std::invalid_argument("date::as_local_time_point: invalid date")); 0241 return std::chrono::local_days(unch_get_days()); 0242 } 0243 #endif 0244 0245 /** 0246 * \brief Tests for equality. 0247 * \details Two dates are considered equal if all of its individual components 0248 * are equal. This function works for invalid dates, too. 0249 * 0250 * \par Exception safety 0251 * No-throw guarantee. 0252 */ 0253 constexpr bool operator==(const date& rhs) const noexcept 0254 { 0255 return year_ == rhs.year_ && month_ == rhs.month_ && day_ == rhs.day_; 0256 } 0257 0258 /** 0259 * \brief Tests for inequality. 0260 * 0261 * \par Exception safety 0262 * No-throw guarantee. 0263 */ 0264 constexpr bool operator!=(const date& rhs) const noexcept { return !(rhs == *this); } 0265 0266 /** 0267 * \brief Returns the current system time as a date object. 0268 * \par Exception safety 0269 * Strong guarantee. Only throws if obtaining the current time throws. 0270 */ 0271 static date now() 0272 { 0273 auto now = time_point::clock::now(); 0274 return date(std::chrono::time_point_cast<time_point::duration>(now)); 0275 } 0276 0277 private: 0278 std::uint16_t year_{}; 0279 std::uint8_t month_{}; 0280 std::uint8_t day_{}; 0281 0282 BOOST_CXX14_CONSTEXPR days unch_get_days() const 0283 { 0284 return days(detail::ymd_to_days(year_, month_, day_)); 0285 } 0286 }; 0287 0288 /** 0289 * \relates date 0290 * \brief Streams a date. 0291 * \details This function works for invalid dates, too. 0292 */ 0293 BOOST_MYSQL_DECL 0294 std::ostream& operator<<(std::ostream& os, const date& v); 0295 0296 /// The minimum allowed value for \ref date. 0297 BOOST_INLINE_CONSTEXPR date min_date{0u, 1u, 1u}; 0298 0299 /// The maximum allowed value for \ref date. 0300 BOOST_INLINE_CONSTEXPR date max_date{9999u, 12u, 31u}; 0301 0302 } // namespace mysql 0303 } // namespace boost 0304 0305 #ifdef BOOST_MYSQL_HEADER_ONLY 0306 #include <boost/mysql/impl/date.ipp> 0307 #endif 0308 0309 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|