summaryrefslogtreecommitdiff
path: root/http/utility.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'http/utility.hpp')
-rw-r--r--http/utility.hpp143
1 files changed, 111 insertions, 32 deletions
diff --git a/http/utility.hpp b/http/utility.hpp
index d6f31d0717..5ca1dea151 100644
--- a/http/utility.hpp
+++ b/http/utility.hpp
@@ -4,7 +4,6 @@
#include <openssl/crypto.h>
#include <boost/callable_traits.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/url/url.hpp>
#include <nlohmann/json.hpp>
@@ -14,6 +13,7 @@
#include <cstdint>
#include <ctime>
#include <functional>
+#include <iomanip>
#include <limits>
#include <stdexcept>
#include <string>
@@ -541,55 +541,134 @@ inline bool base64Decode(const std::string_view input, std::string& output)
namespace details
{
-constexpr uint64_t maxMilliSeconds = 253402300799999;
-constexpr uint64_t maxSeconds = 253402300799;
-inline std::string getDateTime(boost::posix_time::milliseconds timeSinceEpoch)
+// Returns year/month/day triple in civil calendar
+// Preconditions: z is number of days since 1970-01-01 and is in the range:
+// [numeric_limits<Int>::min(),
+// numeric_limits<Int>::max()-719468].
+// Algorithm sourced from
+// https://howardhinnant.github.io/date_algorithms.html#civil_from_days
+// All constants are explained in the above
+template <class IntType>
+constexpr std::tuple<IntType, unsigned, unsigned>
+ civilFromDays(IntType z) noexcept
+{
+ z += 719468;
+ IntType era = (z >= 0 ? z : z - 146096) / 146097;
+ unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
+ unsigned yoe =
+ (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399]
+ IntType y = static_cast<IntType>(yoe) + era * 400;
+ unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365]
+ unsigned mp = (5 * doy + 2) / 153; // [0, 11]
+ unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31]
+ unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12]
+
+ return std::tuple<IntType, unsigned, unsigned>(y + (m <= 2), m, d);
+}
+
+// Creates a string from an integer in the most efficient way possible without
+// using std::locale. Adds an exact zero pad based on the pad input parameter.
+// Does not handle negative numbers.
+inline std::string padZeros(int value, size_t pad)
{
- boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
- boost::posix_time::ptime time = epoch + timeSinceEpoch;
- // append zero offset to the end according to the Redfish spec for Date-Time
- return boost::posix_time::to_iso_extended_string(time) + "+00:00";
+ std::string result(pad, '0');
+ for (int val = value; pad > 0; pad--)
+ {
+ result[pad - 1] = static_cast<char>('0' + val % 10);
+ val /= 10;
+ }
+ return result;
+}
+
+template <typename IntType, typename Period>
+std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
+{
+ using seconds = std::chrono::duration<int>;
+ using minutes = std::chrono::duration<int, std::ratio<60>>;
+ using hours = std::chrono::duration<int, std::ratio<3600>>;
+ using days = std::chrono::duration<
+ IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
+
+ // d is days since 1970-01-01
+ days d = std::chrono::duration_cast<days>(t);
+
+ // t is now time duration since midnight of day d
+ t -= d;
+
+ // break d down into year/month/day
+ int year = 0;
+ int month = 0;
+ int day = 0;
+ std::tie(year, month, day) = details::civilFromDays(d.count());
+ // Check against limits. Can't go above year 9999, and can't go below epoch
+ // (1970)
+ if (year >= 10000)
+ {
+ year = 9999;
+ month = 12;
+ day = 31;
+ t = days(1) - std::chrono::duration<IntType, Period>(1);
+ }
+ else if (year < 1970)
+ {
+ year = 1970;
+ month = 1;
+ day = 1;
+ t = std::chrono::duration<IntType, Period>::zero();
+ }
+ std::string out;
+ out += details::padZeros(year, 4);
+ out += '-';
+ out += details::padZeros(month, 2);
+ out += '-';
+ out += details::padZeros(day, 2);
+
+ out += 'T';
+ hours hr = duration_cast<hours>(t);
+ out += details::padZeros(hr.count(), 2);
+ t -= hr;
+ out += ':';
+
+ minutes mt = duration_cast<minutes>(t);
+ out += details::padZeros(mt.count(), 2);
+ t -= mt;
+ out += ':';
+
+ seconds se = duration_cast<seconds>(t);
+ out += details::padZeros(se.count(), 2);
+
+ out += "+00:00";
+ return out;
}
} // namespace details
// Returns the formatted date time string.
// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
// the given |secondsSinceEpoch| is too large, we return the maximum supported
-// date. This behavior is to avoid exceptions throwed by Boost.
+// date.
inline std::string getDateTimeUint(uint64_t secondsSinceEpoch)
{
- secondsSinceEpoch = std::min(secondsSinceEpoch, details::maxSeconds);
- boost::posix_time::seconds boostSeconds(secondsSinceEpoch);
- return details::getDateTime(
- boost::posix_time::milliseconds(boostSeconds.total_milliseconds()));
+ using DurationType = std::chrono::duration<uint64_t>;
+ DurationType sinceEpoch(secondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
}
// Returns the formatted date time string.
-// Note that the maximum supported date is 9999-12-31T23:59:59.999+00:00, if
-// the given |millisSecondsSinceEpoch| is too large, we return the maximum
-// supported date.
+// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
+// the given |secondsSinceEpoch| is too large, we return the maximum supported
+// date.
inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch)
{
- milliSecondsSinceEpoch =
- std::min(details::maxMilliSeconds, milliSecondsSinceEpoch);
- return details::getDateTime(
- boost::posix_time::milliseconds(milliSecondsSinceEpoch));
+ using DurationType = std::chrono::duration<uint64_t, std::milli>;
+ DurationType sinceEpoch(milliSecondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
}
inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch)
{
- // secondsSinceEpoch >= maxSeconds
- if constexpr (std::cmp_less_equal(details::maxSeconds,
- std::numeric_limits<std::time_t>::max()))
- {
- if (std::cmp_greater_equal(secondsSinceEpoch, details::maxSeconds))
- {
- secondsSinceEpoch = details::maxSeconds;
- }
- }
- boost::posix_time::ptime time =
- boost::posix_time::from_time_t(secondsSinceEpoch);
- return boost::posix_time::to_iso_extended_string(time) + "+00:00";
+ using DurationType = std::chrono::duration<std::time_t>;
+ DurationType sinceEpoch(secondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
}
/**