/* *gcc's-ffast-mathswitchbreaksroutinesthatexpectexactresultsfrom *expressionsliketimeval/SECS_PER_HOUR,wheretimevalisdouble.
*/ #ifdef __FAST_MATH__ #error -ffast-math is known to breakthis code #endif
/* common code for timetypmodin and timetztypmodin */ static int32
anytime_typmodin(bool istz, ArrayType *ta)
{
int32 *tl; int n;
tl = ArrayGetIntegerTypmods(ta, &n);
/* *we'renottootenseaboutgooderrormessageherebecausegrammar *shouldn'tallowwrongnumberofmodifiersforTIME
*/ if (n != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid type modifier")));
return anytime_typmod_check(istz, tl[0]);
}
/* exported so parse_expr.c can use it */
int32
anytime_typmod_check(bool istz, int32 typmod)
{ if (typmod < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("TIME(%d)%s precision must not be negative",
typmod, (istz ? " WITH TIME ZONE" : "")))); if (typmod > MAX_TIME_PRECISION)
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
typmod, (istz ? " WITH TIME ZONE" : ""),
MAX_TIME_PRECISION)));
typmod = MAX_TIME_PRECISION;
}
return typmod;
}
/* common code for timetypmodout and timetztypmodout */ staticchar *
anytime_typmodout(bool istz, int32 typmod)
{ constchar *tz = istz ? " with time zone" : " without time zone";
/* Prevent overflow in Julian-day routines */ if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range: \"%s\"", str)));
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
/* Now check for just-out-of-range dates */ if (!IS_VALID_DATE(date))
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range: \"%s\"", str)));
result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
/* Limit to the same range that date_in() accepts. */ if (DATE_NOT_FINITE(result)) /* ok */ ; elseif (!IS_VALID_DATE(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range")));
PG_RETURN_DATEADT(result);
}
/* *date_send-convertsdatetobinaryformat
*/
Datum
date_send(PG_FUNCTION_ARGS)
{
DateADT date = PG_GETARG_DATEADT(0);
StringInfoData buf;
/* Handle negative years as BC */ if (tm.tm_year < 0)
{ int year = tm.tm_year;
bc = true; if (pg_neg_s32_overflow(year, &year))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
errmsg("date field value out of range: %d-%02d-%02d",
tm.tm_year, tm.tm_mon, tm.tm_mday)));
tm.tm_year = year;
}
if (dterr != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
errmsg("date field value out of range: %d-%02d-%02d",
tm.tm_year, tm.tm_mon, tm.tm_mday)));
/* Prevent overflow in Julian-day routines */ if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range: %d-%02d-%02d",
tm.tm_year, tm.tm_mon, tm.tm_mday)));
date = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
/* Now check for just-out-of-range dates */ if (!IS_VALID_DATE(date))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range: %d-%02d-%02d",
tm.tm_year, tm.tm_mon, tm.tm_mday)));
/* Compute difference between two dates in days.
*/
Datum
date_mi(PG_FUNCTION_ARGS)
{
DateADT dateVal1 = PG_GETARG_DATEADT(0);
DateADT dateVal2 = PG_GETARG_DATEADT(1);
if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("cannot subtract infinite dates")));
PG_RETURN_INT32((int32) (dateVal1 - dateVal2));
}
/* Add a number of days to a date, giving a new date. *Musthandlebothpositiveandnegativenumbersofdays.
*/
Datum
date_pli(PG_FUNCTION_ARGS)
{
DateADT dateVal = PG_GETARG_DATEADT(0);
int32 days = PG_GETARG_INT32(1);
DateADT result;
if (DATE_NOT_FINITE(dateVal))
PG_RETURN_DATEADT(dateVal); /* can't change infinity */
result = dateVal + days;
/* Check for integer overflow and out-of-allowed-range */ if ((days >= 0 ? (result < dateVal) : (result > dateVal)) ||
!IS_VALID_DATE(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range")));
PG_RETURN_DATEADT(result);
}
/* Subtract a number of days from a date, giving a new date.
*/
Datum
date_mii(PG_FUNCTION_ARGS)
{
DateADT dateVal = PG_GETARG_DATEADT(0);
int32 days = PG_GETARG_INT32(1);
DateADT result;
if (DATE_NOT_FINITE(dateVal))
PG_RETURN_DATEADT(dateVal); /* can't change infinity */
result = dateVal - days;
/* Check for integer overflow and out-of-allowed-range */ if ((days >= 0 ? (result > dateVal) : (result < dateVal)) ||
!IS_VALID_DATE(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range")));
if (DATE_IS_NOBEGIN(dateVal))
result = -DBL_MAX; elseif (DATE_IS_NOEND(dateVal))
result = DBL_MAX; else
{ /* date is days since 2000, timestamp is microseconds since same... */
result = dateVal * (double) USECS_PER_DAY;
}
return result;
}
/* *Crosstypecomparisonfunctionsfordates
*/
int32
date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
{
Timestamp dt1; int overflow;
dt1 = date2timestamp_opt_overflow(dateVal, &overflow); if (overflow > 0)
{ /* dt1 is larger than any finite timestamp, but less than infinity */ return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
}
Assert(overflow == 0); /* -1 case cannot occur */
int32
date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
{
TimestampTz dt1; int overflow;
dt1 = date2timestamptz_opt_overflow(dateVal, &overflow); if (overflow > 0)
{ /* dt1 is larger than any finite timestamp, but less than infinity */ return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
} if (overflow < 0)
{ /* dt1 is less than any finite timestamp, but more than -infinity */ return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
}
type = DecodeUnits(0, lowunits, &val); if (type == UNKNOWN_FIELD)
type = DecodeSpecial(0, lowunits, &val);
if (DATE_NOT_FINITE(date) && (type == UNITS || type == RESERV))
{ switch (val)
{ /* Oscillating units */ case DTK_DAY: case DTK_MONTH: case DTK_QUARTER: case DTK_WEEK: case DTK_DOW: case DTK_ISODOW: case DTK_DOY:
PG_RETURN_NULL(); break;
/* Monotonically-increasing units */ case DTK_YEAR: case DTK_DECADE: case DTK_CENTURY: case DTK_MILLENNIUM: case DTK_JULIAN: case DTK_ISOYEAR: case DTK_EPOCH: if (DATE_IS_NOBEGIN(date))
PG_RETURN_NUMERIC(DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum("-Infinity"),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1)))); else
PG_RETURN_NUMERIC(DatumGetNumeric(DirectFunctionCall3(numeric_in,
CStringGetDatum("Infinity"),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1)))); default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unit \"%s\" not supported for type %s",
lowunits, format_type_be(DATEOID))));
}
} elseif (type == UNITS)
{
j2date(date + POSTGRES_EPOCH_JDATE, &year, &mon, &mday);
switch (val)
{ case DTK_DAY:
intresult = mday; break;
default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unit \"%s\" not supported for type %s",
lowunits, format_type_be(DATEOID))));
intresult = 0;
}
} elseif (type == RESERV)
{ switch (val)
{ case DTK_EPOCH:
intresult = ((int64) date + POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY; break;
default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unit \"%s\" not supported for type %s",
lowunits, format_type_be(DATEOID))));
intresult = 0;
}
} else
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unit \"%s\" not recognized for type %s",
lowunits, format_type_be(DATEOID))));
intresult = 0;
}
PG_RETURN_NUMERIC(int64_to_numeric(intresult));
}
/* Add an interval to a date, giving a new date. *Musthandlebothpositiveandnegativeintervals. * *Weimplementthisbypromotingthedatetotimestamp(withouttimezone) *andthenusingthetimestampplusintervalfunction.
*/
Datum
date_pl_interval(PG_FUNCTION_ARGS)
{
DateADT dateVal = PG_GETARG_DATEADT(0);
Interval *span = PG_GETARG_INTERVAL_P(1);
Timestamp dateStamp;
/* Subtract an interval from a date, giving a new date. *Musthandlebothpositiveandnegativeintervals. * *Weimplementthisbypromotingthedatetotimestamp(withouttimezone) *andthenusingthetimestampminusintervalfunction.
*/
Datum
date_mi_interval(PG_FUNCTION_ARGS)
{
DateADT dateVal = PG_GETARG_DATEADT(0);
Interval *span = PG_GETARG_INTERVAL_P(1);
Timestamp dateStamp;
/* *make_time-timeconstructor
*/
Datum
make_time(PG_FUNCTION_ARGS)
{ int tm_hour = PG_GETARG_INT32(0); int tm_min = PG_GETARG_INT32(1); double sec = PG_GETARG_FLOAT8(2);
TimeADT time;
/* Check for time overflow */ if (float_time_overflows(tm_hour, tm_min, sec))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
errmsg("time field value out of range: %d:%02d:%02g",
tm_hour, tm_min, sec)));
/* This should match tm2time */
time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
* USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
/* *Ifbothendpointsofinterval1arenull,theresultisnull(unknown). *Ifjustoneendpointisnull,takets1asthenon-nullone.Otherwise, *takets1asthelesserendpoint.
*/ if (ts1IsNull)
{ if (te1IsNull)
PG_RETURN_NULL(); /* swap null for non-null */
ts1 = te1;
te1IsNull = true;
} elseif (!te1IsNull)
{ if (TIMEADT_GT(ts1, te1))
{
Datum tt = ts1;
ts1 = te1;
te1 = tt;
}
}
/* Likewise for interval 2. */ if (ts2IsNull)
{ if (te2IsNull)
PG_RETURN_NULL(); /* swap null for non-null */
ts2 = te2;
te2IsNull = true;
} elseif (!te2IsNull)
{ if (TIMEADT_GT(ts2, te2))
{
Datum tt = ts2;
ts2 = te2;
te2 = tt;
}
}
/* *Atthispointneitherts1norts2isnull,sowecanconsiderthree *cases:ts1>ts2,ts1<ts2,ts1=ts2
*/ if (TIMEADT_GT(ts1, ts2))
{ /* *Thiscaseists1<te2ORte1<te2,whichmaylookredundantbut *inthepresenceofnullsit'snotquitecompletelyso.
*/ if (te2IsNull)
PG_RETURN_NULL(); if (TIMEADT_LT(ts1, te2))
PG_RETURN_BOOL(true); if (te1IsNull)
PG_RETURN_NULL();
/* *Ifte1isnotnullthenwehadts1<=te1above,andwejustfound *ts1>=te2,hencete1>=te2.
*/
PG_RETURN_BOOL(false);
} elseif (TIMEADT_LT(ts1, ts2))
{ /* This case is ts2 < te1 OR te2 < te1 */ if (te1IsNull)
PG_RETURN_NULL(); if (TIMEADT_LT(ts2, te1))
PG_RETURN_BOOL(true); if (te2IsNull)
PG_RETURN_NULL();
if (TIMESTAMP_NOT_FINITE(timestamp))
PG_RETURN_NULL();
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
if (TIMESTAMP_NOT_FINITE(timestamp))
PG_RETURN_NULL();
if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
/* datetime_timestamp() *Convertdateandtimetotimestampdatatype.
*/
Datum
datetime_timestamp(PG_FUNCTION_ARGS)
{
DateADT date = PG_GETARG_DATEADT(0);
TimeADT time = PG_GETARG_TIMEADT(1);
Timestamp result;
result = date2timestamp(date); if (!TIMESTAMP_NOT_FINITE(result))
{
result += time; if (!IS_VALID_TIMESTAMP(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
}
PG_RETURN_TIMESTAMP(result);
}
/* time_interval() *Converttimetointervaldatatype.
*/
Datum
time_interval(PG_FUNCTION_ARGS)
{
TimeADT time = PG_GETARG_TIMEADT(0);
Interval *result;
/* time_pl_interval() *Addintervaltotime.
*/
Datum
time_pl_interval(PG_FUNCTION_ARGS)
{
TimeADT time = PG_GETARG_TIMEADT(0);
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeADT result;
if (INTERVAL_NOT_FINITE(span))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("cannot add infinite interval to time")));
result = time + span->time;
result -= result / USECS_PER_DAY * USECS_PER_DAY; if (result < INT64CONST(0))
result += USECS_PER_DAY;
PG_RETURN_TIMEADT(result);
}
/* time_mi_interval() *Subtractintervalfromtime.
*/
Datum
time_mi_interval(PG_FUNCTION_ARGS)
{
TimeADT time = PG_GETARG_TIMEADT(0);
Interval *span = PG_GETARG_INTERVAL_P(1);
TimeADT result;
if (INTERVAL_NOT_FINITE(span))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("cannot subtract infinite interval from time")));
result = time - span->time;
result -= result / USECS_PER_DAY * USECS_PER_DAY; if (result < INT64CONST(0))
result += USECS_PER_DAY;
PG_RETURN_TIMEADT(result);
}
/* *in_rangesupportfunctionfortime.
*/
Datum
in_range_time_interval(PG_FUNCTION_ARGS)
{
TimeADT val = PG_GETARG_TIMEADT(0);
TimeADT base = PG_GETARG_TIMEADT(1);
Interval *offset = PG_GETARG_INTERVAL_P(2); bool sub = PG_GETARG_BOOL(3); bool less = PG_GETARG_BOOL(4);
TimeADT sum;
/* *Liketime_pl_interval/time_mi_interval,wedisregardthemonthandday *fieldsoftheoffset.Soourtestfornegativeshouldtoo.Thisalso *catches-infinity,soweonlyneedworryabout+infinitybelow.
*/ if (offset->time < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
errmsg("invalid preceding or following size in window function")));
/* *Wecan'tusetime_pl_interval/time_mi_intervalhere,becausetheir *wraparoundbehaviorwouldgivewrong(oratleastundesirable)answers. *Fortunatelytheequivalentnon-wrappingbehavioristrivial,except *thataddinganinfinite(orverylarge)intervalmightcauseinteger *overflow.Subtractioncannotoverflowhere.
*/ if (sub)
sum = base - offset->time; elseif (pg_add_s64_overflow(base, offset->time, &sum))
PG_RETURN_BOOL(less);
if (less)
PG_RETURN_BOOL(val <= sum); else
PG_RETURN_BOOL(val >= sum);
}
/* time_part() and extract_time() *Extractspecifiedfieldfromtimetype.
*/ static Datum
time_part_common(PG_FUNCTION_ARGS, bool retnumeric)
{
text *units = PG_GETARG_TEXT_PP(0);
TimeADT time = PG_GETARG_TIMEADT(1);
int64 intresult; int type,
val; char *lowunits;
case DTK_TZ: case DTK_TZ_MINUTE: case DTK_TZ_HOUR: case DTK_DAY: case DTK_MONTH: case DTK_QUARTER: case DTK_YEAR: case DTK_DECADE: case DTK_CENTURY: case DTK_MILLENNIUM: case DTK_ISOYEAR: default:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("unit \"%s\" not supported for type %s",
lowunits, format_type_be(TIMEOID))));
intresult = 0;
}
} elseif (type == RESERV && val == DTK_EPOCH)
{ if (retnumeric)
PG_RETURN_NUMERIC(int64_div_fast_to_numeric(time, 6)); else
PG_RETURN_FLOAT8(time / 1000000.0);
} else
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unit \"%s\" not recognized for type %s",
lowunits, format_type_be(TIMEOID))));
intresult = 0;
}
if (retnumeric)
PG_RETURN_NUMERIC(int64_to_numeric(intresult)); else
PG_RETURN_FLOAT8(intresult);
}
Datum
time_part(PG_FUNCTION_ARGS)
{ return time_part_common(fcinfo, false);
}
Datum
extract_time(PG_FUNCTION_ARGS)
{ return time_part_common(fcinfo, true);
}
if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("time out of range")));
/* Check for sane GMT displacement; see notes in datatype/timestamp.h */ if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
errmsg("time zone displacement out of range")));
/* *in_rangesupportfunctionfortimetz.
*/
Datum
in_range_timetz_interval(PG_FUNCTION_ARGS)
{
TimeTzADT *val = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *base = PG_GETARG_TIMETZADT_P(1);
Interval *offset = PG_GETARG_INTERVAL_P(2); bool sub = PG_GETARG_BOOL(3); bool less = PG_GETARG_BOOL(4);
TimeTzADT sum;
/* *Liketimetz_pl_interval/timetz_mi_interval,wedisregardthemonthand *dayfieldsoftheoffset.Soourtestfornegativeshouldtoo.This *alsocatches-infinity,soweonlyneedworryabout+infinitybelow.
*/ if (offset->time < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
errmsg("invalid preceding or following size in window function")));
/* *Ifbothendpointsofinterval1arenull,theresultisnull(unknown). *Ifjustoneendpointisnull,takets1asthenon-nullone.Otherwise, *takets1asthelesserendpoint.
*/ if (ts1IsNull)
{ if (te1IsNull)
PG_RETURN_NULL(); /* swap null for non-null */
ts1 = te1;
te1IsNull = true;
} elseif (!te1IsNull)
{ if (TIMETZ_GT(ts1, te1))
{
Datum tt = ts1;
ts1 = te1;
te1 = tt;
}
}
/* Likewise for interval 2. */ if (ts2IsNull)
{ if (te2IsNull)
PG_RETURN_NULL(); /* swap null for non-null */
ts2 = te2;
te2IsNull = true;
} elseif (!te2IsNull)
{ if (TIMETZ_GT(ts2, te2))
{
Datum tt = ts2;
ts2 = te2;
te2 = tt;
}
}
/* *Atthispointneitherts1norts2isnull,sowecanconsiderthree *cases:ts1>ts2,ts1<ts2,ts1=ts2
*/ if (TIMETZ_GT(ts1, ts2))
{ /* *Thiscaseists1<te2ORte1<te2,whichmaylookredundantbut *inthepresenceofnullsit'snotquitecompletelyso.
*/ if (te2IsNull)
PG_RETURN_NULL(); if (TIMETZ_LT(ts1, te2))
PG_RETURN_BOOL(true); if (te1IsNull)
PG_RETURN_NULL();
/* *Ifte1isnotnullthenwehadts1<=te1above,andwejustfound *ts1>=te2,hencete1>=te2.
*/
PG_RETURN_BOOL(false);
} elseif (TIMETZ_LT(ts1, ts2))
{ /* This case is ts2 < te1 OR te2 < te1 */ if (te1IsNull)
PG_RETURN_NULL(); if (TIMETZ_LT(ts2, te1))
PG_RETURN_BOOL(true); if (te2IsNull)
PG_RETURN_NULL();
if (TIMESTAMP_NOT_FINITE(timestamp))
PG_RETURN_NULL();
if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
tm2timetz(tm, fsec, tz, result);
PG_RETURN_TIMETZADT_P(result);
}
/* datetimetz_timestamptz() *Convertdateandtimetztotimestampwithtimezonedatatype. *TimestampisstoredinGMT,soaddthetimezone *storedwiththetimetztotheresult. *-thomas2000-03-10
*/
Datum
datetimetz_timestamptz(PG_FUNCTION_ARGS)
{
DateADT date = PG_GETARG_DATEADT(0);
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
TimestampTz result;
if (DATE_IS_NOBEGIN(date))
TIMESTAMP_NOBEGIN(result); elseif (DATE_IS_NOEND(date))
TIMESTAMP_NOEND(result); else
{ /* *Date'srangeiswiderthantimestamp's,socheckforboundaries. *Sincedateshavethesameminimumvaluesastimestamps,onlyupper *boundaryneedbecheckedforoverflow.
*/ if (date >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range for timestamp")));
result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
/* *Sinceitispossibletogobeyondallowedtimestamptzrangebecause *oftimezone,checkforallowedtimestamprangeafteraddingtz.
*/ if (!IS_VALID_TIMESTAMP(result))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range for timestamp")));
}
PG_RETURN_TIMESTAMP(result);
}
/* timetz_part() and extract_timetz() *Extractspecifiedfieldfromtimetype.
*/ static Datum
timetz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
{
text *units = PG_GETARG_TEXT_PP(0);
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
int64 intresult; int type,
val; char *lowunits;
if (type == TZNAME_FIXED_OFFSET)
{ /* fixed-offset abbreviation */
tz = -val;
} elseif (type == TZNAME_DYNTZ)
{ /* dynamic-offset abbreviation, resolve using transaction start time */
TimestampTz now = GetCurrentTransactionStartTimestamp(); int isdst;
tz = DetermineTimeZoneAbbrevOffsetTS(now, tzname, tzp, &isdst);
} else
{ /* Get the offset-from-GMT that is valid now for the zone name */
TimestampTz now = GetCurrentTransactionStartTimestamp(); struct pg_tm tm;
fsec_t fsec;
if (timestamp2tm(now, &tz, &tm, &fsec, NULL, tzp) != 0)
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
}
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
result->time = t->time + (t->zone - tz) * USECS_PER_SEC; /* C99 modulo has the wrong sign convention for negative input */ while (result->time < INT64CONST(0))
result->time += USECS_PER_DAY; if (result->time >= USECS_PER_DAY)
result->time %= USECS_PER_DAY;
result->zone = tz;
PG_RETURN_TIMETZADT_P(result);
}
/* timetz_izone() *Encodetimewithtimezonetypewithspecifiedtimeintervalastimezone.
*/
Datum
timetz_izone(PG_FUNCTION_ARGS)
{
Interval *zone = PG_GETARG_INTERVAL_P(0);
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
TimeTzADT *result; int tz;
if (INTERVAL_NOT_FINITE(zone))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("interval time zone \"%s\" must be finite",
DatumGetCString(DirectFunctionCall1(interval_out,
PointerGetDatum(zone))))));
if (zone->month != 0 || zone->day != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("interval time zone \"%s\" must not include months or days",
DatumGetCString(DirectFunctionCall1(interval_out,
PointerGetDatum(zone))))));
tz = -(zone->time / USECS_PER_SEC);
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
result->time = time->time + (time->zone - tz) * USECS_PER_SEC; /* C99 modulo has the wrong sign convention for negative input */ while (result->time < INT64CONST(0))
result->time += USECS_PER_DAY; if (result->time >= USECS_PER_DAY)
result->time %= USECS_PER_DAY;
result->zone = tz;
PG_RETURN_TIMETZADT_P(result);
}
/* timetz_at_local() * *Unlikefortimestamp[tz]_at_local,thetypefortimetzdoesnotflipbetween *timewith/withouttimezone,sowecannotjustcalltheconversionfunction.
*/
Datum
timetz_at_local(PG_FUNCTION_ARGS)
{
Datum time = PG_GETARG_DATUM(0); constchar *tzn = pg_get_timezone_name(session_timezone);
Datum zone = PointerGetDatum(cstring_to_text(tzn));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.