RVectorType RTypeUtils::CreateDateTimeVector()

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;
}