File indexing completed on 2025-01-18 09:42:39
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_DETAIL_DATETIME_HPP
0009 #define BOOST_MYSQL_DETAIL_DATETIME_HPP
0010
0011
0012
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016
0017 #include <cstdint>
0018 #include <limits>
0019
0020 namespace boost {
0021 namespace mysql {
0022 namespace detail {
0023
0024
0025 constexpr unsigned char last_month_day_arr[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
0026
0027 constexpr bool is_leap(std::uint16_t y) noexcept { return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); }
0028
0029 constexpr inline std::uint8_t last_month_day(std::uint16_t y, std::uint8_t m) noexcept
0030 {
0031 return m != 2 || !is_leap(y) ? last_month_day_arr[m - 1] : 29u;
0032 }
0033
0034
0035 constexpr std::uint16_t max_year = 9999;
0036 constexpr std::uint8_t max_month = 12;
0037 constexpr std::uint8_t max_day = 31;
0038 constexpr std::uint8_t max_hour = 23;
0039 constexpr std::uint8_t max_min = 59;
0040 constexpr std::uint8_t max_sec = 59;
0041 constexpr std::uint32_t max_micro = 999999;
0042
0043 constexpr inline bool is_valid(std::uint16_t years, std::uint8_t month, std::uint8_t day) noexcept
0044 {
0045 return years <= max_year && month > 0 && month <= max_month && day > 0 &&
0046 day <= last_month_day(years, month);
0047 }
0048
0049 BOOST_CXX14_CONSTEXPR inline int ymd_to_days(
0050 std::uint16_t years,
0051 std::uint8_t month,
0052 std::uint8_t day
0053 ) noexcept
0054 {
0055 BOOST_ASSERT(is_valid(years, month, day));
0056 int y = years;
0057 const int m = month;
0058 const int d = day;
0059 y -= m <= 2;
0060 const int era = (y >= 0 ? y : y - 399) / 400;
0061 const unsigned yoe = static_cast<unsigned>(y - era * 400);
0062 const unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
0063 const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
0064 return era * 146097 + static_cast<int>(doe) - 719468;
0065 }
0066
0067 BOOST_CXX14_CONSTEXPR inline bool days_to_ymd(
0068 int num_days,
0069 std::uint16_t& years,
0070 std::uint8_t& month,
0071 std::uint8_t& day
0072 ) noexcept
0073 {
0074
0075 constexpr int days_magic = 719468;
0076 if (num_days > (std::numeric_limits<int>::max)() - days_magic)
0077 return false;
0078
0079 num_days += days_magic;
0080 const int era = (num_days >= 0 ? num_days : num_days - 146096) / 146097;
0081 const unsigned doe = static_cast<unsigned>(num_days - era * 146097);
0082 const unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
0083 const int y = static_cast<int>(yoe) + era * 400;
0084 const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
0085 const unsigned mp = (5 * doy + 2) / 153;
0086 const unsigned d = doy - (153 * mp + 2) / 5 + 1;
0087 const unsigned m = mp + (mp < 10 ? 3 : -9);
0088 const int final_year = y + (m <= 2);
0089 if (final_year < 0 || final_year > static_cast<int>(max_year))
0090 return false;
0091 else
0092 {
0093 years = static_cast<std::uint16_t>(final_year);
0094 month = static_cast<std::uint8_t>(m);
0095 day = static_cast<std::uint8_t>(d);
0096 return true;
0097 }
0098 }
0099
0100 }
0101 }
0102 }
0103
0104 #endif