aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/date.c')
-rw-r--r--src/backend/utils/adt/date.c268
1 files changed, 207 insertions, 61 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 4504f5f043c..36b3a52de25 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,21 +8,24 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.57 2001/05/03 19:00:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.58 2001/09/28 08:09:10 thomas Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include <ctype.h>
#include <limits.h>
#include <time.h>
#include <float.h>
#include "access/hash.h"
#include "miscadmin.h"
+#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/nabstime.h"
+#include "utils/timestamp.h"
/*****************************************************************************
@@ -58,13 +61,13 @@ date_in(PG_FUNCTION_ARGS)
break;
case DTK_CURRENT:
+ elog(ERROR, "Date CURRENT no longer supported"
+ "\n\tdate_in() internal coding error");
GetCurrentTime(tm);
break;
case DTK_EPOCH:
- tm->tm_year = 1970;
- tm->tm_mon = 1;
- tm->tm_mday = 1;
+ GetEpochTime(tm);
break;
default:
@@ -224,6 +227,46 @@ date_timestamp(PG_FUNCTION_ARGS)
{
DateADT dateVal = PG_GETARG_DATEADT(0);
Timestamp result;
+
+ /* date is days since 2000, timestamp is seconds since same... */
+ result = dateVal * 86400.0;
+
+ PG_RETURN_TIMESTAMP(result);
+}
+
+
+/* timestamp_date()
+ * Convert timestamp to date data type.
+ */
+Datum
+timestamp_date(PG_FUNCTION_ARGS)
+{
+ Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
+ DateADT result;
+ struct tm tt,
+ *tm = &tt;
+ double fsec;
+
+ if (TIMESTAMP_NOT_FINITE(timestamp))
+ PG_RETURN_NULL();
+
+ if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
+ elog(ERROR, "Unable to convert timestamp to date");
+
+ result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
+
+ PG_RETURN_DATEADT(result);
+}
+
+
+/* date_timestamptz()
+ * Convert date to timestamp with time zone data type.
+ */
+Datum
+date_timestamptz(PG_FUNCTION_ARGS)
+{
+ DateADT dateVal = PG_GETARG_DATEADT(0);
+ TimestampTz result;
struct tm tt,
*tm = &tt;
time_t utime;
@@ -259,32 +302,25 @@ date_timestamp(PG_FUNCTION_ARGS)
}
-/* timestamp_date()
- * Convert timestamp to date data type.
+/* timestamptz_date()
+ * Convert timestamp with time zone to date data type.
*/
Datum
-timestamp_date(PG_FUNCTION_ARGS)
+timestamptz_date(PG_FUNCTION_ARGS)
{
- Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
+ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
DateADT result;
struct tm tt,
*tm = &tt;
- int tz;
double fsec;
+ int tz;
char *tzn;
if (TIMESTAMP_NOT_FINITE(timestamp))
- elog(ERROR, "Unable to convert timestamp to date");
+ PG_RETURN_NULL();
- if (TIMESTAMP_IS_EPOCH(timestamp))
- timestamp2tm(SetTimestamp(timestamp), NULL, tm, &fsec, NULL);
- else if (TIMESTAMP_IS_CURRENT(timestamp))
- timestamp2tm(SetTimestamp(timestamp), &tz, tm, &fsec, &tzn);
- else
- {
- if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to convert timestamp to date");
- }
+ if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
+ elog(ERROR, "Unable to convert timestamp to date");
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
@@ -316,15 +352,6 @@ abstime_date(PG_FUNCTION_ARGS)
* will be set
*/
- case EPOCH_ABSTIME:
- result = date2j(1970, 1, 1) - date2j(2000, 1, 1);
- break;
-
- case CURRENT_ABSTIME:
- GetCurrentTime(tm);
- result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
- break;
-
default:
abstime2tm(abstime, &tz, tm, NULL);
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
@@ -664,22 +691,13 @@ timestamp_time(PG_FUNCTION_ARGS)
TimeADT result;
struct tm tt,
*tm = &tt;
- int tz;
double fsec;
- char *tzn;
if (TIMESTAMP_NOT_FINITE(timestamp))
- elog(ERROR, "Unable to convert timestamp to date");
+ PG_RETURN_NULL();
- if (TIMESTAMP_IS_EPOCH(timestamp))
- timestamp2tm(SetTimestamp(timestamp), NULL, tm, &fsec, NULL);
- else if (TIMESTAMP_IS_CURRENT(timestamp))
- timestamp2tm(SetTimestamp(timestamp), &tz, tm, &fsec, &tzn);
- else
- {
- if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to convert timestamp to date");
- }
+ if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
+ elog(ERROR, "Unable to convert timestamp to date");
result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
@@ -736,6 +754,24 @@ interval_time(PG_FUNCTION_ARGS)
PG_RETURN_TIMEADT(result);
}
+/* time_mi_time()
+ * Subtract two times to produce an interval.
+ */
+Datum
+time_mi_time(PG_FUNCTION_ARGS)
+{
+ TimeADT time1 = PG_GETARG_TIMEADT(0);
+ TimeADT time2 = PG_GETARG_TIMEADT(1);
+ Interval *result;
+
+ result = (Interval *) palloc(sizeof(Interval));
+
+ result->time = time2 - time1;
+ result->month = 0;
+
+ PG_RETURN_INTERVAL_P(result);
+}
+
/* time_pl_interval()
* Add interval to time.
*/
@@ -918,7 +954,12 @@ timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
* If same GMT time, sort by timezone; we only want to say that two
* timetz's are equal if both the time and zone parts are equal.
*/
- return time1->zone - time2->zone;
+ if (time1->zone > time2->zone)
+ return 1;
+ if (time1->zone < time2->zone)
+ return -1;
+
+ return 0;
}
Datum
@@ -1199,13 +1240,48 @@ overlaps_timetz(PG_FUNCTION_ARGS)
#undef TIMETZ_LT
}
-/* timestamp_timetz()
+
+Datum
+timetz_time(PG_FUNCTION_ARGS)
+{
+ TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
+ TimeADT result;
+
+ /* swallow the time zone and just return the time */
+ result = timetz->time;
+
+ PG_RETURN_TIMEADT(result);
+}
+
+
+Datum
+time_timetz(PG_FUNCTION_ARGS)
+{
+ TimeADT time = PG_GETARG_TIMEADT(0);
+ TimeTzADT *result;
+ struct tm tt,
+ *tm = &tt;
+ int tz;
+
+ GetCurrentTime(tm);
+ tz = DetermineLocalTimeZone(tm);
+
+ result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+
+ result->time = time;
+ result->zone = tz;
+
+ PG_RETURN_TIMETZADT_P(result);
+}
+
+
+/* timestamptz_timetz()
* Convert timestamp to timetz data type.
*/
Datum
-timestamp_timetz(PG_FUNCTION_ARGS)
+timestamptz_timetz(PG_FUNCTION_ARGS)
{
- Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
+ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
TimeTzADT *result;
struct tm tt,
*tm = &tt;
@@ -1214,20 +1290,10 @@ timestamp_timetz(PG_FUNCTION_ARGS)
char *tzn;
if (TIMESTAMP_NOT_FINITE(timestamp))
- elog(ERROR, "Unable to convert timestamp to date");
+ PG_RETURN_NULL();
- if (TIMESTAMP_IS_EPOCH(timestamp))
- {
- timestamp2tm(SetTimestamp(timestamp), NULL, tm, &fsec, NULL);
- tz = 0;
- }
- else if (TIMESTAMP_IS_CURRENT(timestamp))
- timestamp2tm(SetTimestamp(timestamp), &tz, tm, &fsec, &tzn);
- else
- {
- if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "Unable to convert timestamp to date");
- }
+ if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
+ elog(ERROR, "Unable to convert timestamp to date");
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
@@ -1238,18 +1304,18 @@ timestamp_timetz(PG_FUNCTION_ARGS)
}
-/* datetimetz_timestamp()
- * Convert date and timetz to timestamp data type.
+/* datetimetz_timestamptz()
+ * Convert date and timetz to timestamp with time zone data type.
* Timestamp is stored in GMT, so add the time zone
* stored with the timetz to the result.
* - thomas 2000-03-10
*/
Datum
-datetimetz_timestamp(PG_FUNCTION_ARGS)
+datetimetz_timestamptz(PG_FUNCTION_ARGS)
{
DateADT date = PG_GETARG_DATEADT(0);
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
- Timestamp result;
+ TimestampTz result;
result = date * 86400.0 + time->time + time->zone;
@@ -1310,3 +1376,83 @@ text_timetz(PG_FUNCTION_ARGS)
return DirectFunctionCall1(timetz_in,
CStringGetDatum(dstr));
}
+
+/* timetz_zone()
+ * Encode time with time zone type with specified time zone.
+ */
+Datum
+timetz_zone(PG_FUNCTION_ARGS)
+{
+ text *zone = PG_GETARG_TEXT_P(0);
+ TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
+ TimeTzADT *result;
+ TimeADT time1;
+ int tz;
+ int type,
+ val;
+ int i;
+ char *up,
+ *lp,
+ lowzone[MAXDATELEN + 1];
+
+ if (VARSIZE(zone) - VARHDRSZ > MAXDATELEN)
+ elog(ERROR, "Time zone '%s' not recognized",
+ DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(zone))));
+ up = VARDATA(zone);
+ lp = lowzone;
+ for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++)
+ *lp++ = tolower((unsigned char) *up++);
+ *lp = '\0';
+
+ type = DecodeSpecial(0, lowzone, &val);
+
+ result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+
+ if ((type == TZ) || (type == DTZ))
+ {
+ tz = val * 60;
+ time1 = time->time - time->zone + tz;
+ TMODULO(result->time, time1, 86400e0);
+ if (result->time < 0)
+ result->time += 86400;
+ result->zone = tz;
+ }
+ else
+ {
+ elog(ERROR, "Time zone '%s' not recognized", lowzone);
+ PG_RETURN_NULL();
+ }
+
+ PG_RETURN_TIMETZADT_P(result);
+} /* timetz_zone() */
+
+/* timetz_izone()
+ * Encode time with time zone type with specified time interval as time zone.
+ */
+Datum
+timetz_izone(PG_FUNCTION_ARGS)
+{
+ Interval *zone = PG_GETARG_INTERVAL_P(0);
+ TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
+ TimeTzADT *result;
+ TimeADT time1;
+ int tz;
+
+ if (zone->month != 0)
+ elog(ERROR, "INTERVAL time zone '%s' not legal (month specified)",
+ DatumGetCString(DirectFunctionCall1(interval_out,
+ PointerGetDatum(zone))));
+
+ tz = -(zone->time);
+
+ result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+
+ time1 = time->time - time->zone + tz;
+ TMODULO(result->time, time1, 86400e0);
+ if (result->time < 0)
+ result->time += 86400;
+ result->zone = tz;
+
+ PG_RETURN_TIMETZADT_P(result);
+} /* timetz_izone() */