#pragma once #include #include #include #include #include #include namespace mssql { using namespace std; // Timestamps return dates in UTC timezone class TimestampColumn : public Column { public: TimestampColumn(int id, shared_ptr storage, int32_t tz_offset = 0) : Column(id) { auto & ins = (*storage); if (ins.timestampoffsetvec_ptr != nullptr) { auto & timeStruct = (*ins.timestampoffsetvec_ptr)[0]; milliseconds_from_timestamp_offset(timeStruct); } else if (ins.timestampvec_ptr != nullptr) { auto & timeStruct = (*ins.timestampvec_ptr)[0]; milliseconds_from_timestamp(timeStruct, tz_offset); } } TimestampColumn(int id, SQL_SS_TIMESTAMPOFFSET_STRUCT const& timeStruct) : Column(id) { milliseconds_from_timestamp_offset(timeStruct); } TimestampColumn(int id, TIMESTAMP_STRUCT const& timeStruct) : Column(id) { milliseconds_from_timestamp(timeStruct); } TimestampColumn(int id, double ms, int32_t delta, int32_t offset) : Column(id), milliseconds(ms), nanoseconds_delta(delta), offset_minutes(offset) { } TimestampColumn(int id, double ms) : TimestampColumn(id, ms, 0, 0) { } Local ToString() override { return AsString(milliseconds); } Local ToNative() override { nodeTypeFactory fact; auto dd = fact.new_date(milliseconds, nanoseconds_delta); return dd; } void to_timestamp_offset(SQL_SS_TIMESTAMPOFFSET_STRUCT& date) const { DateFromMilliseconds(date); } void to_timestamp_struct(SQL_TIMESTAMP_STRUCT & timestamp) const { SQL_SS_TIMESTAMPOFFSET_STRUCT ts; to_timestamp_offset(ts); timestamp.year = ts.year; timestamp.month = ts.month; timestamp.day = ts.day; timestamp.hour = ts.hour; timestamp.minute = ts.minute; timestamp.second = ts.second; timestamp.fraction = ts.fraction; } void ToTime2Struct(SQL_SS_TIME2_STRUCT & time2) const { SQL_SS_TIMESTAMPOFFSET_STRUCT ts; to_timestamp_offset(ts); time2.hour = ts.hour; time2.minute = ts.minute; time2.second = ts.second; time2.fraction = ts.fraction; } void ToDateStruct(SQL_DATE_STRUCT & dt) const { SQL_SS_TIMESTAMPOFFSET_STRUCT ts; to_timestamp_offset(ts); dt.year = ts.year; dt.month = ts.month; dt.day = ts.day; } static const int64_t NANOSECONDS_PER_MS = static_cast(1e6); // nanoseconds per millisecond private: double milliseconds; int32_t nanoseconds_delta; // just the fractional part of the time passed in, not since epoch time // return the number of days since Jan 1, 1970 double DaysSinceEpoch(SQLSMALLINT y, SQLUSMALLINT m, SQLUSMALLINT d) const; void milliseconds_from_timestamp(TIMESTAMP_STRUCT const & ts, SQLSMALLINT tz_offset = 0); // derived from ECMA 262 15.9 void milliseconds_from_timestamp_offset(SQL_SS_TIMESTAMPOFFSET_STRUCT const& time_struct); // return the year from the epoch time. The remainder is returned in the day parameter static int64_t year_from_day(int64_t& day); // calculate the individual components of a date from the total milliseconds // since Jan 1, 1970 void DateFromMilliseconds(SQL_SS_TIMESTAMPOFFSET_STRUCT& date) const; SQLSMALLINT offset_minutes; }; }