📄 nabstime.c
字号:
/* timestamptz_abstime() * Convert timestamp with time zone to abstime. */Datumtimestamptz_abstime(PG_FUNCTION_ARGS){ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); AbsoluteTime result; fsec_t fsec; struct pg_tm tt, *tm = &tt; if (TIMESTAMP_IS_NOBEGIN(timestamp)) result = NOSTART_ABSTIME; else if (TIMESTAMP_IS_NOEND(timestamp)) result = NOEND_ABSTIME; else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) result = tm2abstime(tm, 0); else { ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); result = INVALID_ABSTIME; } PG_RETURN_ABSOLUTETIME(result);}/* abstime_timestamptz() * Convert abstime to timestamp with time zone. */Datumabstime_timestamptz(PG_FUNCTION_ARGS){ AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0); TimestampTz result; struct pg_tm tt, *tm = &tt; int tz; char zone[MAXDATELEN + 1], *tzn = zone; switch (abstime) { case INVALID_ABSTIME: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert abstime \"invalid\" to timestamp"))); TIMESTAMP_NOBEGIN(result); break; case NOSTART_ABSTIME: TIMESTAMP_NOBEGIN(result); break; case NOEND_ABSTIME: TIMESTAMP_NOEND(result); break; default: abstime2tm(abstime, &tz, tm, &tzn); if (tm2timestamp(tm, 0, &tz, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); break; }; PG_RETURN_TIMESTAMP(result);}/***************************************************************************** * USER I/O ROUTINES * *****************************************************************************//* * reltimein - converts a reltime string in an internal format */Datumreltimein(PG_FUNCTION_ARGS){ char *str = PG_GETARG_CSTRING(0); RelativeTime result; struct pg_tm tt, *tm = &tt; fsec_t fsec; int dtype; int dterr; char *field[MAXDATEFIELDS]; int nf, ftype[MAXDATEFIELDS]; char workbuf[MAXDATELEN + 1]; dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field, ftype, MAXDATEFIELDS, &nf); if (dterr == 0) dterr = DecodeInterval(field, ftype, nf, &dtype, tm, &fsec); if (dterr != 0) { if (dterr == DTERR_FIELD_OVERFLOW) dterr = DTERR_INTERVAL_OVERFLOW; DateTimeParseError(dterr, str, "reltime"); } switch (dtype) { case DTK_DELTA: result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec; result += tm->tm_year * SECS_PER_YEAR + ((tm->tm_mon * DAYS_PER_MONTH) + tm->tm_mday) * SECS_PER_DAY; break; default: elog(ERROR, "unexpected dtype %d while parsing reltime \"%s\"", dtype, str); result = INVALID_RELTIME; break; } PG_RETURN_RELATIVETIME(result);}/* * reltimeout - converts the internal format to a reltime string */Datumreltimeout(PG_FUNCTION_ARGS){ RelativeTime time = PG_GETARG_RELATIVETIME(0); char *result; struct pg_tm tt, *tm = &tt; char buf[MAXDATELEN + 1]; reltime2tm(time, tm); EncodeInterval(tm, 0, DateStyle, buf); result = pstrdup(buf); PG_RETURN_CSTRING(result);}/* * reltimerecv - converts external binary format to reltime */Datumreltimerecv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_RELATIVETIME((RelativeTime) pq_getmsgint(buf, sizeof(RelativeTime)));}/* * reltimesend - converts reltime to binary format */Datumreltimesend(PG_FUNCTION_ARGS){ RelativeTime time = PG_GETARG_RELATIVETIME(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint(&buf, time, sizeof(time)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}static voidreltime2tm(RelativeTime time, struct pg_tm * tm){ double dtime = time; FMODULO(dtime, tm->tm_year, 31557600); FMODULO(dtime, tm->tm_mon, 2592000); FMODULO(dtime, tm->tm_mday, SECS_PER_DAY); FMODULO(dtime, tm->tm_hour, SECS_PER_HOUR); FMODULO(dtime, tm->tm_min, SECS_PER_MINUTE); FMODULO(dtime, tm->tm_sec, 1);}/* * tintervalin - converts an tinterval string to internal format */Datumtintervalin(PG_FUNCTION_ARGS){ char *tintervalstr = PG_GETARG_CSTRING(0); TimeInterval tinterval; AbsoluteTime i_start, i_end, t1, t2; parsetinterval(tintervalstr, &t1, &t2); tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData)); if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) tinterval->status = T_INTERVAL_INVAL; /* undefined */ else tinterval->status = T_INTERVAL_VALID; i_start = ABSTIMEMIN(t1, t2); i_end = ABSTIMEMAX(t1, t2); tinterval->data[0] = i_start; tinterval->data[1] = i_end; PG_RETURN_TIMEINTERVAL(tinterval);}/* * tintervalout - converts an internal tinterval format to a string */Datumtintervalout(PG_FUNCTION_ARGS){ TimeInterval tinterval = PG_GETARG_TIMEINTERVAL(0); char *i_str, *p; i_str = (char *) palloc(T_INTERVAL_LEN); /* ["..." "..."] */ strcpy(i_str, "[\""); if (tinterval->status == T_INTERVAL_INVAL) strcat(i_str, INVALID_INTERVAL_STR); else { p = DatumGetCString(DirectFunctionCall1(abstimeout, AbsoluteTimeGetDatum(tinterval->data[0]))); strcat(i_str, p); pfree(p); strcat(i_str, "\" \""); p = DatumGetCString(DirectFunctionCall1(abstimeout, AbsoluteTimeGetDatum(tinterval->data[1]))); strcat(i_str, p); pfree(p); } strcat(i_str, "\"]"); PG_RETURN_CSTRING(i_str);}/* * tintervalrecv - converts external binary format to tinterval */Datumtintervalrecv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TimeInterval tinterval; tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData)); tinterval->status = pq_getmsgint(buf, sizeof(tinterval->status)); if (!(tinterval->status == T_INTERVAL_INVAL || tinterval->status == T_INTERVAL_VALID)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid status in external \"tinterval\" value"))); tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0])); tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1])); PG_RETURN_TIMEINTERVAL(tinterval);}/* * tintervalsend - converts tinterval to binary format */Datumtintervalsend(PG_FUNCTION_ARGS){ TimeInterval tinterval = PG_GETARG_TIMEINTERVAL(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint(&buf, tinterval->status, sizeof(tinterval->status)); pq_sendint(&buf, tinterval->data[0], sizeof(tinterval->data[0])); pq_sendint(&buf, tinterval->data[1], sizeof(tinterval->data[1])); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************/Datuminterval_reltime(PG_FUNCTION_ARGS){ Interval *interval = PG_GETARG_INTERVAL_P(0); RelativeTime time; int year, month, day;#ifdef HAVE_INT64_TIMESTAMP int64 span;#else double span;#endif year = interval->month / MONTHS_PER_YEAR; month = interval->month % MONTHS_PER_YEAR; day = interval->day;#ifdef HAVE_INT64_TIMESTAMP span = ((INT64CONST(365250000) * year + INT64CONST(30000000) * month + INT64CONST(1000000) * day) * INT64CONST(86400)) + interval->time; span /= USECS_PER_SEC;#else span = (DAYS_PER_YEAR * year + (double) DAYS_PER_MONTH * month + day) * SECS_PER_DAY + interval->time;#endif if (span < INT_MIN || span > INT_MAX) time = INVALID_RELTIME; else time = span; PG_RETURN_RELATIVETIME(time);}Datumreltime_interval(PG_FUNCTION_ARGS){ RelativeTime reltime = PG_GETARG_RELATIVETIME(0); Interval *result; int year, month, day; result = (Interval *) palloc(sizeof(Interval)); switch (reltime) { case INVALID_RELTIME: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert reltime \"invalid\" to interval"))); result->time = 0; result->day = 0; result->month = 0; break; default:#ifdef HAVE_INT64_TIMESTAMP year = reltime / SECS_PER_YEAR; reltime -= year * SECS_PER_YEAR; month = reltime / (DAYS_PER_MONTH * SECS_PER_DAY); reltime -= month * (DAYS_PER_MONTH * SECS_PER_DAY); day = reltime / SECS_PER_DAY; reltime -= day * SECS_PER_DAY; result->time = (reltime * USECS_PER_SEC);#else TMODULO(reltime, year, SECS_PER_YEAR); TMODULO(reltime, month, DAYS_PER_MONTH * SECS_PER_DAY); TMODULO(reltime, day, SECS_PER_DAY); result->time = reltime;#endif result->month = MONTHS_PER_YEAR * year + month; result->day = day; break; } PG_RETURN_INTERVAL_P(result);}/* * mktinterval - creates a time interval with endpoints t1 and t2 */Datummktinterval(PG_FUNCTION_ARGS){ AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0); AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1); AbsoluteTime tstart = ABSTIMEMIN(t1, t2); AbsoluteTime tend = ABSTIMEMAX(t1, t2); TimeInterval tinterval; tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData)); if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME) tinterval->status = T_INTERVAL_INVAL; else { tinterval->status = T_INTERVAL_VALID; tinterval->data[0] = tstart; tinterval->data[1] = tend; } PG_RETURN_TIMEINTERVAL(tinterval);}/* * timepl, timemi and abstimemi use the formula * abstime + reltime = abstime * so abstime - reltime = abstime * and abstime - abstime = reltime *//* * timepl - returns the value of (abstime t1 + reltime t2) */Datumtimepl(PG_FUNCTION_ARGS){ AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0); RelativeTime t2 = PG_GETARG_RELATIVETIME(1); if (AbsoluteTimeIsReal(t1) && RelativeTimeIsValid(t2) && ((t2 > 0 && t1 < NOEND_ABSTIME - t2) || (t2 <= 0 && t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */ PG_RETURN_ABSOLUTETIME(t1 + t2); PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME);}/* * timemi - returns the value of (abstime t1 - reltime t2) */Datumtimemi(PG_FUNCTION_ARGS){ AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0); RelativeTime t2 = PG_GETARG_RELATIVETIME(1); if (AbsoluteTimeIsReal(t1) && RelativeTimeIsValid(t2) && ((t2 > 0 && t1 > NOSTART_ABSTIME + t2) || (t2 <= 0 && t1 < NOEND_ABSTIME + t2))) /* prevent overflow */ PG_RETURN_ABSOLUTETIME(t1 - t2); PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME);}/* * intinterval - returns true iff absolute date is in the tinterval */Datumintinterval(PG_FUNCTION_ARGS){ AbsoluteTime t = PG_GETARG_ABSOLUTETIME(0); TimeInterval tinterval = PG_GETARG_TIMEINTERVAL(1); if (tinterval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME) { if (DatumGetBool(DirectFunctionCall2(abstimege, AbsoluteTimeGetDatum(t), AbsoluteTimeGetDatum(tinterval->data[0]))) && DatumGetBool(DirectFunctionCall2(abstimele, AbsoluteTimeGetDatum(t), AbsoluteTimeGetDatum(tinterval->data[1])))) PG_RETURN_BOOL(true); } PG_RETURN_BOOL(false);}/* * tintervalrel - returns relative time corresponding to tinterval */Datumtintervalrel(PG_FUNCTION_ARGS){ TimeInterval tinterval = PG_GETARG_TIMEINTERVAL(0); AbsoluteTime t1 = tinterval->data[0]; AbsoluteTime t2 = tinterval->data[1]; if (tinterval->status != T_INTERVAL_VALID) PG_RETURN_RELATIVETIME(INVALID_RELTIME); if (AbsoluteTimeIsReal(t1) && AbsoluteTimeIsReal(t2)) PG_RETURN_RELATIVETIME(t2 - t1); PG_RETURN_RELATIVETIME(INVALID_RELTIME);}/* * timenow - returns time "now", internal format * * Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992 */Datumtimenow(PG_FUNCTION_ARGS){ time_t sec; if (time(&sec) < 0) PG_RETURN_ABSOLUTETIME(INVALID_ABSTIME); PG_RETURN_ABSOLUTETIME((AbsoluteTime) sec);}/* * reltime comparison routines */static intreltime_cmp_internal(RelativeTime a, RelativeTime b){ /* * We consider all INVALIDs to be equal and larger than any non-INVALID. * This is somewhat arbitrary; the important thing is to have a consistent * sort order. */ if (a == INVALID_RELTIME) { if (b == INVALID_RELTIME) return 0; /* INVALID = INVALID */ else return 1; /* INVALID > non-INVALID */ } if (b == INVALID_RELTIME) return -1; /* non-INVALID < INVALID */ if (a > b) return 1; else if (a == b) return 0; else return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -