1996-07-09 06:22:35 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-13 23:22:53 +00:00
|
|
|
* date.c
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
* implements DATE and TIME data types specified in SQL-92 standard
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
2002-06-20 20:29:54 +00:00
|
|
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2003-04-08 17:02:04 +00:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.81 2003/04/08 17:02:04 tgl Exp $
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres.h"
|
2000-06-19 03:55:01 +00:00
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
#include <ctype.h>
|
2000-06-19 03:55:01 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <time.h>
|
1997-09-07 05:04:48 +00:00
|
|
|
#include <float.h>
|
2000-06-19 03:55:01 +00:00
|
|
|
|
|
|
|
#include "access/hash.h"
|
1999-07-16 05:00:38 +00:00
|
|
|
#include "miscadmin.h"
|
2001-09-28 08:09:14 +00:00
|
|
|
#include "utils/builtins.h"
|
2000-06-15 03:33:12 +00:00
|
|
|
#include "utils/date.h"
|
|
|
|
#include "utils/nabstime.h"
|
2001-09-28 08:09:14 +00:00
|
|
|
#include "utils/timestamp.h"
|
1997-03-14 23:21:12 +00:00
|
|
|
|
2002-09-21 19:52:41 +00:00
|
|
|
/*
|
|
|
|
* gcc's -ffast-math switch breaks routines that expect exact results from
|
|
|
|
* expressions like timeval / 3600, where timeval is double.
|
|
|
|
*/
|
|
|
|
#ifdef __FAST_MATH__
|
|
|
|
#error -ffast-math is known to break this code
|
|
|
|
#endif
|
|
|
|
|
2000-06-19 03:55:01 +00:00
|
|
|
|
2002-09-21 19:52:41 +00:00
|
|
|
static int time2tm(TimeADT time, struct tm * tm, fsec_t *fsec);
|
|
|
|
static int timetz2tm(TimeTzADT *time, struct tm * tm, fsec_t *fsec, int *tzp);
|
|
|
|
static int tm2time(struct tm * tm, fsec_t fsec, TimeADT *result);
|
|
|
|
static int tm2timetz(struct tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
|
2001-10-04 15:14:22 +00:00
|
|
|
static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
|
2001-10-03 05:29:27 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*****************************************************************************
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
* Date ADT
|
1996-07-09 06:22:35 +00:00
|
|
|
*****************************************************************************/
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
|
|
|
|
/* date_in()
|
|
|
|
* Given date text string, convert to internal date format.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_in(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
char *str = PG_GETARG_CSTRING(0);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
DateADT date;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
int tzp;
|
1997-09-08 02:41:22 +00:00
|
|
|
int dtype;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
int nf;
|
1997-09-08 02:41:22 +00:00
|
|
|
char *field[MAXDATEFIELDS];
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
int ftype[MAXDATEFIELDS];
|
1997-09-08 02:41:22 +00:00
|
|
|
char lowstr[MAXDATELEN + 1];
|
1997-03-14 23:21:12 +00:00
|
|
|
|
2002-08-04 06:44:47 +00:00
|
|
|
if (strlen(str) >= sizeof(lowstr))
|
|
|
|
elog(ERROR, "Bad date external representation (too long) '%s'", str);
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
2001-03-22 04:01:46 +00:00
|
|
|
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
elog(ERROR, "Bad date external representation '%s'", str);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
switch (dtype)
|
|
|
|
{
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
case DTK_DATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_CURRENT:
|
2001-09-28 08:09:14 +00:00
|
|
|
elog(ERROR, "Date CURRENT no longer supported"
|
|
|
|
"\n\tdate_in() internal coding error");
|
2002-06-11 13:40:53 +00:00
|
|
|
GetCurrentDateTime(tm);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_EPOCH:
|
2001-09-28 08:09:14 +00:00
|
|
|
GetEpochTime(tm);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
elog(ERROR, "Unrecognized date external representation '%s'", str);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
2003-04-04 04:50:44 +00:00
|
|
|
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_DATEADT(date);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* date_out()
|
|
|
|
* Given internal format date, convert to text string.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_out(PG_FUNCTION_ARGS)
|
1997-07-29 15:54:49 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT date = PG_GETARG_DATEADT(0);
|
1997-09-08 02:41:22 +00:00
|
|
|
char *result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
char buf[MAXDATELEN + 1];
|
1997-07-29 15:54:49 +00:00
|
|
|
|
2003-04-04 04:50:44 +00:00
|
|
|
j2date(date + POSTGRES_EPOCH_JDATE,
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
&(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
1997-07-29 15:54:49 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
EncodeDateOnly(tm, DateStyle, buf);
|
1997-07-29 15:54:49 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result = pstrdup(buf);
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_eq(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
1997-07-29 15:54:49 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(dateVal1 == dateVal2);
|
|
|
|
}
|
1997-07-29 15:54:49 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_ne(PG_FUNCTION_ARGS)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(dateVal1 != dateVal2);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_lt(PG_FUNCTION_ARGS)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(dateVal1 < dateVal2);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_le(PG_FUNCTION_ARGS)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(dateVal1 <= dateVal2);
|
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 18:36:24 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_gt(PG_FUNCTION_ARGS)
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(dateVal1 > dateVal2);
|
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 18:36:24 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_ge(PG_FUNCTION_ARGS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(dateVal1 >= dateVal2);
|
|
|
|
}
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions
Here are some additional patches mostly related to the date and time
data types. It includes some type conversion routines to move between
the different date types and some other date manipulation routines such
as date_part(units,datetime).
I noticed Edmund Mergl et al's neat trick for getting function overloading
for builtin functions, so started to use that for the date and time stuff.
Later, if someone figures out how to get function overloading directly
for internal C code, then we can move to that technique.
These patches include documentation updates (don't faint!) for the built-in
man page. Doesn't yet include mention of timestamp, since I don't know
much about it and since it may change a bit to become a _real_ ANSI timestamp
which would include parser support for the declaration syntax (what do you
think, Dan?).
The patches were developed on the 970330 release, but have been rebuilt
off of the 970402 release. The first patch below is to get libpq to compile,
on my Linux box, but is not related to the rest of the patches and you can
choose not to apply that one at this time. Thanks in advance, scrappy!
1997-04-02 18:36:24 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_cmp(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
if (dateVal1 < dateVal2)
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_INT32(-1);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
else if (dateVal1 > dateVal2)
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_INT32(1);
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_larger(PG_FUNCTION_ARGS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
date_smaller(PG_FUNCTION_ARGS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* Compute difference between two dates in days.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_mi(PG_FUNCTION_ARGS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal1 = PG_GETARG_DATEADT(0);
|
|
|
|
DateADT dateVal2 = PG_GETARG_DATEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32((int32) (dateVal1 - dateVal2));
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* Add a number of days to a date, giving a new date.
|
|
|
|
* Must handle both positive and negative numbers of days.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_pli(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal = PG_GETARG_DATEADT(0);
|
|
|
|
int32 days = PG_GETARG_INT32(1);
|
|
|
|
|
|
|
|
PG_RETURN_DATEADT(dateVal + days);
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* Subtract a number of days from a date, giving a new date.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_mii(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal = PG_GETARG_DATEADT(0);
|
|
|
|
int32 days = PG_GETARG_INT32(1);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_DATEADT(dateVal - days);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#if NOT_USED
|
|
|
|
/* date_pl_interval() and date_mi_interval() are probably
|
|
|
|
* better implmented by converting the input date
|
|
|
|
* to timestamp without time zone. So that is what we do
|
|
|
|
* in pg_proc.h - thomas 2002-03-11
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Add an interval to a date, giving a new date.
|
|
|
|
* Must handle both positive and negative intervals.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
date_pl_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
DateADT dateVal = PG_GETARG_DATEADT(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
|
|
|
|
if (span->month != 0)
|
|
|
|
{
|
2003-04-04 04:50:44 +00:00
|
|
|
j2date(dateVal + POSTGRES_EPOCH_JDATE,
|
|
|
|
&(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
2002-04-21 19:52:18 +00:00
|
|
|
tm->tm_mon += span->month;
|
2003-04-04 04:50:44 +00:00
|
|
|
dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
2002-04-21 19:52:18 +00:00
|
|
|
}
|
|
|
|
if (span->time != 0)
|
|
|
|
dateVal += (span->time / 86400e0);
|
|
|
|
|
|
|
|
PG_RETURN_DATEADT(dateVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Subtract an interval from a date, giving a new date.
|
|
|
|
* Must handle both positive and negative intervals.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
date_mi_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
DateADT dateVal = PG_GETARG_DATEADT(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
|
|
|
|
if (span->month != 0)
|
|
|
|
{
|
2003-04-04 04:50:44 +00:00
|
|
|
j2date(dateVal + POSTGRES_EPOCH_JDATE,
|
|
|
|
&(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
2002-04-21 19:52:18 +00:00
|
|
|
tm->tm_mon -= span->month;
|
2003-04-04 04:50:44 +00:00
|
|
|
dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
2002-04-21 19:52:18 +00:00
|
|
|
}
|
|
|
|
if (span->time != 0)
|
|
|
|
dateVal -= (span->time / 86400e0);
|
|
|
|
|
|
|
|
PG_RETURN_DATEADT(dateVal);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* date_timestamp()
|
|
|
|
* Convert date to timestamp data type.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
date_timestamp(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT dateVal = PG_GETARG_DATEADT(0);
|
|
|
|
Timestamp result;
|
2001-09-28 08:09:14 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
/* date is days since 2000, timestamp is microseconds since same... */
|
|
|
|
result = dateVal * INT64CONST(86400000000);
|
|
|
|
#else
|
2001-09-28 08:09:14 +00:00
|
|
|
/* date is days since 2000, timestamp is seconds since same... */
|
|
|
|
result = dateVal * 86400.0;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-09-28 08:09:14 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (TIMESTAMP_NOT_FINITE(timestamp))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
2002-06-01 15:52:15 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
/* Microseconds to days */
|
2002-04-21 19:52:18 +00:00
|
|
|
result = (timestamp / INT64CONST(86400000000));
|
2002-06-01 15:52:15 +00:00
|
|
|
#else
|
|
|
|
/* Seconds to days */
|
|
|
|
result = (timestamp / 86400.0);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-09-28 08:09:14 +00:00
|
|
|
|
|
|
|
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);
|
2001-10-25 05:50:21 +00:00
|
|
|
TimestampTz result;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-04-04 04:50:44 +00:00
|
|
|
j2date(dateVal + POSTGRES_EPOCH_JDATE,
|
2002-09-03 19:41:28 +00:00
|
|
|
&(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-09-12 05:41:37 +00:00
|
|
|
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
{
|
2002-09-04 20:31:48 +00:00
|
|
|
int tz;
|
2002-09-03 19:41:28 +00:00
|
|
|
|
2000-09-12 05:41:37 +00:00
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
2002-09-03 19:41:28 +00:00
|
|
|
tz = DetermineLocalTimeZone(tm);
|
2000-09-12 05:41:37 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-09-03 19:41:28 +00:00
|
|
|
result = (dateVal * INT64CONST(86400000000))
|
|
|
|
+ (tz * INT64CONST(1000000));
|
2000-10-29 13:17:34 +00:00
|
|
|
#else
|
2002-09-03 19:41:28 +00:00
|
|
|
result = dateVal * 86400.0 + tz;
|
2000-09-12 05:41:37 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-09-03 19:41:28 +00:00
|
|
|
/* Outside of range for timezone support, so assume UTC */
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (dateVal * INT64CONST(86400000000));
|
|
|
|
#else
|
2001-03-22 04:01:46 +00:00
|
|
|
result = dateVal * 86400.0;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-09-12 05:41:37 +00:00
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMESTAMP(result);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
/* timestamptz_date()
|
|
|
|
* Convert timestamp with time zone to date data type.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
2001-09-28 08:09:14 +00:00
|
|
|
timestamptz_date(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2001-10-25 05:50:21 +00:00
|
|
|
TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
DateADT result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2001-09-28 08:09:14 +00:00
|
|
|
int tz;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
char *tzn;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
if (TIMESTAMP_NOT_FINITE(timestamp))
|
2001-09-28 08:09:14 +00:00
|
|
|
PG_RETURN_NULL();
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
|
|
|
|
elog(ERROR, "Unable to convert timestamp to date");
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2003-04-04 04:50:44 +00:00
|
|
|
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_DATEADT(result);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* abstime_date()
|
|
|
|
* Convert abstime to date data type.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
abstime_date(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
DateADT result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
int tz;
|
1997-09-20 16:17:45 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
switch (abstime)
|
|
|
|
{
|
|
|
|
case INVALID_ABSTIME:
|
|
|
|
case NOSTART_ABSTIME:
|
|
|
|
case NOEND_ABSTIME:
|
|
|
|
elog(ERROR, "Unable to convert reserved abstime value to date");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* pretend to drop through to make compiler think that result
|
|
|
|
* will be set
|
|
|
|
*/
|
|
|
|
|
|
|
|
default:
|
|
|
|
abstime2tm(abstime, &tz, tm, NULL);
|
2003-04-04 04:50:44 +00:00
|
|
|
result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
break;
|
|
|
|
}
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_DATEADT(result);
|
|
|
|
}
|
1997-09-20 16:17:45 +00:00
|
|
|
|
|
|
|
|
2000-11-11 19:55:19 +00:00
|
|
|
/* date_text()
|
|
|
|
* Convert date to text data type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
date_text(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Input is a Date, but may as well leave it in Datum form */
|
|
|
|
Datum date = PG_GETARG_DATUM(0);
|
|
|
|
text *result;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
str = DatumGetCString(DirectFunctionCall1(date_out, date));
|
|
|
|
|
|
|
|
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_date()
|
|
|
|
* Convert text string to date.
|
|
|
|
* Text type is not null terminated, so use temporary string
|
|
|
|
* then call the standard input routine.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
text_date(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *str = PG_GETARG_TEXT_P(0);
|
|
|
|
int i;
|
|
|
|
char *sp,
|
|
|
|
*dp,
|
|
|
|
dstr[MAXDATELEN + 1];
|
|
|
|
|
|
|
|
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
|
|
|
|
elog(ERROR, "Bad date external representation (too long)");
|
|
|
|
|
|
|
|
sp = VARDATA(str);
|
|
|
|
dp = dstr;
|
|
|
|
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
*dp = '\0';
|
|
|
|
|
|
|
|
return DirectFunctionCall1(date_in,
|
|
|
|
CStringGetDatum(dstr));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* Time ADT
|
|
|
|
*****************************************************************************/
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_in(PG_FUNCTION_ARGS)
|
1997-09-20 16:17:45 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
char *str = PG_GETARG_CSTRING(0);
|
2002-09-04 20:31:48 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 typmod = PG_GETARG_INT32(2);
|
|
|
|
TimeADT result;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
2003-01-31 01:08:08 +00:00
|
|
|
int tz;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
int nf;
|
|
|
|
char lowstr[MAXDATELEN + 1];
|
|
|
|
char *field[MAXDATEFIELDS];
|
|
|
|
int dtype;
|
|
|
|
int ftype[MAXDATEFIELDS];
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2002-08-04 06:44:47 +00:00
|
|
|
if (strlen(str) >= sizeof(lowstr))
|
|
|
|
elog(ERROR, "Bad time external representation (too long) '%s'", str);
|
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
2003-01-31 01:08:08 +00:00
|
|
|
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
elog(ERROR, "Bad time external representation '%s'", str);
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
tm2time(tm, fsec, &result);
|
2001-10-03 05:29:27 +00:00
|
|
|
AdjustTimeForTypmod(&result, typmod);
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
PG_RETURN_TIMEADT(result);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
/* tm2time()
|
|
|
|
* Convert a tm structure to a time data type.
|
|
|
|
*/
|
2002-09-21 19:52:41 +00:00
|
|
|
static int
|
2002-04-21 19:52:18 +00:00
|
|
|
tm2time(struct tm * tm, fsec_t fsec, TimeADT *result)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
*result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
|
2002-09-04 20:31:48 +00:00
|
|
|
* INT64CONST(1000000)) + fsec);
|
2002-04-21 19:52:18 +00:00
|
|
|
#else
|
|
|
|
*result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* time2tm()
|
|
|
|
* Convert time data type to POSIX time structure.
|
|
|
|
* For dates within the system-supported time_t range, convert to the
|
|
|
|
* local time zone. If out of this range, leave as GMT. - tgl 97/05/27
|
|
|
|
*/
|
2002-09-21 19:52:41 +00:00
|
|
|
static int
|
2002-09-04 20:31:48 +00:00
|
|
|
time2tm(TimeADT time, struct tm * tm, fsec_t *fsec)
|
2002-04-21 19:52:18 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
tm->tm_hour = (time / INT64CONST(3600000000));
|
|
|
|
time -= (tm->tm_hour * INT64CONST(3600000000));
|
|
|
|
tm->tm_min = (time / INT64CONST(60000000));
|
|
|
|
time -= (tm->tm_min * INT64CONST(60000000));
|
|
|
|
tm->tm_sec = (time / INT64CONST(1000000));
|
|
|
|
time -= (tm->tm_sec * INT64CONST(1000000));
|
|
|
|
*fsec = time;
|
|
|
|
#else
|
|
|
|
double trem;
|
|
|
|
|
|
|
|
trem = time;
|
|
|
|
TMODULO(trem, tm->tm_hour, 3600e0);
|
|
|
|
TMODULO(trem, tm->tm_min, 60e0);
|
|
|
|
TMODULO(trem, tm->tm_sec, 1e0);
|
|
|
|
*fsec = trem;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_out(PG_FUNCTION_ARGS)
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time = PG_GETARG_TIMEADT(0);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
char *result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
char buf[MAXDATELEN + 1];
|
1997-09-20 16:17:45 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
time2tm(time, tm, &fsec);
|
2000-03-14 23:06:59 +00:00
|
|
|
EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result = pstrdup(buf);
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
/* time_scale()
|
|
|
|
* Adjust time type for specified scale factor.
|
|
|
|
* Used by PostgreSQL type system to stuff columns.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
time_scale(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeADT time = PG_GETARG_TIMEADT(0);
|
|
|
|
int32 typmod = PG_GETARG_INT32(1);
|
|
|
|
TimeADT result;
|
|
|
|
|
|
|
|
result = time;
|
|
|
|
AdjustTimeForTypmod(&result, typmod);
|
|
|
|
|
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
|
|
|
|
2002-08-04 06:44:47 +00:00
|
|
|
/* AdjustTimeForTypmod()
|
|
|
|
* Force the precision of the time value to a specified value.
|
|
|
|
* Uses *exactly* the same code as in AdjustTimestampForTypemod()
|
|
|
|
* but we make a separate copy because those types do not
|
|
|
|
* have a fundamental tie together but rather a coincidence of
|
|
|
|
* implementation. - thomas
|
|
|
|
*/
|
2001-10-03 05:29:27 +00:00
|
|
|
static void
|
|
|
|
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
|
|
|
|
{
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2003-01-29 01:08:42 +00:00
|
|
|
static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
|
2002-08-04 06:44:47 +00:00
|
|
|
INT64CONST(1000000),
|
|
|
|
INT64CONST(100000),
|
|
|
|
INT64CONST(10000),
|
|
|
|
INT64CONST(1000),
|
|
|
|
INT64CONST(100),
|
|
|
|
INT64CONST(10),
|
|
|
|
INT64CONST(1)
|
|
|
|
};
|
|
|
|
|
2003-01-29 01:08:42 +00:00
|
|
|
static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
|
2003-01-09 01:06:57 +00:00
|
|
|
INT64CONST(500000),
|
|
|
|
INT64CONST(50000),
|
|
|
|
INT64CONST(5000),
|
|
|
|
INT64CONST(500),
|
|
|
|
INT64CONST(50),
|
|
|
|
INT64CONST(5),
|
2002-08-04 06:44:47 +00:00
|
|
|
INT64CONST(0)
|
|
|
|
};
|
2002-09-04 20:31:48 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#else
|
2003-01-29 01:08:42 +00:00
|
|
|
/* note MAX_TIME_PRECISION differs in this case */
|
|
|
|
static const double TimeScales[MAX_TIME_PRECISION + 1] = {
|
2003-04-08 17:02:04 +00:00
|
|
|
1.0,
|
|
|
|
10.0,
|
|
|
|
100.0,
|
|
|
|
1000.0,
|
|
|
|
10000.0,
|
|
|
|
100000.0,
|
|
|
|
1000000.0,
|
|
|
|
10000000.0,
|
|
|
|
100000000.0,
|
|
|
|
1000000000.0,
|
|
|
|
10000000000.0
|
2002-08-04 06:44:47 +00:00
|
|
|
};
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-10-03 05:29:27 +00:00
|
|
|
|
2002-08-04 06:44:47 +00:00
|
|
|
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
|
|
|
|
{
|
2003-01-09 01:06:57 +00:00
|
|
|
/*
|
|
|
|
* Note: this round-to-nearest code is not completely consistent
|
|
|
|
* about rounding values that are exactly halfway between integral
|
2003-01-22 20:44:20 +00:00
|
|
|
* values. On most platforms, rint() will implement round-to-nearest-even,
|
2003-01-09 01:06:57 +00:00
|
|
|
* but the integer code always rounds up (away from zero). Is it
|
|
|
|
* worth trying to be consistent?
|
|
|
|
*/
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-08-04 06:44:47 +00:00
|
|
|
if (*time >= INT64CONST(0))
|
|
|
|
{
|
|
|
|
*time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
|
|
|
|
* TimeScales[typmod]);
|
2001-10-04 15:14:22 +00:00
|
|
|
}
|
2002-08-04 06:44:47 +00:00
|
|
|
else
|
|
|
|
{
|
2003-01-09 01:06:57 +00:00
|
|
|
*time = - ((((- *time) + TimeOffsets[typmod]) / TimeScales[typmod])
|
|
|
|
* TimeScales[typmod]);
|
2002-08-04 06:44:47 +00:00
|
|
|
}
|
2003-01-09 01:06:57 +00:00
|
|
|
#else
|
|
|
|
*time = (rint(((double) *time) * TimeScales[typmod])
|
|
|
|
/ TimeScales[typmod]);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-10-03 05:29:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_eq(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 == time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_ne(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 != time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_lt(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 < time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_le(PG_FUNCTION_ARGS)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 <= time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_gt(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 > time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_ge(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_BOOL(time1 >= time2);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_cmp(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
if (time1 < time2)
|
|
|
|
PG_RETURN_INT32(-1);
|
|
|
|
if (time1 > time2)
|
|
|
|
PG_RETURN_INT32(1);
|
|
|
|
PG_RETURN_INT32(0);
|
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_larger(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_smaller(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time1 = PG_GETARG_TIMEADT(0);
|
|
|
|
TimeADT time2 = PG_GETARG_TIMEADT(1);
|
|
|
|
|
|
|
|
PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/* overlaps_time() --- implements the SQL92 OVERLAPS operator.
|
|
|
|
*
|
|
|
|
* Algorithm is per SQL92 spec. This is much harder than you'd think
|
|
|
|
* because the spec requires us to deliver a non-null answer in some cases
|
|
|
|
* where some of the inputs are null.
|
2000-03-14 23:06:59 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
overlaps_time(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* The arguments are TimeADT, but we leave them as generic Datums to
|
|
|
|
* avoid dereferencing nulls (TimeADT is pass-by-reference!)
|
2000-12-07 18:38:59 +00:00
|
|
|
*/
|
|
|
|
Datum ts1 = PG_GETARG_DATUM(0);
|
|
|
|
Datum te1 = PG_GETARG_DATUM(1);
|
|
|
|
Datum ts2 = PG_GETARG_DATUM(2);
|
|
|
|
Datum te2 = PG_GETARG_DATUM(3);
|
|
|
|
bool ts1IsNull = PG_ARGISNULL(0);
|
|
|
|
bool te1IsNull = PG_ARGISNULL(1);
|
|
|
|
bool ts2IsNull = PG_ARGISNULL(2);
|
|
|
|
bool te2IsNull = PG_ARGISNULL(3);
|
2000-06-09 01:11:16 +00:00
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
#define TIMEADT_GT(t1,t2) \
|
|
|
|
(DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
|
|
|
|
#define TIMEADT_LT(t1,t2) \
|
|
|
|
(DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/*
|
2001-03-22 04:01:46 +00:00
|
|
|
* If both endpoints of interval 1 are null, the result is null
|
|
|
|
* (unknown). If just one endpoint is null, take ts1 as the non-null
|
|
|
|
* one. Otherwise, take ts1 as the lesser endpoint.
|
2000-12-07 18:38:59 +00:00
|
|
|
*/
|
|
|
|
if (ts1IsNull)
|
|
|
|
{
|
|
|
|
if (te1IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
/* swap null for non-null */
|
2000-03-14 23:06:59 +00:00
|
|
|
ts1 = te1;
|
2000-12-07 18:38:59 +00:00
|
|
|
te1IsNull = true;
|
2000-03-14 23:06:59 +00:00
|
|
|
}
|
2000-12-07 18:38:59 +00:00
|
|
|
else if (!te1IsNull)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-12-07 18:38:59 +00:00
|
|
|
if (TIMEADT_GT(ts1, te1))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
Datum tt = ts1;
|
2000-12-07 18:38:59 +00:00
|
|
|
|
|
|
|
ts1 = te1;
|
|
|
|
te1 = tt;
|
|
|
|
}
|
|
|
|
}
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/* Likewise for interval 2. */
|
|
|
|
if (ts2IsNull)
|
|
|
|
{
|
|
|
|
if (te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
/* swap null for non-null */
|
2000-03-14 23:06:59 +00:00
|
|
|
ts2 = te2;
|
2000-12-07 18:38:59 +00:00
|
|
|
te2IsNull = true;
|
|
|
|
}
|
|
|
|
else if (!te2IsNull)
|
|
|
|
{
|
|
|
|
if (TIMEADT_GT(ts2, te2))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
Datum tt = ts2;
|
2000-12-07 18:38:59 +00:00
|
|
|
|
|
|
|
ts2 = te2;
|
|
|
|
te2 = tt;
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
}
|
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/*
|
|
|
|
* At this point neither ts1 nor ts2 is null, so we can consider three
|
|
|
|
* cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
|
|
|
|
*/
|
|
|
|
if (TIMEADT_GT(ts1, ts2))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* This case is ts1 < te2 OR te1 < te2, which may look redundant
|
2000-12-07 18:38:59 +00:00
|
|
|
* but in the presence of nulls it's not quite completely so.
|
|
|
|
*/
|
|
|
|
if (te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
if (TIMEADT_LT(ts1, te2))
|
|
|
|
PG_RETURN_BOOL(true);
|
|
|
|
if (te1IsNull)
|
|
|
|
PG_RETURN_NULL();
|
2001-03-22 04:01:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If te1 is not null then we had ts1 <= te1 above, and we just
|
2000-12-07 18:38:59 +00:00
|
|
|
* found ts1 >= te2, hence te1 >= te2.
|
|
|
|
*/
|
|
|
|
PG_RETURN_BOOL(false);
|
|
|
|
}
|
|
|
|
else if (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();
|
2001-03-22 04:01:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If te2 is not null then we had ts2 <= te2 above, and we just
|
2000-12-07 18:38:59 +00:00
|
|
|
* found ts2 >= te1, hence te2 >= te1.
|
|
|
|
*/
|
|
|
|
PG_RETURN_BOOL(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
|
|
|
|
* rather silly way of saying "true if both are nonnull, else
|
|
|
|
* null".
|
2000-12-07 18:38:59 +00:00
|
|
|
*/
|
|
|
|
if (te1IsNull || te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
PG_RETURN_BOOL(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef TIMEADT_GT
|
|
|
|
#undef TIMEADT_LT
|
2000-03-14 23:06:59 +00:00
|
|
|
}
|
1996-07-09 06:22:35 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* timestamp_time()
|
|
|
|
* Convert timestamp to time data type.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timestamp_time(PG_FUNCTION_ARGS)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
Timestamp timestamp = PG_GETARG_TIMESTAMP(0);
|
|
|
|
TimeADT result;
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
if (TIMESTAMP_NOT_FINITE(timestamp))
|
2001-09-28 08:09:14 +00:00
|
|
|
PG_RETURN_NULL();
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
|
2002-04-21 19:52:18 +00:00
|
|
|
elog(ERROR, "Unable to convert timestamp to time");
|
|
|
|
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-09-04 20:31:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Could also do this with time = (timestamp / 86400000000 *
|
|
|
|
* 86400000000) - timestamp;
|
2002-04-21 19:52:18 +00:00
|
|
|
*/
|
|
|
|
result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
|
|
|
|
* INT64CONST(1000000)) + fsec);
|
|
|
|
#else
|
|
|
|
result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timestamptz_time()
|
|
|
|
* Convert timestamptz to time data type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timestamptz_time(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
|
|
|
|
TimeADT result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
int tz;
|
|
|
|
fsec_t fsec;
|
|
|
|
char *tzn;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
if (TIMESTAMP_NOT_FINITE(timestamp))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
|
|
|
|
elog(ERROR, "Unable to convert timestamptz to time");
|
|
|
|
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-09-04 20:31:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Could also do this with time = (timestamp / 86400000000 *
|
|
|
|
* 86400000000) - timestamp;
|
2002-04-21 19:52:18 +00:00
|
|
|
*/
|
|
|
|
result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
|
|
|
|
* INT64CONST(1000000)) + fsec);
|
|
|
|
#else
|
2000-06-09 01:11:16 +00:00
|
|
|
result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
All regression tests pass except for rules.sql (unrelated).
Implement "date/time grand unification".
Transform datetime and timespan into timestamp and interval.
Deprecate datetime and timespan, though translate to new types in gram.y.
Transform all datetime and timespan catalog entries into new types.
Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
routines for all date/time types.
date.{h,c} now deals with date, time types.
timestamp.{h,c} now deals with timestamp, interval types.
nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.
2000-02-16 18:17:02 +00:00
|
|
|
/* datetime_timestamp()
|
|
|
|
* Convert date and time to timestamp data type.
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
datetime_timestamp(PG_FUNCTION_ARGS)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT date = PG_GETARG_DATEADT(0);
|
|
|
|
TimeADT time = PG_GETARG_TIMEADT(1);
|
|
|
|
Timestamp result;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp,
|
2001-03-22 04:01:46 +00:00
|
|
|
DateADTGetDatum(date)));
|
2000-06-09 01:11:16 +00:00
|
|
|
result += time;
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMESTAMP(result);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
|
|
|
/* time_interval()
|
|
|
|
* Convert time to interval data type.
|
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
time_interval(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeADT time = PG_GETARG_TIMEADT(0);
|
2000-03-14 23:06:59 +00:00
|
|
|
Interval *result;
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result = (Interval *) palloc(sizeof(Interval));
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result->time = time;
|
2000-03-14 23:06:59 +00:00
|
|
|
result->month = 0;
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_INTERVAL_P(result);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-12-03 14:51:12 +00:00
|
|
|
/* interval_time()
|
|
|
|
* Convert interval to time data type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
interval_time(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(0);
|
|
|
|
TimeADT result;
|
2002-04-21 19:52:18 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = span->time;
|
|
|
|
if ((result >= INT64CONST(86400000000))
|
|
|
|
|| (result <= INT64CONST(-86400000000)))
|
|
|
|
result -= (result / INT64CONST(1000000) * INT64CONST(1000000));
|
|
|
|
#else
|
2000-12-03 14:51:12 +00:00
|
|
|
Interval span1;
|
|
|
|
|
|
|
|
result = span->time;
|
|
|
|
TMODULO(result, span1.time, 86400e0);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-12-03 14:51:12 +00:00
|
|
|
|
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
/* 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));
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
result->time = (time1 - time2);
|
2001-09-28 08:09:14 +00:00
|
|
|
result->month = 0;
|
|
|
|
|
|
|
|
PG_RETURN_INTERVAL_P(result);
|
|
|
|
}
|
|
|
|
|
2000-12-03 14:51:12 +00:00
|
|
|
/* time_pl_interval()
|
|
|
|
* Add interval to time.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
time_pl_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeADT time = PG_GETARG_TIMEADT(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
TimeADT result;
|
2002-04-21 19:52:18 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (time + span->time);
|
|
|
|
result -= (result / INT64CONST(86400000000) * INT64CONST(86400000000));
|
|
|
|
if (result < INT64CONST(0))
|
|
|
|
result += INT64CONST(86400000000);
|
|
|
|
#else
|
2000-12-03 14:51:12 +00:00
|
|
|
TimeADT time1;
|
|
|
|
|
|
|
|
result = (time + span->time);
|
|
|
|
TMODULO(result, time1, 86400e0);
|
|
|
|
if (result < 0)
|
|
|
|
result += 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-12-03 14:51:12 +00:00
|
|
|
|
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* time_mi_interval()
|
|
|
|
* Subtract interval from time.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
time_mi_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeADT time = PG_GETARG_TIMEADT(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
TimeADT result;
|
2002-04-21 19:52:18 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (time - span->time);
|
|
|
|
result -= (result / INT64CONST(86400000000) * INT64CONST(86400000000));
|
|
|
|
if (result < INT64CONST(0))
|
|
|
|
result += INT64CONST(86400000000);
|
|
|
|
#else
|
2000-12-03 14:51:12 +00:00
|
|
|
TimeADT time1;
|
|
|
|
|
|
|
|
result = (time - span->time);
|
|
|
|
TMODULO(result, time1, 86400e0);
|
|
|
|
if (result < 0)
|
|
|
|
result += 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-12-03 14:51:12 +00:00
|
|
|
|
|
|
|
PG_RETURN_TIMEADT(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* interval_pl_time()
|
|
|
|
* Add time to interval.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
interval_pl_time(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Datum span = PG_GETARG_DATUM(0);
|
|
|
|
Datum time = PG_GETARG_DATUM(1);
|
|
|
|
|
|
|
|
return DirectFunctionCall2(time_pl_interval, time, span);
|
|
|
|
}
|
|
|
|
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-11-11 19:55:19 +00:00
|
|
|
/* time_text()
|
|
|
|
* Convert time to text data type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
time_text(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Input is a Time, but may as well leave it in Datum form */
|
|
|
|
Datum time = PG_GETARG_DATUM(0);
|
|
|
|
text *result;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
str = DatumGetCString(DirectFunctionCall1(time_out, time));
|
|
|
|
|
|
|
|
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_time()
|
|
|
|
* Convert text string to time.
|
|
|
|
* Text type is not null terminated, so use temporary string
|
|
|
|
* then call the standard input routine.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
text_time(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *str = PG_GETARG_TEXT_P(0);
|
|
|
|
int i;
|
|
|
|
char *sp,
|
|
|
|
*dp,
|
|
|
|
dstr[MAXDATELEN + 1];
|
|
|
|
|
|
|
|
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
|
|
|
|
elog(ERROR, "Bad time external representation (too long)");
|
|
|
|
|
|
|
|
sp = VARDATA(str);
|
|
|
|
dp = dstr;
|
|
|
|
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
*dp = '\0';
|
|
|
|
|
2001-10-04 14:49:57 +00:00
|
|
|
return DirectFunctionCall3(time_in,
|
|
|
|
CStringGetDatum(dstr),
|
|
|
|
ObjectIdGetDatum(InvalidOid),
|
|
|
|
Int32GetDatum(-1));
|
2000-11-11 19:55:19 +00:00
|
|
|
}
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
/* time_part()
|
|
|
|
* Extract specified field from time type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
time_part(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *units = PG_GETARG_TEXT_P(0);
|
|
|
|
TimeADT time = PG_GETARG_TIMEADT(1);
|
|
|
|
float8 result;
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
|
|
|
|
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
|
|
|
|
elog(ERROR, "TIME 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 == UNKNOWN_FIELD)
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
|
|
|
|
if (type == UNITS)
|
|
|
|
{
|
|
|
|
fsec_t fsec;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
|
|
|
|
time2tm(time, tm, &fsec);
|
|
|
|
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case DTK_MICROSEC:
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);
|
|
|
|
#else
|
|
|
|
result = ((tm->tm_sec + fsec) * 1000000);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MILLISEC:
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = ((tm->tm_sec * INT64CONST(1000))
|
|
|
|
+ (fsec / INT64CONST(1000)));
|
|
|
|
#else
|
|
|
|
result = ((tm->tm_sec + fsec) * 1000);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_SECOND:
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (tm->tm_sec + (fsec / INT64CONST(1000000)));
|
|
|
|
#else
|
|
|
|
result = (tm->tm_sec + fsec);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MINUTE:
|
|
|
|
result = tm->tm_min;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_HOUR:
|
|
|
|
result = tm->tm_hour;
|
|
|
|
break;
|
|
|
|
|
|
|
|
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:
|
|
|
|
default:
|
|
|
|
elog(ERROR, "TIME units '%s' not supported",
|
|
|
|
DatumGetCString(DirectFunctionCall1(textout,
|
|
|
|
PointerGetDatum(units))));
|
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((type == RESERV) && (val == DTK_EPOCH))
|
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (time / 1000000e0);
|
|
|
|
#else
|
|
|
|
result = time;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(ERROR, "TIME units '%s' not recognized",
|
|
|
|
DatumGetCString(DirectFunctionCall1(textout,
|
|
|
|
PointerGetDatum(units))));
|
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_FLOAT8(result);
|
|
|
|
}
|
|
|
|
|
2000-11-11 19:55:19 +00:00
|
|
|
|
2000-03-14 23:06:59 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* Time With Time Zone ADT
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
/* tm2timetz()
|
|
|
|
* Convert a tm structure to a time data type.
|
|
|
|
*/
|
2002-09-21 19:52:41 +00:00
|
|
|
static int
|
2002-04-21 19:52:18 +00:00
|
|
|
tm2timetz(struct tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result->time = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
|
|
|
|
* INT64CONST(1000000)) + fsec);
|
|
|
|
#else
|
|
|
|
result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
|
|
|
|
#endif
|
|
|
|
result->zone = tz;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_in(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
char *str = PG_GETARG_CSTRING(0);
|
2001-10-25 05:50:21 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 typmod = PG_GETARG_INT32(2);
|
|
|
|
TimeTzADT *result;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2000-03-14 23:06:59 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
int tz;
|
|
|
|
int nf;
|
|
|
|
char lowstr[MAXDATELEN + 1];
|
|
|
|
char *field[MAXDATEFIELDS];
|
|
|
|
int dtype;
|
|
|
|
int ftype[MAXDATEFIELDS];
|
|
|
|
|
2002-08-04 06:44:47 +00:00
|
|
|
if (strlen(str) >= sizeof(lowstr))
|
|
|
|
elog(ERROR, "Bad time with time zone"
|
|
|
|
" external representation (too long) '%s'", str);
|
|
|
|
|
2000-03-14 23:06:59 +00:00
|
|
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
2000-04-12 17:17:23 +00:00
|
|
|
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
2000-03-14 23:06:59 +00:00
|
|
|
elog(ERROR, "Bad time external representation '%s'", str);
|
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
2002-04-21 19:52:18 +00:00
|
|
|
tm2timetz(tm, fsec, tz, result);
|
2001-10-03 05:29:27 +00:00
|
|
|
AdjustTimeForTypmod(&(result->time), typmod);
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_out(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
|
2000-03-14 23:06:59 +00:00
|
|
|
char *result;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2000-03-14 23:06:59 +00:00
|
|
|
int tz;
|
|
|
|
char buf[MAXDATELEN + 1];
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
timetz2tm(time, tm, &fsec, &tz);
|
|
|
|
EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf);
|
|
|
|
|
|
|
|
result = pstrdup(buf);
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timetz2tm()
|
|
|
|
* Convert TIME WITH TIME ZONE data type to POSIX time structure.
|
|
|
|
*/
|
2002-09-21 19:52:41 +00:00
|
|
|
static int
|
2002-09-04 20:31:48 +00:00
|
|
|
timetz2tm(TimeTzADT *time, struct tm * tm, fsec_t *fsec, int *tzp)
|
2002-04-21 19:52:18 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2003-02-13 17:04:19 +00:00
|
|
|
int64 trem = time->time;
|
|
|
|
|
|
|
|
tm->tm_hour = (trem / INT64CONST(3600000000));
|
|
|
|
trem -= (tm->tm_hour * INT64CONST(3600000000));
|
|
|
|
tm->tm_min = (trem / INT64CONST(60000000));
|
|
|
|
trem -= (tm->tm_min * INT64CONST(60000000));
|
|
|
|
tm->tm_sec = (trem / INT64CONST(1000000));
|
|
|
|
*fsec = (trem - (tm->tm_sec * INT64CONST(1000000)));
|
2002-04-21 19:52:18 +00:00
|
|
|
#else
|
2003-02-13 17:04:19 +00:00
|
|
|
double trem = time->time;
|
2002-04-21 19:52:18 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
TMODULO(trem, tm->tm_hour, 3600e0);
|
|
|
|
TMODULO(trem, tm->tm_min, 60e0);
|
|
|
|
TMODULO(trem, tm->tm_sec, 1e0);
|
2002-04-21 19:52:18 +00:00
|
|
|
*fsec = trem;
|
|
|
|
#endif
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = time->zone;
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
return 0;
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-10-03 05:29:27 +00:00
|
|
|
/* timetz_scale()
|
|
|
|
* Adjust time type for specified scale factor.
|
|
|
|
* Used by PostgreSQL type system to stuff columns.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_scale(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
int32 typmod = PG_GETARG_INT32(1);
|
|
|
|
TimeTzADT *result;
|
|
|
|
|
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
|
|
|
|
|
|
|
result->time = time->time;
|
|
|
|
result->zone = time->zone;
|
|
|
|
|
|
|
|
AdjustTimeForTypmod(&(result->time), typmod);
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
}
|
|
|
|
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
static int
|
|
|
|
timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
|
|
|
|
{
|
|
|
|
double t1,
|
|
|
|
t2;
|
|
|
|
|
|
|
|
/* Primary sort is by true (GMT-equivalent) time */
|
|
|
|
t1 = time1->time + time1->zone;
|
|
|
|
t2 = time2->time + time2->zone;
|
|
|
|
|
|
|
|
if (t1 > t2)
|
|
|
|
return 1;
|
|
|
|
if (t1 < t2)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2001-09-28 08:09:14 +00:00
|
|
|
if (time1->zone > time2->zone)
|
|
|
|
return 1;
|
|
|
|
if (time1->zone < time2->zone)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
2001-05-03 19:00:37 +00:00
|
|
|
}
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_eq(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_ne(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_lt(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_le(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_gt(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_ge(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_cmp(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-06-09 01:11:16 +00:00
|
|
|
|
2001-05-03 19:00:37 +00:00
|
|
|
PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
|
2000-06-09 01:11:16 +00:00
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-19 03:55:01 +00:00
|
|
|
/*
|
|
|
|
* timetz, being an unusual size, needs a specialized hash function.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_hash(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *key = PG_GETARG_TIMETZADT_P(0);
|
2000-06-19 03:55:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Specify hash length as sizeof(double) + sizeof(int4), not as
|
|
|
|
* sizeof(TimeTzADT), so that any garbage pad bytes in the structure
|
|
|
|
* won't be included in the hash!
|
|
|
|
*/
|
2002-04-21 19:52:18 +00:00
|
|
|
return hash_any((unsigned char *) key, sizeof(key->time) + sizeof(key->zone));
|
2000-06-19 03:55:01 +00:00
|
|
|
}
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_larger(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-06-09 01:11:16 +00:00
|
|
|
|
|
|
|
if (DatumGetBool(DirectFunctionCall2(timetz_gt,
|
|
|
|
TimeTzADTPGetDatum(time1),
|
|
|
|
TimeTzADTPGetDatum(time2))))
|
|
|
|
PG_RETURN_TIMETZADT_P(time1);
|
|
|
|
PG_RETURN_TIMETZADT_P(time2);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
timetz_smaller(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
|
2000-06-09 01:11:16 +00:00
|
|
|
|
|
|
|
if (DatumGetBool(DirectFunctionCall2(timetz_lt,
|
|
|
|
TimeTzADTPGetDatum(time1),
|
|
|
|
TimeTzADTPGetDatum(time2))))
|
|
|
|
PG_RETURN_TIMETZADT_P(time1);
|
|
|
|
PG_RETURN_TIMETZADT_P(time2);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-12-03 14:51:12 +00:00
|
|
|
/* timetz_pl_interval()
|
|
|
|
* Add interval to timetz.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_pl_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
TimeTzADT *result;
|
2002-09-04 20:31:48 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifndef HAVE_INT64_TIMESTAMP
|
2000-12-03 14:51:12 +00:00
|
|
|
TimeTzADT time1;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-12-03 14:51:12 +00:00
|
|
|
|
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result->time = (time->time + span->time);
|
|
|
|
result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));
|
|
|
|
if (result->time < INT64CONST(0))
|
|
|
|
result->time += INT64CONST(86400000000);
|
|
|
|
#else
|
2000-12-03 14:51:12 +00:00
|
|
|
result->time = (time->time + span->time);
|
|
|
|
TMODULO(result->time, time1.time, 86400e0);
|
|
|
|
if (result->time < 0)
|
|
|
|
result->time += 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
|
|
|
|
2000-12-03 14:51:12 +00:00
|
|
|
result->zone = time->zone;
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timetz_mi_interval()
|
|
|
|
* Subtract interval from timetz.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_mi_interval(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
|
|
|
|
Interval *span = PG_GETARG_INTERVAL_P(1);
|
|
|
|
TimeTzADT *result;
|
2002-09-04 20:31:48 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifndef HAVE_INT64_TIMESTAMP
|
2000-12-03 14:51:12 +00:00
|
|
|
TimeTzADT time1;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2000-12-03 14:51:12 +00:00
|
|
|
|
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result->time = (time->time - span->time);
|
|
|
|
result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));
|
|
|
|
if (result->time < INT64CONST(0))
|
|
|
|
result->time += INT64CONST(86400000000);
|
|
|
|
#else
|
2000-12-03 14:51:12 +00:00
|
|
|
result->time = (time->time - span->time);
|
|
|
|
TMODULO(result->time, time1.time, 86400e0);
|
|
|
|
if (result->time < 0)
|
|
|
|
result->time += 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
|
|
|
|
2000-12-03 14:51:12 +00:00
|
|
|
result->zone = time->zone;
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
}
|
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/* overlaps_timetz() --- implements the SQL92 OVERLAPS operator.
|
|
|
|
*
|
|
|
|
* Algorithm is per SQL92 spec. This is much harder than you'd think
|
|
|
|
* because the spec requires us to deliver a non-null answer in some cases
|
|
|
|
* where some of the inputs are null.
|
2000-03-14 23:06:59 +00:00
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
|
|
|
overlaps_timetz(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* The arguments are TimeTzADT *, but we leave them as generic Datums
|
2000-12-07 18:38:59 +00:00
|
|
|
* for convenience of notation --- and to avoid dereferencing nulls.
|
2000-06-09 01:11:16 +00:00
|
|
|
*/
|
|
|
|
Datum ts1 = PG_GETARG_DATUM(0);
|
|
|
|
Datum te1 = PG_GETARG_DATUM(1);
|
|
|
|
Datum ts2 = PG_GETARG_DATUM(2);
|
|
|
|
Datum te2 = PG_GETARG_DATUM(3);
|
2000-12-07 18:38:59 +00:00
|
|
|
bool ts1IsNull = PG_ARGISNULL(0);
|
|
|
|
bool te1IsNull = PG_ARGISNULL(1);
|
|
|
|
bool ts2IsNull = PG_ARGISNULL(2);
|
|
|
|
bool te2IsNull = PG_ARGISNULL(3);
|
2000-06-09 01:11:16 +00:00
|
|
|
|
|
|
|
#define TIMETZ_GT(t1,t2) \
|
|
|
|
DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
|
|
|
|
#define TIMETZ_LT(t1,t2) \
|
|
|
|
DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
|
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/*
|
2001-03-22 04:01:46 +00:00
|
|
|
* If both endpoints of interval 1 are null, the result is null
|
|
|
|
* (unknown). If just one endpoint is null, take ts1 as the non-null
|
|
|
|
* one. Otherwise, take ts1 as the lesser endpoint.
|
2000-12-07 18:38:59 +00:00
|
|
|
*/
|
|
|
|
if (ts1IsNull)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-12-07 18:38:59 +00:00
|
|
|
if (te1IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
/* swap null for non-null */
|
2000-03-14 23:06:59 +00:00
|
|
|
ts1 = te1;
|
2000-12-07 18:38:59 +00:00
|
|
|
te1IsNull = true;
|
2000-03-14 23:06:59 +00:00
|
|
|
}
|
2000-12-07 18:38:59 +00:00
|
|
|
else if (!te1IsNull)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-12-07 18:38:59 +00:00
|
|
|
if (TIMETZ_GT(ts1, te1))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
Datum tt = ts1;
|
2000-12-07 18:38:59 +00:00
|
|
|
|
|
|
|
ts1 = te1;
|
|
|
|
te1 = tt;
|
|
|
|
}
|
|
|
|
}
|
2000-04-12 17:17:23 +00:00
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/* Likewise for interval 2. */
|
|
|
|
if (ts2IsNull)
|
|
|
|
{
|
|
|
|
if (te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
/* swap null for non-null */
|
2000-03-14 23:06:59 +00:00
|
|
|
ts2 = te2;
|
2000-12-07 18:38:59 +00:00
|
|
|
te2IsNull = true;
|
|
|
|
}
|
|
|
|
else if (!te2IsNull)
|
|
|
|
{
|
|
|
|
if (TIMETZ_GT(ts2, te2))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
Datum tt = ts2;
|
2000-12-07 18:38:59 +00:00
|
|
|
|
|
|
|
ts2 = te2;
|
|
|
|
te2 = tt;
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
}
|
|
|
|
|
2000-12-07 18:38:59 +00:00
|
|
|
/*
|
|
|
|
* At this point neither ts1 nor ts2 is null, so we can consider three
|
|
|
|
* cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
|
|
|
|
*/
|
|
|
|
if (TIMETZ_GT(ts1, ts2))
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* This case is ts1 < te2 OR te1 < te2, which may look redundant
|
2000-12-07 18:38:59 +00:00
|
|
|
* but in the presence of nulls it's not quite completely so.
|
|
|
|
*/
|
|
|
|
if (te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
if (TIMETZ_LT(ts1, te2))
|
|
|
|
PG_RETURN_BOOL(true);
|
|
|
|
if (te1IsNull)
|
|
|
|
PG_RETURN_NULL();
|
2001-03-22 04:01:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If te1 is not null then we had ts1 <= te1 above, and we just
|
2000-12-07 18:38:59 +00:00
|
|
|
* found ts1 >= te2, hence te1 >= te2.
|
|
|
|
*/
|
|
|
|
PG_RETURN_BOOL(false);
|
|
|
|
}
|
|
|
|
else if (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();
|
2001-03-22 04:01:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If te2 is not null then we had ts2 <= te2 above, and we just
|
2000-12-07 18:38:59 +00:00
|
|
|
* found ts2 >= te1, hence te2 >= te1.
|
|
|
|
*/
|
|
|
|
PG_RETURN_BOOL(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-03-22 04:01:46 +00:00
|
|
|
/*
|
|
|
|
* For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
|
|
|
|
* rather silly way of saying "true if both are nonnull, else
|
|
|
|
* null".
|
2000-12-07 18:38:59 +00:00
|
|
|
*/
|
|
|
|
if (te1IsNull || te2IsNull)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
PG_RETURN_BOOL(true);
|
|
|
|
}
|
2000-06-09 01:11:16 +00:00
|
|
|
|
|
|
|
#undef TIMETZ_GT
|
|
|
|
#undef TIMETZ_LT
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
|
|
|
|
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;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2001-09-28 08:09:14 +00:00
|
|
|
int tz;
|
|
|
|
|
2002-06-11 13:40:53 +00:00
|
|
|
GetCurrentDateTime(tm);
|
2002-04-21 19:52:18 +00:00
|
|
|
time2tm(time, tm, &fsec);
|
2001-09-28 08:09:14 +00:00
|
|
|
tz = DetermineLocalTimeZone(tm);
|
|
|
|
|
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
|
|
|
|
|
|
|
result->time = time;
|
|
|
|
result->zone = tz;
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* timestamptz_timetz()
|
2000-03-14 23:06:59 +00:00
|
|
|
* Convert timestamp to timetz data type.
|
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
2001-09-28 08:09:14 +00:00
|
|
|
timestamptz_timetz(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2001-10-25 05:50:21 +00:00
|
|
|
TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
|
2000-04-12 17:17:23 +00:00
|
|
|
TimeTzADT *result;
|
2000-03-14 23:06:59 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
int tz;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2000-03-14 23:06:59 +00:00
|
|
|
char *tzn;
|
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
if (TIMESTAMP_NOT_FINITE(timestamp))
|
2001-09-28 08:09:14 +00:00
|
|
|
PG_RETURN_NULL();
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
|
2002-04-21 19:52:18 +00:00
|
|
|
elog(ERROR, "Unable to convert timestamptz to timetz");
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
tm2timetz(tm, fsec, tz, result);
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
}
|
2000-03-14 23:06:59 +00:00
|
|
|
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
/* datetimetz_timestamptz()
|
|
|
|
* Convert date and timetz to timestamp with time zone data type.
|
2000-03-14 23:06:59 +00:00
|
|
|
* Timestamp is stored in GMT, so add the time zone
|
|
|
|
* stored with the timetz to the result.
|
|
|
|
* - thomas 2000-03-10
|
|
|
|
*/
|
2000-06-09 01:11:16 +00:00
|
|
|
Datum
|
2001-09-28 08:09:14 +00:00
|
|
|
datetimetz_timestamptz(PG_FUNCTION_ARGS)
|
2000-03-14 23:06:59 +00:00
|
|
|
{
|
2000-06-09 01:11:16 +00:00
|
|
|
DateADT date = PG_GETARG_DATEADT(0);
|
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
|
2001-10-25 05:50:21 +00:00
|
|
|
TimestampTz result;
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (((date * INT64CONST(86400000000)) + time->time)
|
2002-09-04 20:31:48 +00:00
|
|
|
+ (time->zone * INT64CONST(1000000)));
|
2002-04-21 19:52:18 +00:00
|
|
|
#else
|
|
|
|
result = (((date * 86400.0) + time->time) + time->zone);
|
|
|
|
#endif
|
2000-03-14 23:06:59 +00:00
|
|
|
|
2000-06-09 01:11:16 +00:00
|
|
|
PG_RETURN_TIMESTAMP(result);
|
|
|
|
}
|
2000-11-11 19:55:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* timetz_text()
|
|
|
|
* Convert timetz to text data type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_text(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Input is a Timetz, but may as well leave it in Datum form */
|
|
|
|
Datum timetz = PG_GETARG_DATUM(0);
|
|
|
|
text *result;
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
|
|
|
|
|
|
|
|
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_timetz()
|
|
|
|
* Convert text string to timetz.
|
|
|
|
* Text type is not null terminated, so use temporary string
|
|
|
|
* then call the standard input routine.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
text_timetz(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *str = PG_GETARG_TEXT_P(0);
|
|
|
|
int i;
|
|
|
|
char *sp,
|
|
|
|
*dp,
|
|
|
|
dstr[MAXDATELEN + 1];
|
|
|
|
|
|
|
|
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
|
|
|
|
elog(ERROR, "Bad timetz external representation (too long)");
|
|
|
|
|
|
|
|
sp = VARDATA(str);
|
|
|
|
dp = dstr;
|
|
|
|
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
*dp = '\0';
|
|
|
|
|
2001-10-04 14:49:57 +00:00
|
|
|
return DirectFunctionCall3(timetz_in,
|
|
|
|
CStringGetDatum(dstr),
|
|
|
|
ObjectIdGetDatum(InvalidOid),
|
|
|
|
Int32GetDatum(-1));
|
2000-11-11 19:55:19 +00:00
|
|
|
}
|
2001-09-28 08:09:14 +00:00
|
|
|
|
2001-10-18 17:30:21 +00:00
|
|
|
/* timetz_part()
|
|
|
|
* Extract specified field from time type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
timetz_part(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
text *units = PG_GETARG_TEXT_P(0);
|
|
|
|
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
|
|
|
|
float8 result;
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
|
|
|
|
if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
|
|
|
|
elog(ERROR, "TIMETZ units '%s' not recognized",
|
|
|
|
DatumGetCString(DirectFunctionCall1(textout,
|
2001-10-25 05:50:21 +00:00
|
|
|
PointerGetDatum(units))));
|
2001-10-18 17:30:21 +00:00
|
|
|
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 == UNKNOWN_FIELD)
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
|
|
|
|
if (type == UNITS)
|
|
|
|
{
|
|
|
|
double dummy;
|
|
|
|
int tz;
|
2002-04-21 19:52:18 +00:00
|
|
|
fsec_t fsec;
|
2001-10-18 17:30:21 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
timetz2tm(time, tm, &fsec, &tz);
|
2001-10-18 17:30:21 +00:00
|
|
|
|
|
|
|
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:
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);
|
|
|
|
#else
|
2001-10-18 17:30:21 +00:00
|
|
|
result = ((tm->tm_sec + fsec) * 1000000);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-10-18 17:30:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MILLISEC:
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = ((tm->tm_sec * INT64CONST(1000))
|
|
|
|
+ (fsec / INT64CONST(1000)));
|
|
|
|
#else
|
2001-10-18 17:30:21 +00:00
|
|
|
result = ((tm->tm_sec + fsec) * 1000);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-10-18 17:30:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_SECOND:
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = (tm->tm_sec + (fsec / INT64CONST(1000000)));
|
|
|
|
#else
|
2001-10-18 17:30:21 +00:00
|
|
|
result = (tm->tm_sec + fsec);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-10-18 17:30:21 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MINUTE:
|
|
|
|
result = tm->tm_min;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_HOUR:
|
|
|
|
result = tm->tm_hour;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DAY:
|
|
|
|
case DTK_MONTH:
|
|
|
|
case DTK_QUARTER:
|
|
|
|
case DTK_YEAR:
|
|
|
|
case DTK_DECADE:
|
|
|
|
case DTK_CENTURY:
|
|
|
|
case DTK_MILLENNIUM:
|
|
|
|
default:
|
|
|
|
elog(ERROR, "TIMETZ units '%s' not supported",
|
|
|
|
DatumGetCString(DirectFunctionCall1(textout,
|
2001-10-25 05:50:21 +00:00
|
|
|
PointerGetDatum(units))));
|
2001-10-18 17:30:21 +00:00
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((type == RESERV) && (val == DTK_EPOCH))
|
2002-04-21 19:52:18 +00:00
|
|
|
{
|
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
result = ((time->time / 1000000e0) - time->zone);
|
|
|
|
#else
|
|
|
|
result = (time->time - time->zone);
|
|
|
|
#endif
|
|
|
|
}
|
2001-10-18 17:30:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(ERROR, "TIMETZ units '%s' not recognized",
|
|
|
|
DatumGetCString(DirectFunctionCall1(textout,
|
2001-10-25 05:50:21 +00:00
|
|
|
PointerGetDatum(units))));
|
2001-10-18 17:30:21 +00:00
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_FLOAT8(result);
|
|
|
|
}
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
/* 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;
|
|
|
|
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;
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-11-21 23:31:20 +00:00
|
|
|
result->time = time->time + ((time->zone - tz) * INT64CONST(1000000));
|
|
|
|
while (result->time < INT64CONST(0))
|
2002-04-21 19:52:18 +00:00
|
|
|
result->time += INT64CONST(86400000000);
|
2002-11-21 23:31:20 +00:00
|
|
|
while (result->time >= INT64CONST(86400000000))
|
|
|
|
result->time -= INT64CONST(86400000000);
|
2002-04-21 19:52:18 +00:00
|
|
|
#else
|
2002-11-21 23:31:20 +00:00
|
|
|
result->time = time->time + (time->zone - tz);
|
|
|
|
while (result->time < 0)
|
2001-09-28 08:09:14 +00:00
|
|
|
result->time += 86400;
|
2002-11-21 23:31:20 +00:00
|
|
|
while (result->time >= 86400)
|
|
|
|
result->time -= 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
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;
|
|
|
|
int tz;
|
|
|
|
|
|
|
|
if (zone->month != 0)
|
|
|
|
elog(ERROR, "INTERVAL time zone '%s' not legal (month specified)",
|
|
|
|
DatumGetCString(DirectFunctionCall1(interval_out,
|
|
|
|
PointerGetDatum(zone))));
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
|
|
tz = -(zone->time / INT64CONST(1000000));
|
|
|
|
#else
|
2001-09-28 08:09:14 +00:00
|
|
|
tz = -(zone->time);
|
2002-04-21 19:52:18 +00:00
|
|
|
#endif
|
2001-09-28 08:09:14 +00:00
|
|
|
|
|
|
|
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
|
|
|
|
2002-04-21 19:52:18 +00:00
|
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
2002-11-21 23:31:20 +00:00
|
|
|
result->time = time->time + ((time->zone - tz) * INT64CONST(1000000));
|
2002-04-21 19:52:18 +00:00
|
|
|
while (result->time < INT64CONST(0))
|
|
|
|
result->time += INT64CONST(86400000000);
|
|
|
|
while (result->time >= INT64CONST(86400000000))
|
|
|
|
result->time -= INT64CONST(86400000000);
|
|
|
|
#else
|
2002-11-21 23:31:20 +00:00
|
|
|
result->time = time->time + (time->zone - tz);
|
2002-04-21 19:52:18 +00:00
|
|
|
while (result->time < 0)
|
2001-09-28 08:09:14 +00:00
|
|
|
result->time += 86400;
|
2002-04-21 19:52:18 +00:00
|
|
|
while (result->time >= 86400)
|
|
|
|
result->time -= 86400;
|
|
|
|
#endif
|
|
|
|
|
2001-09-28 08:09:14 +00:00
|
|
|
result->zone = tz;
|
|
|
|
|
|
|
|
PG_RETURN_TIMETZADT_P(result);
|
|
|
|
} /* timetz_izone() */
|