25#ifndef FBCPP_CALENDAR_CONVERTER_H 
   26#define FBCPP_CALENDAR_CONVERTER_H 
   48    class CalendarConverter final
 
   51        explicit CalendarConverter(Client& client, StatusWrapper* statusWrapper)
 
   53              statusWrapper{statusWrapper}
 
   58        OpaqueDate dateToOpaqueDate(
const Date& date)
 
   61                throwInvalidDateValue();
 
   63            const auto yearValue = 
static_cast<unsigned>(
static_cast<int>(date.year()));
 
   64            const auto monthValue = 
static_cast<unsigned>(date.month());
 
   65            const auto dayValue = 
static_cast<unsigned>(date.day());
 
   68                throwInvalidDateValue();
 
   70            return OpaqueDate{client.getUtil()->encodeDate(
static_cast<unsigned>(yearValue), monthValue, dayValue)};
 
   73        Date opaqueDateToDate(OpaqueDate date)
 
   79            client.getUtil()->decodeDate(date.value, &year, &month, &day);
 
   81            return Date{std::chrono::year{
static_cast<int>(year)}, std::chrono::month{month}, std::chrono::day{day}};
 
   84        Date stringToDate(std::string_view value)
 
   86            static const std::regex pattern(R
"(^\s*([0-9]{4})\s*-\s*([0-9]{2})\s*-\s*([0-9]{2})\s*$)"); 
   88            const std::string stringValue{value};
 
   91            if (!std::regex_match(stringValue, matches, pattern))
 
   92                throwConversionErrorFromString(std::string{value});
 
   94            const auto makeComponentView = [&](
const std::size_t index)
 
   96                return std::string_view{stringValue.data() + 
static_cast<std::size_t
>(matches.position(index)),
 
   97                    static_cast<std::size_t
>(matches.length(index))};
 
  100            const auto parseComponent = [&](
const std::size_t index)
 
  103                const auto component = makeComponentView(index);
 
  104                const auto [ptr, ec] =
 
  105                    std::from_chars(component.data(), component.data() + component.size(), result, 10);
 
  107                if (ec != std::errc{} || ptr != component.data() + component.size())
 
  108                    throwConversionErrorFromString(std::string{value});
 
  113            const int year = parseComponent(1);
 
  114            const unsigned month = 
static_cast<unsigned>(parseComponent(2));
 
  115            const unsigned day = 
static_cast<unsigned>(parseComponent(3));
 
  117            const Date date{std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day}};
 
  120                throwInvalidDateValue();
 
  125        OpaqueDate stringToOpaqueDate(std::string_view value)
 
  127            return dateToOpaqueDate(stringToDate(value));
 
  130        std::string opaqueDateToString(OpaqueDate date)
 
  132            return std::format(
"{:%Y-%m-%d}", std::chrono::local_days{opaqueDateToDate(date)});
 
  135        OpaqueTime timeToOpaqueTime(
const Time& time)
 
  137            const auto hours = 
static_cast<unsigned>(time.hours().count());
 
  138            const auto minutes = 
static_cast<unsigned>(time.minutes().count());
 
  139            const auto seconds = 
static_cast<unsigned>(time.seconds().count());
 
  140            const auto subseconds = 
