date.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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_DATE_HPP
  8. #define BOOST_MYSQL_DATE_HPP
  9. #include <boost/mysql/days.hpp>
  10. #include <boost/mysql/detail/auxiliar/datetime.hpp>
  11. #include <boost/config.hpp>
  12. #include <chrono>
  13. #include <cstdint>
  14. #include <iosfwd>
  15. namespace boost {
  16. namespace mysql {
  17. /**
  18. * \brief Type representing MySQL `DATE` data type.
  19. * \details Represents a broken date by its year, month and day components.
  20. * This type is close to the protocol and should not be used as a vocabulary type.
  21. * Instead, cast it to a `std::chrono::time_point` by calling \ref as_time_point
  22. * or \ref get_time_point.
  23. * \n
  24. * As opposed to `time_point`, this type allows representing invalid and zero dates.
  25. */
  26. class date
  27. {
  28. public:
  29. /// A `std::chrono::time_point` that can represent any valid `date`.
  30. using time_point = std::chrono::time_point<std::chrono::system_clock, days>;
  31. /**
  32. * \brief Constructs a zero date.
  33. * \details
  34. * Results in a date with all of its components set to zero.
  35. *
  36. * \par Exception safety
  37. * No-throw guarantee.
  38. */
  39. constexpr date() noexcept = default;
  40. /**
  41. * \brief Constructs a date from its year, month and date components.
  42. * \par Exception safety
  43. * No-throw guarantee.
  44. */
  45. constexpr date(std::uint16_t year, std::uint8_t month, std::uint8_t day) noexcept
  46. : year_(year), month_(month), day_(day)
  47. {
  48. }
  49. /**
  50. * \brief Constructs a date from a `time_point`.
  51. * \par Exception safety
  52. * Strong guarantee. Throws on invalid input.
  53. * \throws std::out_of_range If the resulting `date` would be
  54. * out of the [\ref min_date, \ref max_date] range.
  55. */
  56. BOOST_CXX14_CONSTEXPR inline explicit date(time_point tp);
  57. /**
  58. * \brief Retrieves the year component.
  59. * \par Exception safety
  60. * No-throw guarantee.
  61. */
  62. constexpr std::uint16_t year() const noexcept { return year_; }
  63. /**
  64. * \brief Retrieves the month component.
  65. * \par Exception safety
  66. * No-throw guarantee.
  67. */
  68. constexpr std::uint8_t month() const noexcept { return month_; }
  69. /**
  70. * \brief Retrieves the day component.
  71. * \par Exception safety
  72. * No-throw guarantee.
  73. */
  74. constexpr std::uint8_t day() const noexcept { return day_; }
  75. /**
  76. * \brief Returns `true` if `*this` represents a valid `time_point`.
  77. * \details If any of the individual components is out of range, the date
  78. * doesn't represent an actual `time_point` (e.g. `date(2020, 2, 30)`) or
  79. * the date is not in the [\ref min_date, \ref max_date] validity range,
  80. * returns `false`. Otherwise, returns `true`.
  81. * \par Exception safety
  82. * No-throw guarantee.
  83. */
  84. constexpr bool valid() const noexcept { return detail::is_valid(year_, month_, day_); }
  85. /**
  86. * \brief Converts `*this` into a `time_point` (unchecked access).
  87. * \par Preconditions
  88. * `this->valid() == true` (if violated, results in undefined behavior).
  89. *
  90. * \par Exception safety
  91. * No-throw guarantee.
  92. */
  93. BOOST_CXX14_CONSTEXPR inline time_point get_time_point() const noexcept;
  94. /**
  95. * \brief Converts `*this` into a `time_point` (checked access).
  96. * \par Exception safety
  97. * Strong guarantee.
  98. * \throws std::invalid_argument If `!this->valid()`.
  99. */
  100. BOOST_CXX14_CONSTEXPR inline time_point as_time_point() const;
  101. /**
  102. * \brief Tests for equality.
  103. * \details Two dates are considered equal if all of its individual components
  104. * are equal. This function works for invalid dates, too.
  105. *
  106. * \par Exception safety
  107. * No-throw guarantee.
  108. */
  109. constexpr bool operator==(const date& rhs) const noexcept;
  110. /**
  111. * \brief Tests for inequality.
  112. *
  113. * \par Exception safety
  114. * No-throw guarantee.
  115. */
  116. constexpr bool operator!=(const date& rhs) const noexcept { return !(rhs == *this); }
  117. /**
  118. * \brief Returns the current system time as a date object.
  119. * \par Exception safety
  120. * Strong guarantee. Only throws if obtaining the current time throws.
  121. */
  122. static date now()
  123. {
  124. auto now = time_point::clock::now();
  125. return date(std::chrono::time_point_cast<time_point::duration>(now));
  126. }
  127. private:
  128. std::uint16_t year_{};
  129. std::uint8_t month_{};
  130. std::uint8_t day_{};
  131. BOOST_CXX14_CONSTEXPR inline time_point unch_get_time_point() const noexcept;
  132. };
  133. /**
  134. * \relates date
  135. * \brief Streams a date.
  136. * \details This function works for invalid dates, too.
  137. */
  138. inline std::ostream& operator<<(std::ostream& os, const date& v);
  139. /// The minimum allowed value for \ref date.
  140. constexpr date min_date{0u, 1u, 1u};
  141. /// The maximum allowed value for \ref date.
  142. constexpr date max_date{9999u, 12u, 31u};
  143. } // namespace mysql
  144. } // namespace boost
  145. #include <boost/mysql/impl/date.hpp>
  146. #endif