Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:39

0001 //
0002 // Copyright (c) 2019-2023 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_DETAIL_DATETIME_HPP
0009 #define BOOST_MYSQL_DETAIL_DATETIME_HPP
0010 
0011 // All these algorithms have been taken from:
0012 // http://howardhinnant.github.io/date_algorithms.html
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 // Helpers
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 // Interface
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);            // [0, 399]
0062     const unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;  // [0, 365]
0063     const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;           // [0, 146096]
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     // Prevent overflow
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);         // [0, 146096]
0082     const unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;  // [0, 399]
0083     const int y = static_cast<int>(yoe) + era * 400;
0084     const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);  // [0, 365]
0085     const unsigned mp = (5 * doy + 2) / 153;                       // [0, 11]
0086     const unsigned d = doy - (153 * mp + 2) / 5 + 1;               // [1, 31]
0087     const unsigned m = mp + (mp < 10 ? 3 : -9);                    // [1, 12]
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 }  // namespace detail
0101 }  // namespace mysql
0102 }  // namespace boost
0103 
0104 #endif