static_cast<unsigned>(time.subseconds().count() / 100);
 
  142            OpaqueTime opaqueTime;
 
  143            opaqueTime.value = client.getUtil()->encodeTime(hours, minutes, seconds, subseconds);
 
  148        Time opaqueTimeToTime(OpaqueTime time)
 
  155            const auto util = client.getUtil();
 
  156            util->decodeTime(time.value, &hours, &minutes, &seconds, &subseconds);
 
  158            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  159                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(subseconds) * 100};
 
  161            return Time{timeOfDay};
 
  164        Time stringToTime(std::string_view value)
 
  166            static const std::regex pattern(
 
  167                R
"(^\s*([0-9]{2})\s*:\s*([0-9]{2})\s*:\s*([0-9]{2})(?:\s*\.\s*([0-9]{1,4}))?\s*$)"); 
  169            const std::string stringValue{value};
 
  172            if (!std::regex_match(stringValue, matches, pattern))
 
  173                throwConversionErrorFromString(std::string{value});
 
  175            const auto makeComponentView = [&](
const std::size_t index)
 
  177                return std::string_view{stringValue.data() + 
static_cast<std::size_t
>(matches.position(index)),
 
  178                    static_cast<std::size_t
>(matches.length(index))};
 
  181            const auto parseComponent = [&](
const std::size_t index)
 
  184                const auto component = makeComponentView(index);
 
  185                const auto [ptr, ec] =
 
  186                    std::from_chars(component.data(), component.data() + component.size(), result, 10);
 
  188                if (ec != std::errc{} || ptr != component.data() + component.size())
 
  189                    throwConversionErrorFromString(std::string{value});
 
  194            const auto hours = parseComponent(1);
 
  195            const auto minutes = parseComponent(2);
 
  196            const auto seconds = parseComponent(3);
 
  198            unsigned fractions = 0;
 
  199            if (matches[4].matched && matches.length(4) > 0)
 
  201                const auto fractionComponent = makeComponentView(4);
 
  202                const auto [ptr, ec] = std::from_chars(
 
  203                    fractionComponent.data(), fractionComponent.data() + fractionComponent.size(), fractions, 10);
 
  205                if (ec != std::errc{} || ptr != fractionComponent.data() + fractionComponent.size())
 
  206                    throwConversionErrorFromString(std::string{value});
 
  208                for (
auto remaining = 4 - 
static_cast<int>(fractionComponent.size()); remaining > 0; --remaining)
 
  212            if (hours >= 24 || minutes >= 60 || seconds >= 60)
 
  213                throwInvalidTimeValue();
 
  215            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  216                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(fractions) * 100};
 
  218            if (timeOfDay >= std::chrono::hours{24})
 
  219                throwInvalidTimeValue();
 
  221            return Time{std::chrono::duration_cast<std::chrono::microseconds>(timeOfDay)};
 
  224        OpaqueTime stringToOpaqueTime(std::string_view value)
 
  226            return timeToOpaqueTime(stringToTime(value));
 
  229        std::string opaqueTimeToString(OpaqueTime time)
 
  231            const auto converted = opaqueTimeToTime(time);
 
  232            const auto subseconds = 
static_cast<unsigned>(converted.subseconds().count() / 100);
 
  234            return std::format(
"{:02}:{:02}:{:02}.{:04}", 
static_cast<unsigned>(converted.hours().count()),
 
  235                static_cast<unsigned>(converted.minutes().count()), 
static_cast<unsigned>(converted.seconds().count()),
 
  239        OpaqueTimeTz timeTzToOpaqueTimeTz(
const TimeTz& timeTz)
 
  241            const auto duration = timeTz.utcTime.to_duration();
 
  243            if (duration.count() < 0)
 
  244                throwInvalidTimeValue();
 
  246            const auto dayDuration = std::chrono::hours{24};
 
  247            if (duration >= dayDuration)
 
  248                throwInvalidTimeValue();
 
  250            if (duration.count() % 100 != 0)
 
  251                throwInvalidTimeValue();
 
  253            OpaqueTimeTz opaque{};
 
  255            client.getUtil()->encodeTimeTz(statusWrapper, &opaque.value, 0u, 0u, 0u, 0u, timeTz.zone.c_str());
 
  257            opaque.value.utc_time = 
static_cast<ISC_TIME
>(duration.count() / 100);
 
  262        TimeTz opaqueTimeTzToTimeTz(
const OpaqueTimeTz& opaqueTime, std::string* decodedTimeZoneName = 
nullptr)
 
  264            const auto ticks = 
static_cast<std::int64_t
>(opaqueTime.value.utc_time) * 100;
 
  270            std::array<char, 128> timeZoneBuffer;
 
  272            client.getUtil()->decodeTimeTz(statusWrapper, &opaqueTime.value, &hours, &minutes, &seconds, &fractions,
 
  273                static_cast<unsigned>(timeZoneBuffer.size()), timeZoneBuffer.data());
 
  276            timeTz.utcTime = 
Time{std::chrono::microseconds{ticks}};
 
  277            timeTz.zone = timeZoneBuffer.data();
 
  279            if (decodedTimeZoneName)
 
  280                *decodedTimeZoneName = timeTz.zone;
 
  285        OpaqueTimeTz stringToOpaqueTimeTz(std::string_view value)
 
  287            return timeTzToOpaqueTimeTz(stringToTimeTz(value));
 
  290        std::string opaqueTimeTzToString(
const OpaqueTimeTz& time)
 
  296            std::array<char, 128> timeZoneBuffer;
 
  298            client.getUtil()->decodeTimeTz(statusWrapper, &time.value, &hours, &minutes, &seconds, &fractions,
 
  299                static_cast<unsigned>(timeZoneBuffer.size()), timeZoneBuffer.data());
 
  301            return std::format(
"{:02}:{:02}:{:02}.{:04} {}", hours, minutes, seconds, fractions, timeZoneBuffer.data());
 
  304        TimeTz stringToTimeTz(std::string_view value)
 
  306            static const std::regex pattern(
 
  307                R
"(^\s*([0-9]{2})\s*:\s*([0-9]{2})\s*:\s*([0-9]{2})(?:\s*\.\s*([0-9]{1,4}))?\s+([^\s]+)\s*$)"); 
  309            const std::string stringValue{value};
 
  312            if (!std::regex_match(stringValue, matches, pattern))
 
  313                throwConversionErrorFromString(std::string{value});
 
  315            const auto makeComponentView = [&](
const std::size_t index)
 
  317                return std::string_view{stringValue.data() + 
static_cast<std::size_t
>(matches.position(index)),
 
  318                    static_cast<std::size_t
>(matches.length(index))};
 
  321            const auto parseComponent = [&](
const std::size_t index)
 
  324                const auto component = makeComponentView(index);
 
  325                const auto [ptr, ec] =
 
  326                    std::from_chars(component.data(), component.data() + component.size(), result, 10);
 
  328                if (ec != std::errc{} || ptr != component.data() + component.size())
 
  329                    throwConversionErrorFromString(std::string{value});
 
  334            const auto hours = parseComponent(1);
 
  335            const auto minutes = parseComponent(2);
 
  336            const auto seconds = parseComponent(3);
 
  338            unsigned fractions = 0;
 
  339            if (matches[4].matched && matches.length(4) > 0)
 
  341                const auto fractionComponent = makeComponentView(4);
 
  342                const auto [ptr, ec] = std::from_chars(
 
  343                    fractionComponent.data(), fractionComponent.data() + fractionComponent.size(), fractions, 10);
 
  345                if (ec != std::errc{} || ptr != fractionComponent.data() + fractionComponent.size())
 
  346                    throwConversionErrorFromString(std::string{value});
 
  348                for (
auto remaining = 4 - 
static_cast<int>(fractionComponent.size()); remaining > 0; --remaining)
 
  352            if (hours >= 24 || minutes >= 60 || seconds >= 60)
 
  353                throwInvalidTimeValue();
 
  355            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  356                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(fractions) * 100};
 
  358            if (timeOfDay >= std::chrono::hours{24})
 
  359                throwInvalidTimeValue();
 
  361            OpaqueTimeTz encoded;
 
  362            const std::string timeZoneString{makeComponentView(5)};
 
  363            client.getUtil()->encodeTimeTz(
 
  364                statusWrapper, &encoded.value, hours, minutes, seconds, fractions, timeZoneString.c_str());
 
  366            return opaqueTimeTzToTimeTz(encoded);
 
  370        OpaqueTimestamp timestampToOpaqueTimestamp(
const Timestamp& timestamp)
 
  372            const auto& date = timestamp.date;
 
  374                throwInvalidTimestampValue();
 
  376            const auto opaqueDate = dateToOpaqueDate(date);
 
  378            const auto timeOfDay = timestamp.time.to_duration();
 
  379            if (timeOfDay.count() < 0 || timeOfDay >= std::chrono::hours{24})
 
  380                throwInvalidTimestampValue();
 
  382            if (timestamp.time.is_negative())
 
  383                throwInvalidTimestampValue();
 
  385            const auto subseconds = timestamp.time.subseconds().count();
 
  386            if (subseconds % 100 != 0)
 
  387                throwInvalidTimestampValue();
 
  389            OpaqueTimestamp opaqueTimestamp;
 
  390            opaqueTimestamp.value.timestamp_date = opaqueDate.value;
 
  391            opaqueTimestamp.value.timestamp_time =
 
  392                client.getUtil()->encodeTime(
static_cast<unsigned>(timestamp.time.hours().count()),
 
  393                    static_cast<unsigned>(timestamp.time.minutes().count()),
 
  394                    static_cast<unsigned>(timestamp.time.seconds().count()), 
static_cast<unsigned>(subseconds / 100));
 
  396            return opaqueTimestamp;
 
  399        Timestamp opaqueTimestampToTimestamp(OpaqueTimestamp timestamp)
 
  409            const auto util = client.getUtil();
 
  410            util->decodeDate(timestamp.value.timestamp_date, &year, &month, &day);
 
  411            util->decodeTime(timestamp.value.timestamp_time, &hours, &minutes, &seconds, &subseconds);
 
  413            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  414                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(subseconds) * 100};
 
  417                std::chrono::year{
static_cast<int>(year)}, std::chrono::month{month}, std::chrono::day{day}};
 
  420                throwInvalidTimestampValue();
 
  422            return Timestamp{date, 
Time{timeOfDay}};
 
  425        Timestamp stringToTimestamp(std::string_view value)
 
  427            static const std::regex pattern(
 
  428                R
"(^\s*([0-9]{4})\s*-\s*([0-9]{2})\s*-\s*([0-9]{2})\s+([0-9]{2})\s*:\s*([0-9]{2})\s*:\s*([0-9]{2})(?:\s*\.\s*([0-9]{1,4}))?\s*$)"); 
  430            const std::string stringValue{value};
 
  433            if (!std::regex_match(stringValue, matches, pattern))
 
  434                throwConversionErrorFromString(std::string{value});
 
  436            const auto makeComponentView = [&](
const std::size_t index)
 
  438                return std::string_view{stringValue.data() + 
static_cast<std::size_t
>(matches.position(index)),
 
  439                    static_cast<std::size_t
>(matches.length(index))};
 
  442            const auto parseComponent = [&](
const std::size_t index)
 
  445                const auto component = makeComponentView(index);
 
  446                const auto [ptr, ec] =
 
  447                    std::from_chars(component.data(), component.data() + component.size(), result, 10);
 
  449                if (ec != std::errc{} || ptr != component.data() + component.size())
 
  450                    throwConversionErrorFromString(std::string{value});
 
  455            const int year = 
static_cast<int>(parseComponent(1));
 
  456            const unsigned month = parseComponent(2);
 
  457            const unsigned day = parseComponent(3);
 
  458            const auto hours = parseComponent(4);
 
  459            const auto minutes = parseComponent(5);
 
  460            const auto seconds = parseComponent(6);
 
  462            unsigned fractions = 0;
 
  463            if (matches[7].matched && matches.length(7) > 0)
 
  465                const auto fractionComponent = makeComponentView(7);
 
  466                const auto [ptr, ec] = std::from_chars(
 
  467                    fractionComponent.data(), fractionComponent.data() + fractionComponent.size(), fractions, 10);
 
  469                if (ec != std::errc{} || ptr != fractionComponent.data() + fractionComponent.size())
 
  470                    throwConversionErrorFromString(std::string{value});
 
  472                for (
auto remaining = 4 - 
static_cast<int>(fractionComponent.size()); remaining > 0; --remaining)
 
  476            const Date date{std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day}};
 
  479                throwInvalidTimestampValue();
 
  481            if (hours >= 24 || minutes >= 60 || seconds >= 60)
 
  482                throwInvalidTimestampValue();
 
  484            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  485                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(fractions) * 100};
 
  487            if (timeOfDay >= std::chrono::hours{24})
 
  488                throwInvalidTimestampValue();
 
  490            return Timestamp{date, 
Time{timeOfDay}};
 
  493        OpaqueTimestamp stringToOpaqueTimestamp(std::string_view value)
 
  495            return timestampToOpaqueTimestamp(stringToTimestamp(value));
 
  498        std::string opaqueTimestampToString(OpaqueTimestamp timestamp)
 
  500            const auto converted = opaqueTimestampToTimestamp(timestamp);
 
  501            const auto subseconds = 
