9 #include <botan/calendar.h>
10 #include <botan/exceptn.h>
14 #include <botan/mutex.h>
17 #if defined(BOTAN_HAS_BOOST_DATETIME)
18 #include <boost/date_time/posix_time/posix_time_types.hpp>
25 std::tm do_gmtime(std::time_t time_val)
29 #if defined(BOTAN_TARGET_OS_HAS_GMTIME_S)
30 gmtime_s(&tm, &time_val);
31 #elif defined(BOTAN_TARGET_OS_HAS_GMTIME_R)
32 gmtime_r(&time_val, &tm);
34 std::tm* tm_p = std::gmtime(&time_val);
36 throw Encoding_Error(
"time_t_to_tm could not convert");
43 #if !defined(BOTAN_TARGET_OS_HAS_TIMEGM) && !(defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC))
45 #if defined(BOTAN_HAS_BOOST_DATETIME)
47 std::time_t boost_timegm(std::tm *tm)
49 const int sec = tm->tm_sec;
50 const int min = tm->tm_min;
51 const int hour = tm->tm_hour;
52 const int day = tm->tm_mday;
53 const int mon = tm->tm_mon + 1;
54 const int year = tm->tm_year + 1900;
59 using namespace boost::posix_time;
60 using namespace boost::gregorian;
61 const auto epoch = ptime(date(1970, 01, 01));
62 const auto time = ptime(date(year, mon, day),
63 hours(hour) + minutes(min) + seconds(sec));
64 const time_duration diff(time - epoch);
65 out = diff.ticks() / diff.ticks_per_second();
71 #elif defined(BOTAN_OS_TYPE_IS_UNIX)
73 #pragma message "Caution! A fallback version of timegm() is used which is not thread-safe"
77 std::time_t fallback_timegm(std::tm *tm)
80 std::string tz_backup;
85 const char* tz_env_pointer = ::getenv(
"TZ");
86 if (tz_env_pointer !=
nullptr)
87 tz_backup = std::string(tz_env_pointer);
90 ::setenv(
"TZ",
"", 1);
96 if (!tz_backup.empty())
99 ::setenv(
"TZ", tz_backup.data(), 1);
111 #endif // BOTAN_HAS_BOOST_DATETIME
120 throw Invalid_Argument(
"calendar_point::to_std_timepoint() does not support years before 1970.");
125 if (year > 2037 &&
sizeof(std::time_t) == 4)
127 throw Invalid_Argument(
"calendar_point::to_std_timepoint() does not support years after 2037.");
137 tm.tm_mon =
month - 1;
138 tm.tm_year = year - 1900;
141 #if defined(BOTAN_TARGET_OS_HAS_TIMEGM)
142 std::time_t (&botan_timegm)(std::tm *tm) = timegm;
143 #elif defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
145 std::time_t (&botan_timegm)(std::tm *tm) = _mkgmtime;
146 #elif defined(BOTAN_HAS_BOOST_DATETIME)
147 std::time_t (&botan_timegm)(std::tm *tm) = boost_timegm;
148 #elif defined(BOTAN_OS_TYPE_IS_UNIX)
149 std::time_t (&botan_timegm)(std::tm *tm) = fallback_timegm;
151 std::time_t (&botan_timegm)(std::tm *tm) = mktime;
155 std::time_t tt = botan_timegm(&tm);
159 return std::chrono::system_clock::from_time_t(tt);
165 std::stringstream output;
168 output << setfill(
'0')
169 << setw(4) << year <<
"-" << setw(2) <<
month <<
"-" << setw(2) << day
171 << setw(2) << hour <<
":" << setw(2) <<
minutes <<
":" << setw(2) <<
seconds;
178 const std::chrono::system_clock::time_point& time_point)
180 std::tm tm = do_gmtime(std::chrono::system_clock::to_time_t(time_point));
std::chrono::system_clock::time_point to_std_timepoint() const
std::string to_string() const
calendar_point(uint32_t y, uint32_t mon, uint32_t d, uint32_t h, uint32_t min, uint32_t sec)
calendar_point calendar_value(const std::chrono::system_clock::time_point &time_point)