📄 timestamp.c
字号:
} if (tm->tm_sec < 0) { tm->tm_sec += 60; tm->tm_min--; } if (tm->tm_min < 0) { tm->tm_min += 60; tm->tm_hour--; } if (tm->tm_hour < 0) { tm->tm_hour += 24; tm->tm_mday--; } if (tm->tm_mday < 0) { if (dt1 < dt2) { tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1]; tm->tm_mon--; } else { tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1]; tm->tm_mon--; } } if (tm->tm_mon < 0) { tm->tm_mon += 12; tm->tm_year--; } /* recover sign if necessary... */ if (dt1 < dt2) { fsec = -fsec; tm->tm_sec = -tm->tm_sec; tm->tm_min = -tm->tm_min; tm->tm_hour = -tm->tm_hour; tm->tm_mday = -tm->tm_mday; tm->tm_mon = -tm->tm_mon; tm->tm_year = -tm->tm_year; } if (tm2interval(tm, fsec, result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("interval out of range"))); } else ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); PG_RETURN_INTERVAL_P(result);}/*---------------------------------------------------------- * Conversion operators. *---------------------------------------------------------*//* timestamp_text() * Convert timestamp to text data type. */Datumtimestamp_text(PG_FUNCTION_ARGS){ /* Input is a Timestamp, but may as well leave it in Datum form */ Datum timestamp = PG_GETARG_DATUM(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp)); len = (strlen(str) + VARHDRSZ); result = palloc(len); VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result);}/* text_timestamp() * Convert text string to timestamp. * Text type is not null terminated, so use temporary string * then call the standard input routine. */Datumtext_timestamp(PG_FUNCTION_ARGS){ text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input syntax for type timestamp: \"%s\"", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(str)))))); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; return DirectFunctionCall3(timestamp_in, CStringGetDatum(dstr), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));}/* timestamptz_text() * Convert timestamp with time zone to text data type. */Datumtimestamptz_text(PG_FUNCTION_ARGS){ /* Input is a Timestamp, but may as well leave it in Datum form */ Datum timestamp = PG_GETARG_DATUM(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp)); len = (strlen(str) + VARHDRSZ); result = palloc(len); VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result);}/* text_timestamptz() * Convert text string to timestamp with time zone. * Text type is not null terminated, so use temporary string * then call the standard input routine. */Datumtext_timestamptz(PG_FUNCTION_ARGS){ text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input syntax for type timestamp with time zone: \"%s\"", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(str)))))); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; return DirectFunctionCall3(timestamptz_in, CStringGetDatum(dstr), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));}/* interval_text() * Convert interval to text data type. */Datuminterval_text(PG_FUNCTION_ARGS){ Interval *interval = PG_GETARG_INTERVAL_P(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(interval_out, IntervalPGetDatum(interval))); len = (strlen(str) + VARHDRSZ); result = palloc(len); VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result);}/* text_interval() * Convert text string to interval. * Text type may not be null terminated, so copy to temporary string * then call the standard input routine. */Datumtext_interval(PG_FUNCTION_ARGS){ text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input syntax for type interval: \"%s\"", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(str)))))); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; return DirectFunctionCall3(interval_in, CStringGetDatum(dstr), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));}/* timestamp_trunc() * Truncate timestamp to specified units. */Datumtimestamp_trunc(PG_FUNCTION_ARGS){ text *units = PG_GETARG_TEXT_P(0); Timestamp timestamp = PG_GETARG_TIMESTAMP(1); Timestamp result; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; fsec_t fsec; struct tm tt, *tm = &tt; if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("timestamp units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) *lp++ = tolower((unsigned char) *up++); *lp = '\0'; type = DecodeUnits(0, lowunits, &val); if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_TIMESTAMP(timestamp); if (type == UNITS) { if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); switch (val) { case DTK_MILLENNIUM: tm->tm_year = (tm->tm_year / 1000) * 1000; case DTK_CENTURY: tm->tm_year = (tm->tm_year / 100) * 100; case DTK_DECADE: tm->tm_year = (tm->tm_year / 10) * 10; case DTK_YEAR: tm->tm_mon = 1; case DTK_QUARTER: tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1; case DTK_MONTH: tm->tm_mday = 1; case DTK_DAY: tm->tm_hour = 0; case DTK_HOUR: tm->tm_min = 0; case DTK_MINUTE: tm->tm_sec = 0; case DTK_SECOND: fsec = 0; break; case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP fsec = ((fsec / 1000) * 1000);#else fsec = rint(fsec * 1000) / 1000;#endif break; case DTK_MICROSEC:#ifndef HAVE_INT64_TIMESTAMP fsec = rint(fsec * 1000000) / 1000000;#endif break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("timestamp units \"%s\" not supported", lowunits))); result = 0; } if (tm2timestamp(tm, fsec, NULL, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("timestamp units \"%s\" not recognized", lowunits))); result = 0; } PG_RETURN_TIMESTAMP(result);}/* timestamptz_trunc() * Truncate timestamp to specified units. */Datumtimestamptz_trunc(PG_FUNCTION_ARGS){ text *units = PG_GETARG_TEXT_P(0); TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1); TimestampTz result; int tz; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; fsec_t fsec; char *tzn; struct tm tt, *tm = &tt; if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("timestamp with time zone units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) *lp++ = tolower((unsigned char) *up++); *lp = '\0'; type = DecodeUnits(0, lowunits, &val); if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_TIMESTAMPTZ(timestamp); if (type == UNITS) { if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); switch (val) { case DTK_MILLENNIUM: tm->tm_year = (tm->tm_year / 1000) * 1000; case DTK_CENTURY: tm->tm_year = (tm->tm_year / 100) * 100; case DTK_DECADE: tm->tm_year = (tm->tm_year / 10) * 10; case DTK_YEAR: tm->tm_mon = 1; case DTK_QUARTER: tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1; case DTK_MONTH: tm->tm_mday = 1; case DTK_DAY: tm->tm_hour = 0; case DTK_HOUR: tm->tm_min = 0; case DTK_MINUTE: tm->tm_sec = 0; case DTK_SECOND: fsec = 0; break; case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP fsec = ((fsec / 1000) * 1000);#else fsec = rint(fsec * 1000) / 1000;#endif break; case DTK_MICROSEC:#ifndef HAVE_INT64_TIMESTAMP fsec = rint(fsec * 1000000) / 1000000;#endif break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("timestamp with time zone units \"%s\" not " "supported", lowunits))); result = 0; } tz = DetermineLocalTimeZone(tm); if (tm2timestamp(tm, fsec, &tz, &result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("timestamp with time zone units \"%s\" not recognized", lowunits))); result = 0; } PG_RETURN_TIMESTAMPTZ(result);}/* interval_trunc() * Extract specified field from interval. */Datuminterval_trunc(PG_FUNCTION_ARGS){ text *units = PG_GETARG_TEXT_P(0); Interval *interval = PG_GETARG_INTERVAL_P(1); Interval *result; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; fsec_t fsec; struct tm tt, *tm = &tt; result = (Interval *) palloc(sizeof(Interval)); if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("interval units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) *lp++ = tolower((unsigned char) *up++); *lp = '\0'; type = DecodeUnits(0, lowunits, &val); if (type == UNITS) { if (interval2tm(*interval, tm, &fsec) == 0) { switch (val) { case DTK_MILLENNIUM: tm->tm_year = (tm->tm_year / 1000) * 1000; case DTK_CENTURY: tm->tm_year = (tm->tm_year / 100) * 100; case DTK_DECADE: tm->tm_year = (tm->tm_year / 10) * 10; case DTK_YEAR: tm->tm_mon = 0; case DTK_QUARTER: tm->tm_mon = (3 * (tm->tm_mon / 3)); case DTK_MONTH: tm->tm_mday = 0; case DTK_DAY: tm->tm_hour = 0; case DTK_HOUR: tm->tm_min = 0; case DTK_MINUTE: tm->tm_sec = 0; case DTK_SECOND: fsec = 0; break; case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP fsec = ((fsec / 1000) * 1000);#else fsec = rint(fsec * 1000) / 1000;#endif break; case DTK_MICROSEC:#ifndef HAVE_INT64_TIMESTAMP fsec = rint(fsec * 1000000) / 1000000;#endif break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("interval units \"%s\" not supported", lowunits))); } if (tm2interval(tm, fsec, result) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("interval out of range"))); } else elog(ERROR, "could not convert interval to tm"); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("interval units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, Pointe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -