5#include "../SqlColumnTypeDefinitions.hpp"
22 using native_type = std::chrono::system_clock::time_point;
23 using duration_type = std::chrono::system_clock::duration;
28 return SqlDateTime { std::chrono::system_clock::now() };
38 constexpr std::weak_ordering operator<=>(
SqlDateTime const& other) const noexcept
42 constexpr bool operator==(
SqlDateTime const& other)
const noexcept
44 return (*this <=> other) == std::weak_ordering::equivalent;
47 constexpr bool operator!=(
SqlDateTime const& other)
const noexcept
49 return !(*
this == other);
53 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlDateTime(std::chrono::year_month_day ymd,
54 std::chrono::hh_mm_ss<duration_type> time)
noexcept:
56 .year = (SQLSMALLINT) (
int) ymd.year(),
57 .month = (SQLUSMALLINT) (
unsigned) ymd.month(),
58 .day = (SQLUSMALLINT) (
unsigned) ymd.day(),
59 .hour = (SQLUSMALLINT) time.hours().count(),
60 .minute = (SQLUSMALLINT) time.minutes().count(),
61 .second = (SQLUSMALLINT) time.seconds().count(),
63 (SQLUINTEGER) (std::chrono::duration_cast<std::chrono::nanoseconds>(time.to_duration()).count() / 100) * 100,
70 std::chrono::year
year,
71 std::chrono::month
month,
73 std::chrono::hours
hour,
74 std::chrono::minutes
minute,
75 std::chrono::seconds
second,
76 std::chrono::nanoseconds
nanosecond = std::chrono::nanoseconds(0)) noexcept:
78 .year = (SQLSMALLINT) (
int)
year,
79 .month = (SQLUSMALLINT) (
unsigned)
month,
80 .day = (SQLUSMALLINT) (
unsigned)
day,
81 .hour = (SQLUSMALLINT)
hour.count(),
82 .minute = (SQLUSMALLINT)
minute.count(),
83 .second = (SQLUSMALLINT)
second.count(),
84 .fraction = (SQLUINTEGER) (
nanosecond.count() / 100) * 100,
90 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlDateTime(std::chrono::system_clock::time_point
value)
noexcept:
91 sqlValue { ConvertToSqlValue(
value) }
96 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::year
year() const noexcept
98 return std::chrono::year(
static_cast<int>(sqlValue.year));
102 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::month
month() const noexcept
104 return std::chrono::month(
static_cast<unsigned>(sqlValue.month));
108 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::day
day() const noexcept
110 return std::chrono::day(
static_cast<unsigned>(sqlValue.day));
114 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::hours
hour() const noexcept
116 return std::chrono::hours(
static_cast<unsigned>(sqlValue.hour));
120 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::minutes
minute() const noexcept
122 return std::chrono::minutes(
static_cast<unsigned>(sqlValue.minute));
126 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::seconds
second() const noexcept
128 return std::chrono::seconds(
static_cast<unsigned>(sqlValue.second));
132 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::nanoseconds
nanosecond() const noexcept
134 return std::chrono::nanoseconds(
static_cast<unsigned>(sqlValue.fraction));
137 LIGHTWEIGHT_FORCE_INLINE
constexpr operator native_type() const noexcept
142 static LIGHTWEIGHT_FORCE_INLINE SQL_TIMESTAMP_STRUCT
constexpr ConvertToSqlValue(native_type
value)
noexcept
144 using namespace std::chrono;
145 auto const totalDays = floor<days>(
value);
146 auto const ymd = year_month_day { totalDays };
148 hh_mm_ss<duration_type> { std::chrono::duration_cast<duration_type>(floor<nanoseconds>(
value - totalDays)) };
149 return ConvertToSqlValue(ymd, hms);
152 static LIGHTWEIGHT_FORCE_INLINE SQL_TIMESTAMP_STRUCT
constexpr ConvertToSqlValue(
153 std::chrono::year_month_day ymd, std::chrono::hh_mm_ss<duration_type> hms)
noexcept
157 return SQL_TIMESTAMP_STRUCT {
158 .year = (SQLSMALLINT) (
int) ymd.year(),
159 .month = (SQLUSMALLINT) (
unsigned) ymd.month(),
160 .day = (SQLUSMALLINT) (
unsigned) ymd.day(),
161 .hour = (SQLUSMALLINT) hms.hours().count(),
162 .minute = (SQLUSMALLINT) hms.minutes().count(),
163 .second = (SQLUSMALLINT) hms.seconds().count(),
164 .fraction = (SQLUINTEGER) (((std::chrono::duration_cast<std::chrono::nanoseconds>(hms.to_duration()).count() % 1'000'000'000llu) / 100) * 100)
169 static LIGHTWEIGHT_FORCE_INLINE native_type
constexpr ConvertToNative(SQL_TIMESTAMP_STRUCT
const& time)
noexcept
172 using namespace std::chrono;
173 auto const ymd = year_month_day { std::chrono::year { time.year } / std::chrono::month { time.month } / std::chrono::day { time.day } };
174 auto const hms = hh_mm_ss<duration_type> {
175 duration_cast<duration_type>(
177 + minutes { time.minute }
178 + seconds { time.second }
179 + nanoseconds { time.fraction }
182 return sys_days { ymd } + hms.to_duration();
187 [[nodiscard]]
constexpr LIGHTWEIGHT_FORCE_INLINE native_type
value() const noexcept
189 return ConvertToNative(sqlValue);
192 LIGHTWEIGHT_FORCE_INLINE
SqlDateTime& operator+=(duration_type duration)
noexcept
198 LIGHTWEIGHT_FORCE_INLINE
SqlDateTime& operator-=(duration_type duration)
noexcept
204 friend LIGHTWEIGHT_FORCE_INLINE
SqlDateTime operator+(
SqlDateTime dateTime, duration_type duration)
noexcept
206 auto tmp = dateTime.
value() + duration;
211 friend LIGHTWEIGHT_FORCE_INLINE
SqlDateTime operator-(
SqlDateTime dateTime, duration_type duration)
noexcept
216 SQL_TIMESTAMP_STRUCT sqlValue {};
220struct std::formatter<
SqlDateTime>: std::formatter<std::string>
222 LIGHTWEIGHT_FORCE_INLINE
auto format(
SqlDateTime const& value, std::format_context& ctx)
const
223 -> std::format_context::iterator
229 auto const milliseconds = value.sqlValue.fraction / 1'000'000;
230 return std::formatter<std::string>::format(std::format(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:03}",
232 value.sqlValue.month,
235 value.sqlValue.minute,
236 value.sqlValue.second,
245 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN GetColumn(SQLHSTMT stmt,
247 SqlDateTime::native_type* result,
251 SQL_TIMESTAMP_STRUCT sqlValue {};
252 auto const rc = SQLGetData(stmt, column, SQL_C_TYPE_TIMESTAMP, &sqlValue,
sizeof(sqlValue), indicator);
253 if (SQL_SUCCEEDED(rc))
254 *result = SqlDateTime::ConvertToNative(sqlValue);
262 static constexpr auto ColumnType = SqlColumnTypeDefinitions::DateTime {};
264 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN InputParameter(SQLHSTMT stmt,
269#if defined(_WIN32) || defined(_WIN64)
272 using namespace std::string_view_literals;
273 if (cb.ServerType() == SqlServerType::MICROSOFT_SQL && cb.DriverName() ==
"SQLSRV32.DLL"sv)
277 SQLSMALLINT sqlType { SQL_TYPE_TIMESTAMP };
278 SQLULEN paramSize { 23 };
279 SQLSMALLINT decimalDigits { 3 };
280 SQLSMALLINT nullable {};
282 auto const sqlDescribeParamResult =
283 SQLDescribeParam(stmt, column, &hints.sqlType, &hints.paramSize, &hints.decimalDigits, &hints.nullable);
284 if (SQL_SUCCEEDED(sqlDescribeParamResult))
286 return SQLBindParameter(stmt,
293 (SQLPOINTER) &value.sqlValue,
300 return SQLBindParameter(stmt,
307 (SQLPOINTER) &value.sqlValue,
312 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN OutputColumn(
316 *indicator =
sizeof(result->sqlValue);
317 return SQLBindCol(stmt, column, SQL_C_TYPE_TIMESTAMP, &result->sqlValue, 0, indicator);
320 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN GetColumn(SQLHSTMT stmt,
326 return SQLGetData(stmt, column, SQL_C_TYPE_TIMESTAMP, &result->sqlValue,
sizeof(result->sqlValue), indicator);
329 static LIGHTWEIGHT_FORCE_INLINE std::string Inspect(
SqlDateTime const& value)
noexcept
331 return std::format(
"{}", value);
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::month month() const noexcept
Returns the month of this date-time object.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::minutes minute() const noexcept
Returns the minute of this date-time object.
LIGHTWEIGHT_FORCE_INLINE constexpr SqlDateTime(std::chrono::system_clock::time_point value) noexcept
Constructs a date and time from a time point.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::day day() const noexcept
Returns the day of this date-time object.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::nanoseconds nanosecond() const noexcept
Returns the nanosecond of this date-time object.
LIGHTWEIGHT_FORCE_INLINE constexpr SqlDateTime(std::chrono::year year, std::chrono::month month, std::chrono::day day, std::chrono::hours hour, std::chrono::minutes minute, std::chrono::seconds second, std::chrono::nanoseconds nanosecond=std::chrono::nanoseconds(0)) noexcept
Constructs a date and time from individual components.
constexpr LIGHTWEIGHT_FORCE_INLINE native_type value() const noexcept
Returns the current date and time.
LIGHTWEIGHT_FORCE_INLINE constexpr SqlDateTime(std::chrono::year_month_day ymd, std::chrono::hh_mm_ss< duration_type > time) noexcept
Constructs a date and time from individual components.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::year year() const noexcept
Returns the year of this date-time object.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::hours hour() const noexcept
Returns the hour of this date-time object.
constexpr LIGHTWEIGHT_FORCE_INLINE std::chrono::seconds second() const noexcept
Returns the second of this date-time object.
static LIGHTWEIGHT_FORCE_INLINE SqlDateTime Now() noexcept
Returns the current date and time.