8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 02:03:04 +01:00

Fixed DATEDIFF.

This commit is contained in:
Adriano dos Santos Fernandes 2018-04-03 12:52:16 -03:00
parent 141f62611b
commit 3b5aa40b43
3 changed files with 61 additions and 19 deletions

View File

@ -292,6 +292,20 @@ ISC_TIMESTAMP TimeZoneUtil::timeStampTzToTimeStamp(const ISC_TIMESTAMP_TZ& timeS
return TimeStamp::encode_timestamp(&times, fractions);
}
// Converts a time from local to UTC.
void TimeZoneUtil::localTimeToUtc(ISC_TIME& time, Callbacks* cb)
{
//// TODO:
ISC_TIMESTAMP_TZ tempTimeStampTz;
tempTimeStampTz.timestamp_date = TimeStamp::getCurrentTimeStamp().value().timestamp_date;
tempTimeStampTz.timestamp_time = time;
tempTimeStampTz.timestamp_zone = cb->getSessionTimeZone();
localTimeStampToUtc(tempTimeStampTz);
time = tempTimeStampTz.timestamp_time;
}
// Converts a time from local to UTC.
void TimeZoneUtil::localTimeToUtc(ISC_TIME_TZ& timeTz)
{
@ -306,6 +320,20 @@ void TimeZoneUtil::localTimeToUtc(ISC_TIME_TZ& timeTz)
timeTz.time_time = tempTimeStampTz.timestamp_time;
}
// Converts a timestamp from its local datetime fields to UTC.
void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP& timeStamp, Callbacks* cb)
{
ISC_TIMESTAMP_TZ tempTimeStampTz;
tempTimeStampTz.timestamp_date = timeStamp.timestamp_date;
tempTimeStampTz.timestamp_time = timeStamp.timestamp_time;
tempTimeStampTz.timestamp_zone = cb->getSessionTimeZone();
localTimeStampToUtc(tempTimeStampTz);
timeStamp.timestamp_date = tempTimeStampTz.timestamp_date;
timeStamp.timestamp_time = tempTimeStampTz.timestamp_time;
}
// Converts a timestamp from its local datetime fields to UTC.
void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
{

View File

@ -28,6 +28,7 @@
#define COMMON_TIME_ZONE_UTIL_H
#include "../common/classes/fb_string.h"
#include "../common/cvt.h"
namespace Firebird {
@ -53,7 +54,10 @@ public:
static ISC_TIME timeTzToTime(const ISC_TIME_TZ& timeTz, USHORT toTimeZone);
static ISC_TIMESTAMP timeStampTzToTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, USHORT toTimeZone);
static void localTimeToUtc(ISC_TIME& time, Callbacks* cb);
static void localTimeToUtc(ISC_TIME_TZ& timeTz);
static void localTimeStampToUtc(ISC_TIMESTAMP& timeStamp, Callbacks* cb);
static void localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz);
static void decodeTime(const ISC_TIME_TZ& timeTz, struct tm* times, int* fractions = NULL);

View File

