in language-extensions/R/src/RTypeUtils.cpp [266:347]
RVectorType RTypeUtils::CreateDateTimeVector(
SQLULEN rowsNumber,
SQLPOINTER data,
SQLINTEGER *strLen_or_Ind,
SQLSMALLINT nullable)
{
LOG("RTypeUtils::CreateDateTimeVector");
// Note: Always preallocate the Rcpp vector with the size instead of using
// push_back since Rcpp push_back involves copying to create a new vector in R environment.
//
RVectorType vectorInR(rowsNumber);
// Get the time zone if any that R is set to and store it in a temporary variable.
//
string previousTimeZoneInR = "";
try
{
previousTimeZoneInR = Utilities::GetTimeZoneInR();
// Interpret the value sent by Exthost in UTC irrespective of what time zone R had been set to.
//
Utilities::SetTimeZoneInR("UTC");
bool isNullable = nullable == SQL_NULLABLE;
for (SQLULEN index = 0; index < rowsNumber; ++index)
{
if (isNullable &&
strLen_or_Ind != nullptr &&
strLen_or_Ind[index] == SQL_NULL_DATA)
{
// It is NULL (NA) only in this case.
//
vectorInR[index] = DateTimeTypeInR(R_NaReal);
}
else
{
// In all other scenarios, it is not NULL (NA).
//
SQLType value = static_cast<SQLType *>(data)[index];
// Rcpp::Date accepts date in "YYYY-mm-dd" and
// Rcpp::Datetime accepts datetime in "YYYY-mm-dd HH:MM:SS.MICROSEC"
// string formats so generate the date time string.
//
string dateTimeInStringFormat =
to_string(value.year) + "-" +
to_string(value.month) + "-" +
to_string(value.day);
if constexpr (is_same_v<DateTimeTypeInR, Rcpp::Datetime>)
{
// "fraction" is stored in nanoseconds, we need to know the digits after the decimal point.
//
string secondsAfterDecimalPoint
= Utilities::GetSecondsAfterDecimalPointFromNanoSeconds(value.fraction);
dateTimeInStringFormat =
dateTimeInStringFormat + " " +
to_string(value.hour) + ":" +
to_string(value.minute) + ":" +
to_string(value.second) + "." +
secondsAfterDecimalPoint;
}
vectorInR[index] = DateTimeTypeInR(dateTimeInStringFormat);
}
}
}
catch (...)
{
Utilities::SetTimeZoneInR(previousTimeZoneInR);
throw runtime_error("Unable to set UTC time zone and create date(time) vector");
}
Utilities::SetTimeZoneInR(previousTimeZoneInR);
return vectorInR;
}