diff options
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 106 |
1 files changed, 80 insertions, 26 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 1bd42689659..8bd0daf2bf6 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.51 2001/09/28 08:09:11 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.52 2001/10/03 05:29:24 thomas Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,8 @@ static double time2t(const int hour, const int min, const double sec); static int EncodeSpecialTimestamp(Timestamp dt, char *str); static Timestamp dt2local(Timestamp dt, int timezone); +static void +AdjustTimestampForTypmod(Timestamp *time, int32 typmod); /***************************************************************************** @@ -45,6 +47,10 @@ Datum timestamp_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); Timestamp result; double fsec; struct tm tt, @@ -89,6 +95,8 @@ timestamp_in(PG_FUNCTION_ARGS) TIMESTAMP_NOEND(result); } + AdjustTimestampForTypmod(&result, typmod); + PG_RETURN_TIMESTAMP(result); } @@ -98,7 +106,7 @@ timestamp_in(PG_FUNCTION_ARGS) Datum timestamp_out(PG_FUNCTION_ARGS) { - Timestamp dt = PG_GETARG_TIMESTAMP(0); + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); char *result; struct tm tt, *tm = &tt; @@ -106,9 +114,9 @@ timestamp_out(PG_FUNCTION_ARGS) char *tzn = NULL; char buf[MAXDATELEN + 1]; - if (TIMESTAMP_NOT_FINITE(dt)) - EncodeSpecialTimestamp(dt, buf); - else if (timestamp2tm(dt, NULL, tm, &fsec, NULL) == 0) + if (TIMESTAMP_NOT_FINITE(timestamp)) + EncodeSpecialTimestamp(timestamp, buf); + else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0) EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf); else elog(ERROR, "Unable to format timestamp; internal coding error"); @@ -117,6 +125,42 @@ timestamp_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* timestamp_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +timestamp_scale(PG_FUNCTION_ARGS) +{ + Timestamp timestamp = PG_GETARG_TIMESTAMP(0); + int32 typmod = PG_GETARG_INT32(1); + Timestamp result; + + result = timestamp; + + if (! TIMESTAMP_NOT_FINITE(result)) + AdjustTimestampForTypmod(&result, typmod); + + PG_RETURN_TIMESTAMP(result); +} + +static void +AdjustTimestampForTypmod(Timestamp *time, int32 typmod) +{ + if ((typmod >= 0) && (typmod <= 13)) + { + static double TimestampScale = 1; + static int32 TimestampTypmod = 0; + + if (typmod != TimestampTypmod) + TimestampScale = pow(10, typmod); + + *time = (rint(((double) *time)*TimestampScale)/TimestampScale); + } + + return; +} + /* timestamptz_in() * Convert a string to internal form. @@ -125,6 +169,10 @@ Datum timestamptz_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 typmod = PG_GETARG_INT32(2); TimestampTz result; double fsec; struct tm tt, @@ -169,6 +217,8 @@ timestamptz_in(PG_FUNCTION_ARGS) TIMESTAMP_NOEND(result); } + AdjustTimestampForTypmod(&result, typmod); + PG_RETURN_TIMESTAMPTZ(result); } @@ -198,6 +248,25 @@ timestamptz_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(result); } +/* timestamptz_scale() + * Adjust time type for specified scale factor. + * Used by PostgreSQL type system to stuff columns. + */ +Datum +timestamptz_scale(PG_FUNCTION_ARGS) +{ + TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); + int32 typmod = PG_GETARG_INT32(1); + TimestampTz result; + + result = timestamp; + + if (! TIMESTAMP_NOT_FINITE(result)) + AdjustTimestampForTypmod(&result, typmod); + + PG_RETURN_TIMESTAMPTZ(result); +} + /* interval_in() * Convert a string to internal form. @@ -2119,16 +2188,13 @@ timestamp_part(PG_FUNCTION_ARGS) text *units = PG_GETARG_TEXT_P(0); Timestamp timestamp = PG_GETARG_TIMESTAMP(1); float8 result; - int tz; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; - double dummy; double fsec; - char *tzn; struct tm tt, *tm = &tt; @@ -2152,24 +2218,10 @@ timestamp_part(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(result); } - if ((type == UNITS) && (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) == 0)) + if ((type == UNITS) && (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)) { switch (val) { - case DTK_TZ: - result = tz; - break; - - case DTK_TZ_MINUTE: - result = tz / 60; - TMODULO(result, dummy, 60e0); - break; - - case DTK_TZ_HOUR: - dummy = tz; - TMODULO(dummy, result, 3600e0); - break; - case DTK_MICROSEC: result = (fsec * 1000000); break; @@ -2222,11 +2274,13 @@ timestamp_part(PG_FUNCTION_ARGS) result = (tm->tm_year / 1000); break; + case DTK_TZ: + case DTK_TZ_MINUTE: + case DTK_TZ_HOUR: default: elog(ERROR, "Timestamp units '%s' not supported", lowunits); result = 0; } - } else if (type == RESERV) { @@ -2237,14 +2291,14 @@ timestamp_part(PG_FUNCTION_ARGS) break; case DTK_DOW: - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0) elog(ERROR, "Unable to encode timestamp"); result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); break; case DTK_DOY: - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0) elog(ERROR, "Unable to encode timestamp"); result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) |