static_cast<unsigned>(converted.time.subseconds().count() / 100);
 
  503            const auto dateString = std::format(
"{:%Y-%m-%d}", std::chrono::local_days{converted.date});
 
  504            const auto timeString =
 
  505                std::format(
"{:02}:{:02}:{:02}.{:04}", 
static_cast<unsigned>(converted.time.hours().count()),
 
  506                    static_cast<unsigned>(converted.time.minutes().count()),
 
  507                    static_cast<unsigned>(converted.time.seconds().count()), subseconds);
 
  509            return std::format(
"{} {}", dateString, timeString);
 
  512        OpaqueTimestampTz timestampTzToOpaqueTimestampTz(
const TimestampTz& timestampTz)
 
  514            OpaqueTimestampTz opaque;
 
  516            client.getUtil()->encodeTimeStampTz(
 
  517                statusWrapper, &opaque.value, 1u, 1u, 1u, 0u, 0u, 0u, 0u, timestampTz.zone.c_str());
 
  519            const auto utcOpaque = timestampToOpaqueTimestamp(timestampTz.utcTimestamp);
 
  520            opaque.value.utc_timestamp = utcOpaque.value;
 
  525        TimestampTz opaqueTimestampTzToTimestampTz(
 
  526            const OpaqueTimestampTz& opaqueTimestamp, std::string* decodedTimeZoneName = 
nullptr)
 
  529                (
static_cast<std::int64_t
>(opaqueTimestamp.value.utc_timestamp.timestamp_date) * TICKS_PER_DAY +
 
  530                    static_cast<std::int64_t
>(opaqueTimestamp.value.utc_timestamp.timestamp_time)) *
 
  540            std::array<char, 128> timeZoneBuffer;
 
  542            client.getUtil()->decodeTimeStampTz(statusWrapper, &opaqueTimestamp.value, &year, &month, &day, &hours,
 
  543                &minutes, &seconds, &subseconds, 
static_cast<unsigned>(timeZoneBuffer.size()), timeZoneBuffer.data());
 
  545            TimestampTz timestampTz;
 
  546            const auto utcLocalTime = BASE_EPOCH + std::chrono::microseconds{ticks};
 
  548            timestampTz.zone = timeZoneBuffer.data();
 
  550            if (decodedTimeZoneName)
 
  551                *decodedTimeZoneName = timestampTz.zone;
 
  556        OpaqueTimestampTz stringToOpaqueTimestampTz(std::string_view value)
 
  558            return timestampTzToOpaqueTimestampTz(stringToTimestampTz(value));
 
  561        std::string opaqueTimestampTzToString(
const OpaqueTimestampTz& timestamp)
 
  570            std::array<char, 128> timeZoneBuffer;
 
  572            client.getUtil()->decodeTimeStampTz(statusWrapper, ×tamp.value, &year, &month, &day, &hours, &minutes,
 
  573                &seconds, &subseconds, 
static_cast<unsigned>(timeZoneBuffer.size()), timeZoneBuffer.data());
 
  575            return std::format(
"{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:04} {}", year, month, day, hours, minutes,
 
  576                seconds, subseconds, timeZoneBuffer.data());
 
  579        TimestampTz stringToTimestampTz(std::string_view value)
 
  581            static const std::regex pattern(
 
  582                R
"(^\s*([0-9]{4})\s*-\s*([0-9]{2})\s*-\s*([0-9]{2})\s+([0-9]{2})\s*:\s*([0-9]{2})\s*:\s*([0-9]{2})(?:\s*\.\s*([0-9]{1,4}))?\s+([^\s]+)\s*$)"); 
  584            const std::string stringValue{value};
 
  587            if (!std::regex_match(stringValue, matches, pattern))
 
  588                throwConversionErrorFromString(std::string{value});
 
  590            const auto makeComponentView = [&](
const std::size_t index)
 
  592                return std::string_view{stringValue.data() + 
static_cast<std::size_t
>(matches.position(index)),
 
  593                    static_cast<std::size_t
>(matches.length(index))};
 
  596            const auto parseComponent = [&](
const std::size_t index)
 
  599                const auto component = makeComponentView(index);
 
  600                const auto [ptr, ec] =
 
  601                    std::from_chars(component.data(), component.data() + component.size(), result, 10);
 
  603                if (ec != std::errc{} || ptr != component.data() + component.size())
 
  604                    throwConversionErrorFromString(std::string{value});
 
  609            const int year = 
static_cast<int>(parseComponent(1));
 
  610            const unsigned month = parseComponent(2);
 
  611            const unsigned day = parseComponent(3);
 
  612            const auto hours = parseComponent(4);
 
  613            const auto minutes = parseComponent(5);
 
  614            const auto seconds = parseComponent(6);
 
  616            unsigned fractions = 0;
 
  617            if (matches[7].matched && matches.length(7) > 0)
 
  619                const auto fractionComponent = makeComponentView(7);
 
  620                const auto [ptr, ec] = std::from_chars(
 
  621                    fractionComponent.data(), fractionComponent.data() + fractionComponent.size(), fractions, 10);
 
  623                if (ec != std::errc{} || ptr != fractionComponent.data() + fractionComponent.size())
 
  624                    throwConversionErrorFromString(std::string{value});
 
  626                for (
auto remaining = 4 - 
static_cast<int>(fractionComponent.size()); remaining > 0; --remaining)
 
  630            const Date date{std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day}};
 
  633                throwInvalidTimestampValue();
 
  635            if (hours >= 24 || minutes >= 60 || seconds >= 60)
 
  636                throwInvalidTimestampValue();
 
  638            const auto timeOfDay = std::chrono::hours{hours} + std::chrono::minutes{minutes} +
 
  639                std::chrono::seconds{seconds} + std::chrono::microseconds{
static_cast<std::int64_t
>(fractions) * 100};
 
  641            if (timeOfDay >= std::chrono::hours{24})
 
  642                throwInvalidTimestampValue();
 
  644            const Timestamp localTimestamp{date, 
Time{timeOfDay}};
 
  646            const auto monthValue = 
static_cast<unsigned>(date.month());
 
  647            const auto dayValue = 
static_cast<unsigned>(date.day());
 
  649            OpaqueTimestampTz encoded;
 
  650            const std::string timeZoneString{makeComponentView(8)};
 
  651            client.getUtil()->encodeTimeStampTz(statusWrapper, &encoded.value,
 
  652                static_cast<unsigned>(
static_cast<int>(date.year())), monthValue, dayValue, hours, minutes, seconds,
 
  653                fractions, timeZoneString.c_str());
 
  655            const OpaqueTimestamp utcOpaque{encoded.value.utc_timestamp};
 
  656            const auto utcTimestamp = opaqueTimestampToTimestamp(utcOpaque);
 
  658            const auto offsetDuration = localTimestamp.toLocalTime() - utcTimestamp.toLocalTime();
 
  659            if (offsetDuration % std::chrono::minutes{1} != std::chrono::microseconds::zero())
 
  660                throwInvalidTimestampValue();
 
  662            std::string resolvedTimeZoneName;
 
  663            opaqueTimestampTzToTimestampTz(encoded, &resolvedTimeZoneName);
 
  665            return TimestampTz{utcTimestamp, resolvedTimeZoneName};
 
  669        [[noreturn]] 
void throwConversionErrorFromString(
const std::string& str)
 
  671            const std::intptr_t STATUS_CONVERSION_ERROR_FROM_STRING[] = {
 
  673                reinterpret_cast<std::intptr_t
>(str.c_str()),
 
  677            throw DatabaseException(client, STATUS_CONVERSION_ERROR_FROM_STRING);
 
  680        [[noreturn]] 
void throwInvalidDateValue()
 
  682            static constexpr std::intptr_t STATUS_INVALID_DATE_VALUE[] = {
 
  683                isc_invalid_date_val,
 
  687            throw DatabaseException(client, STATUS_INVALID_DATE_VALUE);
 
  690        [[noreturn]] 
void throwInvalidTimeValue()
 
  692            static constexpr std::intptr_t STATUS_INVALID_TIME_VALUE[] = {
 
  693                isc_invalid_time_val,
 
  697            throw DatabaseException(client, STATUS_INVALID_TIME_VALUE);
 
  700        [[noreturn]] 
void throwInvalidTimestampValue()
 
  702            static constexpr std::intptr_t STATUS_INVALID_TIMESTAMP_VALUE[] = {
 
  703                isc_invalid_timestamp_val,
 
  707            throw DatabaseException(client, STATUS_INVALID_TIMESTAMP_VALUE);
 
  711        static constexpr auto TICKS_PER_DAY = std::int64_t{24} * 60 * 60 * 10000;
 
  712        static constexpr auto BASE_EPOCH = std::chrono::local_days{
 
  713            std::chrono::year{1858} / std::chrono::November / 17,
 
  716        StatusWrapper* statusWrapper;
 
std::chrono::year_month_day Date
Firebird SQL calendar date.
std::chrono::hh_mm_ss< std::chrono::microseconds > Time
Firebird SQL time-of-day with microsecond resolution.
static Timestamp fromLocalTime(std::chrono::local_time< std::chrono::microseconds > value) noexcept
Builds a timestamp from a local-time value.