@ -538,8 +538,8 @@ void setParamsDateDiff(DataTypeUtilBase*, const SysFunction*, int argsCount, dsc
{
if (args[1]->isUnknown() && args[2]->isUnknown())
{
args[1]->makeTimestamp();
args[2]->makeTimestamp();
args[1]->makeTimestamp(); //// TODO:
args[2]->makeTimestamp(); //// TODO:
}
else if (args[1]->isUnknown())
*args[1] = *args[2];
@ -2128,7 +2128,6 @@ dsc* evlDateAdd(thread_db* tdbb, const SysFunction* function, const NestValueArr
}
//// FIXME:
dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueArray& args,
impure_value* impure)
{
@ -2153,17 +2152,25 @@ dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueAr
switch (value1Dsc->dsc_dtype)
{
case dtype_sql_time:
timestamp1.value().timestamp_time = *(GDS_TIME *) value1Dsc->dsc_address;
case dtype_sql_time_tz:
timestamp1.value().timestamp_time = *(GDS_TIME*) value1Dsc->dsc_address;
timestamp1.value().timestamp_date = 0;
if (value1Dsc->dsc_dtype == dtype_sql_time && value2Dsc->isDateTimeTz())
TimeZoneUtil::localTimeToUtc(timestamp1.value().timestamp_time, &EngineCallbacks::instance);
break;
case dtype_sql_date:
timestamp1.value().timestamp_date = *(GDS_DATE *) value1Dsc->dsc_address;
timestamp1.value().timestamp_date = *(GDS_DATE*) value1Dsc->dsc_address;
timestamp1.value().timestamp_time = 0;
break;
case dtype_timestamp:
timestamp1.value() = *(GDS_TIMESTAMP *) value1Dsc->dsc_address;
case dtype_timestamp_tz:
timestamp1.value() = *(GDS_TIMESTAMP*) value1Dsc->dsc_address;
if (value1Dsc->dsc_dtype == dtype_timestamp && value2Dsc->isDateTimeTz())
TimeZoneUtil::localTimeStampToUtc(timestamp1.value(), &EngineCallbacks::instance);
break;
default:
@ -2178,17 +2185,25 @@ dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueAr
switch (value2Dsc->dsc_dtype)
{
case dtype_sql_time:
timestamp2.value().timestamp_time = *(GDS_TIME *) value2Dsc->dsc_address;
case dtype_sql_time_tz:
timestamp2.value().timestamp_time = *(GDS_TIME*) value2Dsc->dsc_address;
timestamp2.value().timestamp_date = 0;
if (value2Dsc->dsc_dtype == dtype_sql_time && value1Dsc->isDateTimeTz())
TimeZoneUtil::localTimeToUtc(timestamp2.value().timestamp_time, &EngineCallbacks::instance);
break;
case dtype_sql_date:
timestamp2.value().timestamp_date = *(GDS_DATE *) value2Dsc->dsc_address;
timestamp2.value().timestamp_date = *(GDS_DATE*) value2Dsc->dsc_address;
timestamp2.value().timestamp_time = 0;
break;
case dtype_timestamp:
timestamp2.value() = *(GDS_TIMESTAMP *) value2Dsc->dsc_address;
case dtype_timestamp_tz:
timestamp2.value() = *(GDS_TIMESTAMP*) value2Dsc->dsc_address;
if (value2Dsc->dsc_dtype == dtype_timestamp && value1Dsc->isDateTimeTz())
TimeZoneUtil::localTimeStampToUtc(timestamp2.value(), &EngineCallbacks::instance);
break;
default:
@ -2229,7 +2244,7 @@ dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueAr
case blr_extract_month:
case blr_extract_day:
case blr_extract_week:
if (value1Dsc->dsc_dtype == dtype_sql_time || value2Dsc->dsc_dtype == dtype_sql_time)
if (value1Dsc->isTime() || value2Dsc->isTime())
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_invalid_timediff) <<
@ -2242,22 +2257,17 @@ dsc* evlDateDiff(thread_db* tdbb, const SysFunction* function, const NestValueAr
case blr_extract_second:
case blr_extract_millisecond:
{
//if (value1Dsc->dsc_dtype == dtype_sql_date || value2Dsc->dsc_dtype == dtype_sql_date)
// status_exception::raise(Arg::Gds(isc_expression_eval_err));
// ASF: also throw error if one value is TIMESTAMP and the other is TIME
// CVC: Or if one value is DATE and the other is TIME.
const int type1 = value1Dsc->dsc_dtype;
const int type2 = value2Dsc->dsc_dtype;
if ((type1 == dtype_timestamp && type2 == dtype_sql_time) ||
(type1 == dtype_sql_time && type2 == dtype_timestamp))
if ((value1Dsc->isTimeStamp() && value2Dsc->isTime()) ||
(value1Dsc->isTime() && value2Dsc->isTimeStamp()))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_invalid_tstamptimediff) <<
Arg::Str(function->name));
}
if ((type1 == dtype_sql_date && type2 == dtype_sql_time) ||
(type1 == dtype_sql_time && type2 == dtype_sql_date))
if ((value1Dsc->dsc_dtype == dtype_sql_date && value2Dsc->isTime()) ||
(value1Dsc->isTime() && value2Dsc->dsc_dtype == dtype_sql_date))
{
status_exception::raise(Arg::Gds(isc_expression_eval_err) <<
Arg::Gds(isc_sysf_invalid_datetimediff) <<