datetime.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. //
  2. // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_DATETIME_HPP
  8. #define BOOST_MYSQL_DATETIME_HPP
  9. #include <boost/mysql/days.hpp>
  10. #include <boost/config.hpp>
  11. #include <chrono>
  12. #include <cstdint>
  13. #include <iosfwd>
  14. #include <ratio>
  15. namespace boost {
  16. namespace mysql {
  17. /**
  18. * \brief Type representing MySQL `DATETIME` and `TIMESTAMP` data types.
  19. * \details Represents a broken datetime by its year, month, day, hour, minute, second and
  20. * microsecond components. This type is close to the protocol and should not be used as a vocabulary
  21. * type. Instead, cast it to a `std::chrono::time_point` by calling \ref as_time_point or \ref
  22. * get_time_point.
  23. * \n
  24. * As opposed to `time_point`, this type allows representing invalid and zero datetimes.
  25. */
  26. class datetime
  27. {
  28. public:
  29. /**
  30. * \brief A `std::chrono::time_point` that can represent any valid datetime.
  31. * \details Represents microseconds since the UNIX epoch, with the same precision for all architectures.
  32. */
  33. using time_point = std::chrono::
  34. time_point<std::chrono::system_clock, std::chrono::duration<std::int64_t, std::micro>>;
  35. /**
  36. * \brief Constructs a zero datetime.
  37. * \details Results in a datetime with all of its components set to zero.
  38. * \par Exception safety
  39. * No-throw guarantee.
  40. */
  41. constexpr datetime() noexcept = default;
  42. /**
  43. * \brief Constructs a datetime from its individual components.
  44. * \par Exception safety
  45. * No-throw guarantee.
  46. */
  47. constexpr datetime(
  48. std::uint16_t year,
  49. std::uint8_t month,
  50. std::uint8_t day,
  51. std::uint8_t hour = 0,
  52. std::uint8_t minute = 0,
  53. std::uint8_t second = 0,
  54. std::uint32_t microsecond = 0
  55. ) noexcept
  56. : year_(year),
  57. month_(month),
  58. day_(day),
  59. hour_(hour),
  60. minute_(minute),
  61. second_(second),
  62. microsecond_(microsecond)
  63. {
  64. }
  65. /**
  66. * \brief Constructs a datetime from a `time_point`.
  67. * \par Exception safety
  68. * Strong guarantee. Throws on invalid input.
  69. * \throws std::out_of_range If the resulting `datetime` object would be
  70. * out of the [\ref min_datetime, \ref max_datetime] range.
  71. */
  72. BOOST_CXX14_CONSTEXPR inline explicit datetime(time_point tp);
  73. /**
  74. * \brief Retrieves the year component.
  75. * \par Exception safety
  76. * No-throw guarantee.
  77. */
  78. constexpr std::uint16_t year() const noexcept { return year_; }
  79. /**
  80. * \brief Retrieves the month component.
  81. * \par Exception safety
  82. * No-throw guarantee.
  83. */
  84. constexpr std::uint8_t month() const noexcept { return month_; }
  85. /**
  86. * \brief Retrieves the day component.
  87. * \par Exception safety
  88. * No-throw guarantee.
  89. */
  90. constexpr std::uint8_t day() const noexcept { return day_; }
  91. /**
  92. * \brief Retrieves the hour component.
  93. * \par Exception safety
  94. * No-throw guarantee.
  95. */
  96. constexpr std::uint8_t hour() const noexcept { return hour_; }
  97. /**
  98. * \brief Retrieves the minute component.
  99. * \par Exception safety
  100. * No-throw guarantee.
  101. */
  102. constexpr std::uint8_t minute() const noexcept { return minute_; }
  103. /**
  104. * \brief Retrieves the second component.
  105. * \par Exception safety
  106. * No-throw guarantee.
  107. */
  108. constexpr std::uint8_t second() const noexcept { return second_; }
  109. /**
  110. * \brief Retrieves the microsecond component.
  111. * \par Exception safety
  112. * No-throw guarantee.
  113. */
  114. constexpr std::uint32_t microsecond() const noexcept { return microsecond_; }
  115. /**
  116. * \brief Returns `true` if `*this` represents a valid `time_point`.
  117. * \details If any of the individual components is out of range, the datetime
  118. * doesn't represent an actual `time_point` (e.g. `datetime(2020, 2, 30)`) or
  119. * the datetime is not in the [\ref min_date, \ref max_date] validity range,
  120. * returns `false`. Otherwise, returns `true`.
  121. *
  122. * \par Exception safety
  123. * No-throw guarantee.
  124. */
  125. constexpr bool valid() const noexcept;
  126. /**
  127. * \brief Converts `*this` into a `time_point` (unchecked access).
  128. * \par Preconditions
  129. * `this->valid() == true` (if violated, results in undefined behavior).
  130. *
  131. * \par Exception safety
  132. * No-throw guarantee.
  133. */
  134. BOOST_CXX14_CONSTEXPR inline time_point get_time_point() const noexcept;
  135. /**
  136. * \brief Converts `*this` into a `time_point` (checked access).
  137. * \par Exception safety
  138. * Strong guarantee.
  139. * \throws std::invalid_argument If `!this->valid()`.
  140. */
  141. BOOST_CXX14_CONSTEXPR inline time_point as_time_point() const;
  142. /**
  143. * \brief Tests for equality.
  144. * \details Two datetimes are considered equal if all of its individual components
  145. * are equal. This function works for invalid datetimes, too.
  146. *
  147. * \par Exception safety
  148. * No-throw guarantee.
  149. */
  150. constexpr bool operator==(const datetime& rhs) const noexcept;
  151. /**
  152. * \brief Tests for inequality.
  153. * \par Exception safety
  154. * No-throw guarantee.
  155. */
  156. constexpr bool operator!=(const datetime& rhs) const noexcept { return !(*this == rhs); }
  157. /**
  158. * \brief Returns the current system time as a datetime object.
  159. * \par Exception safety
  160. * Strong guarantee. Only throws if obtaining the current time throws.
  161. */
  162. static datetime now()
  163. {
  164. auto now = time_point::clock::now();
  165. return datetime(std::chrono::time_point_cast<time_point::duration>(now));
  166. }
  167. private:
  168. std::uint16_t year_{};
  169. std::uint8_t month_{};
  170. std::uint8_t day_{};
  171. std::uint8_t hour_{};
  172. std::uint8_t minute_{};
  173. std::uint8_t second_{};
  174. std::uint32_t microsecond_{};
  175. BOOST_CXX14_CONSTEXPR inline time_point unch_get_time_point() const noexcept;
  176. };
  177. /**
  178. * \relates datetime
  179. * \brief Streams a datetime.
  180. * \details This function works for invalid datetimes, too.
  181. */
  182. inline std::ostream& operator<<(std::ostream& os, const datetime& v);
  183. /// The minimum allowed value for \ref datetime.
  184. constexpr datetime min_datetime(0u, 1u, 1u);
  185. /// The maximum allowed value for \ref datetime.
  186. constexpr datetime max_datetime(9999u, 12u, 31u, 23u, 59u, 59u, 999999u);
  187. } // namespace mysql
  188. } // namespace boost
  189. #include <boost/mysql/impl/datetime.hpp>
  190. #endif