Constructors for interval, timestamp, timestamptz
Author: Pavel Stěhule, editorialized somewhat by Álvaro Herrera Reviewed-by: Tomáš Vondra, Marko Tiikkaja With input from Fabrízio de Royes Mello, Jim Nasby
This commit is contained in:
parent
af2543e884
commit
84df54b22e
|
@ -6720,6 +6720,32 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
|||
<entry><literal>2013-07-15</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>
|
||||
<indexterm>
|
||||
<primary>make_interval</primary>
|
||||
</indexterm>
|
||||
<literal>
|
||||
<function>
|
||||
make_interval(<parameter>years</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>months</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>weeks</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>days</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>hours</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>mins</parameter> <type>int</type> DEFAULT 0,
|
||||
<parameter>secs</parameter> <type>double precision</type> DEFAULT 0.0)
|
||||
</function>
|
||||
</literal>
|
||||
</entry>
|
||||
<entry><type>interval</type></entry>
|
||||
<entry>
|
||||
Create interval from years, months, weeks, days, hours, minutes and
|
||||
seconds fields
|
||||
</entry>
|
||||
<entry><literal>make_interval(days := 10)</literal></entry>
|
||||
<entry><literal>10 days</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>
|
||||
<indexterm>
|
||||
|
@ -6741,6 +6767,57 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
|||
<entry><literal>08:15:23.5</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>
|
||||
<indexterm>
|
||||
<primary>make_timestamp</primary>
|
||||
</indexterm>
|
||||
<literal>
|
||||
<function>
|
||||
make_timestamp(<parameter>year</parameter> <type>int</type>,
|
||||
<parameter>month</parameter> <type>int</type>,
|
||||
<parameter>day</parameter> <type>int</type>,
|
||||
<parameter>hour</parameter> <type>int</type>,
|
||||
<parameter>min</parameter> <type>int</type>,
|
||||
<parameter>sec</parameter> <type>double precision</type>)
|
||||
</function>
|
||||
</literal>
|
||||
</entry>
|
||||
<entry><type>timestamp</type></entry>
|
||||
<entry>
|
||||
Create timestamp from year, month, day, hour, minute and seconds fields
|
||||
</entry>
|
||||
<entry><literal>make_timestamp(1-23, 7, 15, 8, 15, 23.5)</literal></entry>
|
||||
<entry><literal>2013-07-15 08:15:23.5</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>
|
||||
<indexterm>
|
||||
<primary>make_timestamptz</primary>
|
||||
</indexterm>
|
||||
<literal>
|
||||
<function>
|
||||
make_timestamptz(<parameter>year</parameter> <type>int</type>,
|
||||
<parameter>month</parameter> <type>int</type>,
|
||||
<parameter>day</parameter> <type>int</type>,
|
||||
<parameter>hour</parameter> <type>int</type>,
|
||||
<parameter>min</parameter> <type>int</type>,
|
||||
<parameter>sec</parameter> <type>double precision</type>,
|
||||
<optional> <parameter>timezone</parameter> <type>text</type> </optional>)
|
||||
</function>
|
||||
</literal>
|
||||
</entry>
|
||||
<entry><type>timestamp with time zone</type></entry>
|
||||
<entry>
|
||||
Create timestamp with time zone from year, month, day, hour, minute
|
||||
and seconds fields. When <parameter>timezone</parameter> is not specified,
|
||||
then current time zone is used.
|
||||
</entry>
|
||||
<entry><literal>make_timestamp(1-23, 7, 15, 8, 15, 23.5)</literal></entry>
|
||||
<entry><literal>2013-07-15 08:15:23.5+01</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>
|
||||
<indexterm>
|
||||
|
|
|
@ -856,3 +856,12 @@ RETURNS SETOF RECORD
|
|||
LANGUAGE INTERNAL
|
||||
VOLATILE ROWS 1000 COST 1000
|
||||
AS 'pg_logical_slot_peek_binary_changes';
|
||||
|
||||
CREATE OR REPLACE FUNCTION
|
||||
make_interval(years int4 DEFAULT 0, months int4 DEFAULT 0, weeks int4 DEFAULT 0,
|
||||
days int4 DEFAULT 0, hours int4 DEFAULT 0, mins int4 DEFAULT 0,
|
||||
secs double precision DEFAULT 0.0)
|
||||
RETURNS interval
|
||||
LANGUAGE INTERNAL
|
||||
STRICT IMMUTABLE
|
||||
AS 'make_interval';
|
||||
|
|
|
@ -40,7 +40,6 @@ static int DecodeNumberField(int len, char *str,
|
|||
struct pg_tm * tm, fsec_t *fsec, bool *is2digits);
|
||||
static int DecodeTime(char *str, int fmask, int range,
|
||||
int *tmask, struct pg_tm * tm, fsec_t *fsec);
|
||||
static int DecodeTimezone(char *str, int *tzp);
|
||||
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
||||
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
||||
struct pg_tm * tm);
|
||||
|
@ -2075,6 +2074,9 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||
else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
|
||||
tm->tm_hour += HOURS_PER_DAY / 2;
|
||||
|
||||
/*
|
||||
* This should match the checks in make_timestamp_internal
|
||||
*/
|
||||
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
|
||||
tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
|
||||
tm->tm_hour > HOURS_PER_DAY ||
|
||||
|
@ -2707,7 +2709,7 @@ DecodeNumberField(int len, char *str, int fmask,
|
|||
*
|
||||
* NB: this must *not* ereport on failure; see commands/variable.c.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
DecodeTimezone(char *str, int *tzp)
|
||||
{
|
||||
int tz;
|
||||
|
|
|
@ -483,6 +483,234 @@ timestamptz_in(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_TIMESTAMPTZ(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to parse a timezone specification, and return its timezone offset value
|
||||
* if it's acceptable. Otherwise, an error is thrown.
|
||||
*/
|
||||
static int
|
||||
parse_sane_timezone(struct pg_tm *tm, text *zone)
|
||||
{
|
||||
char tzname[TZ_STRLEN_MAX + 1];
|
||||
int rt;
|
||||
int tz;
|
||||
|
||||
text_to_cstring_buffer(zone, tzname, sizeof(tzname));
|
||||
|
||||
/*
|
||||
* Look up the requested timezone. First we try to interpret it as a
|
||||
* numeric timezone specification; if DecodeTimezone decides it doesn't
|
||||
* like the format, we look in the date token table (to handle cases like
|
||||
* "EST"), and if that also fails, we look in the timezone database (to
|
||||
* handle cases like "America/New_York"). (This matches the order in
|
||||
* which timestamp input checks the cases; it's important because the
|
||||
* timezone database unwisely uses a few zone names that are identical to
|
||||
* offset abbreviations.)
|
||||
*
|
||||
* Note pg_tzset happily parses numeric input that DecodeTimezone would
|
||||
* reject. To avoid having it accept input that would otherwise be seen
|
||||
* as invalid, it's enough to disallow having a digit in the first
|
||||
* position of our input string.
|
||||
*/
|
||||
if (isdigit(*tzname))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid input syntax for numeric time zone: \"%s\"",
|
||||
tzname),
|
||||
errhint("Numeric time zones must have \"-\" or \"+\" as first character.")));
|
||||
|
||||
rt = DecodeTimezone(tzname, &tz);
|
||||
if (rt != 0)
|
||||
{
|
||||
char *lowzone;
|
||||
int type,
|
||||
val;
|
||||
|
||||
if (rt == DTERR_TZDISP_OVERFLOW)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("numeric time zone \"%s\" out of range", tzname)));
|
||||
else if (rt != DTERR_BAD_FORMAT)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("time zone \"%s\" not recognized", tzname)));
|
||||
|
||||
lowzone = downcase_truncate_identifier(tzname,
|
||||
strlen(tzname),
|
||||
false);
|
||||
type = DecodeSpecial(0, lowzone, &val);
|
||||
|
||||
if (type == TZ || type == DTZ)
|
||||
tz = val * MINS_PER_HOUR;
|
||||
else
|
||||
{
|
||||
pg_tz *tzp;
|
||||
|
||||
tzp = pg_tzset(tzname);
|
||||
|
||||
if (tzp)
|
||||
tz = DetermineTimeZoneOffset(tm, tzp);
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("time zone \"%s\" not recognized", tzname)));
|
||||
}
|
||||
}
|
||||
|
||||
return tz;
|
||||
}
|
||||
|
||||
/*
|
||||
* make_timestamp_internal
|
||||
* workhorse for make_timestamp and make_timestamptz
|
||||
*/
|
||||
static Timestamp
|
||||
make_timestamp_internal(int year, int month, int day,
|
||||
int hour, int min, double sec)
|
||||
{
|
||||
struct pg_tm tm;
|
||||
TimeOffset date;
|
||||
TimeOffset time;
|
||||
int dterr;
|
||||
Timestamp result;
|
||||
|
||||
tm.tm_year = year;
|
||||
tm.tm_mon = month;
|
||||
tm.tm_mday = day;
|
||||
|
||||
/*
|
||||
* Note: we'll reject zero or negative year values. Perhaps negatives
|
||||
* should be allowed to represent BC years?
|
||||
*/
|
||||
dterr = ValidateDate(DTK_DATE_M, false, false, false, &tm);
|
||||
|
||||
if (dterr != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||
errmsg("date field value out of range: %d-%02d-%02d",
|
||||
year, month, day)));
|
||||
|
||||
if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("date out of range: %d-%02d-%02d",
|
||||
year, month, day)));
|
||||
|
||||
date = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
|
||||
|
||||
/* This should match the checks in DecodeTimeOnly */
|
||||
if (hour < 0 || min < 0 || min > MINS_PER_HOUR - 1 ||
|
||||
sec < 0 || sec > SECS_PER_MINUTE ||
|
||||
hour > HOURS_PER_DAY ||
|
||||
/* test for > 24:00:00 */
|
||||
(hour == HOURS_PER_DAY && (min > 0 || sec > 0)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||
errmsg("time field value out of range: %d:%02d:%02g",
|
||||
hour, min, sec)));
|
||||
|
||||
/* This should match tm2time */
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
|
||||
* USECS_PER_SEC) + rint(sec * USECS_PER_SEC);
|
||||
|
||||
result = date * USECS_PER_DAY + time;
|
||||
/* check for major overflow */
|
||||
if ((result - time) / USECS_PER_DAY != date)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
|
||||
year, month, day,
|
||||
hour, min, sec)));
|
||||
|
||||
/* check for just-barely overflow (okay except time-of-day wraps) */
|
||||
/* caution: we want to allow 1999-12-31 24:00:00 */
|
||||
if ((result < 0 && date > 0) ||
|
||||
(result > 0 && date < -1))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
|
||||
year, month, day,
|
||||
hour, min, sec)));
|
||||
#else
|
||||
time = ((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE) + sec;
|
||||
result = date * SECS_PER_DAY + time;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* make_timestamp() - timestamp constructor
|
||||
*/
|
||||
Datum
|
||||
make_timestamp(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 year = PG_GETARG_INT32(0);
|
||||
int32 month = PG_GETARG_INT32(1);
|
||||
int32 mday = PG_GETARG_INT32(2);
|
||||
int32 hour = PG_GETARG_INT32(3);
|
||||
int32 min = PG_GETARG_INT32(4);
|
||||
float8 sec = PG_GETARG_FLOAT8(5);
|
||||
Timestamp result;
|
||||
|
||||
result = make_timestamp_internal(year, month, mday,
|
||||
hour, min, sec);
|
||||
|
||||
PG_RETURN_TIMESTAMP(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_timestamptz() - timestamp with time zone constructor
|
||||
*/
|
||||
Datum
|
||||
make_timestamptz(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 year = PG_GETARG_INT32(0);
|
||||
int32 month = PG_GETARG_INT32(1);
|
||||
int32 mday = PG_GETARG_INT32(2);
|
||||
int32 hour = PG_GETARG_INT32(3);
|
||||
int32 min = PG_GETARG_INT32(4);
|
||||
float8 sec = PG_GETARG_FLOAT8(5);
|
||||
Timestamp result;
|
||||
|
||||
result = make_timestamp_internal(year, month, mday,
|
||||
hour, min, sec);
|
||||
|
||||
PG_RETURN_TIMESTAMPTZ(timestamp2timestamptz(result));
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a timestamp with time zone.
|
||||
* As above, but the time zone is specified as seventh argument.
|
||||
*/
|
||||
Datum
|
||||
make_timestamptz_at_timezone(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 year = PG_GETARG_INT32(0);
|
||||
int32 month = PG_GETARG_INT32(1);
|
||||
int32 mday = PG_GETARG_INT32(2);
|
||||
int32 hour = PG_GETARG_INT32(3);
|
||||
int32 min = PG_GETARG_INT32(4);
|
||||
float8 sec = PG_GETARG_FLOAT8(5);
|
||||
text *zone = PG_GETARG_TEXT_PP(6);
|
||||
Timestamp timestamp;
|
||||
struct pg_tm tt;
|
||||
int tz;
|
||||
fsec_t fsec;
|
||||
|
||||
timestamp = make_timestamp_internal(year, month, mday,
|
||||
hour, min, sec);
|
||||
|
||||
if (timestamp2tm(timestamp, NULL, &tt, &fsec, NULL, NULL) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
tz = parse_sane_timezone(&tt, zone);
|
||||
|
||||
PG_RETURN_TIMESTAMPTZ((TimestampTz) dt2local(timestamp, -tz));
|
||||
}
|
||||
|
||||
/* timestamptz_out()
|
||||
* Convert a timestamp to external form.
|
||||
*/
|
||||
|
@ -1220,6 +1448,42 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make_interval - numeric Interval constructor
|
||||
*/
|
||||
Datum
|
||||
make_interval(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 years = PG_GETARG_INT32(0);
|
||||
int32 months = PG_GETARG_INT32(1);
|
||||
int32 weeks = PG_GETARG_INT32(2);
|
||||
int32 days = PG_GETARG_INT32(3);
|
||||
int32 hours = PG_GETARG_INT32(4);
|
||||
int32 mins = PG_GETARG_INT32(5);
|
||||
double secs = PG_GETARG_FLOAT8(6);
|
||||
Interval *result;
|
||||
|
||||
result = (Interval *) palloc(sizeof(Interval));
|
||||
result->month = years * MONTHS_PER_YEAR + months;
|
||||
result->day = weeks * 7 + days;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time = ((((hours * INT64CONST(60)) +
|
||||
mins) * INT64CONST(60)) +
|
||||
secs) * USECS_PER_SEC;
|
||||
#else
|
||||
result->time = (((hours * (double) MINS_PER_HOUR) +
|
||||
mins) * (double) SECS_PER_MINUTE) +
|
||||
secs;
|
||||
#endif
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* this is a no-op for negative typmods */
|
||||
AdjustIntervalForTypmod(result, -1);
|
||||
#endif
|
||||
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
/* EncodeSpecialTimestamp()
|
||||
* Convert reserved timestamp data type to string.
|
||||
|
|
|
@ -53,6 +53,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201403032
|
||||
#define CATALOG_VERSION_NO 201403041
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4718,11 +4718,19 @@ DESCR("int8range constructor");
|
|||
DATA(insert OID = 3946 ( int8range PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 3926 "20 20 25" _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ ));
|
||||
DESCR("int8range constructor");
|
||||
|
||||
/* date, time constructors */
|
||||
/* date, time, timestamp constructors */
|
||||
DATA(insert OID = 3846 ( make_date PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1082 "23 23 23" _null_ _null_ "{year,month,day}" _null_ make_date _null_ _null_ _null_ ));
|
||||
DESCR("construct date");
|
||||
DATA(insert OID = 3847 ( make_time PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1083 "23 23 701" _null_ _null_ "{hour,min,sec}" _null_ make_time _null_ _null_ _null_ ));
|
||||
DESCR("construct time");
|
||||
DATA(insert OID = 3461 ( make_timestamp PGNSP PGUID 12 1 0 0 0 f f f f t f i 6 0 1114 "23 23 23 23 23 701" _null_ _null_ "{year,month,mday,hour,min,sec}" _null_ make_timestamp _null_ _null_ _null_ ));
|
||||
DESCR("construct timestamp");
|
||||
DATA(insert OID = 3462 ( make_timestamptz PGNSP PGUID 12 1 0 0 0 f f f f t f s 6 0 1184 "23 23 23 23 23 701" _null_ _null_ "{year,month,mday,hour,min,sec}" _null_ make_timestamptz _null_ _null_ _null_ ));
|
||||
DESCR("construct timestamp with time zone");
|
||||
DATA(insert OID = 3463 ( make_timestamptz PGNSP PGUID 12 1 0 0 0 f f f f t f s 7 0 1184 "23 23 23 23 23 701 25" _null_ _null_ "{year,month,mday,hour,min,sec,timezone}" _null_ make_timestamptz_at_timezone _null_ _null_ _null_ ));
|
||||
DESCR("construct timestamp with time zone");
|
||||
DATA(insert OID = 3464 ( make_interval PGNSP PGUID 12 1 0 0 0 f f f f t f i 7 0 1186 "23 23 23 23 23 23 701" _null_ _null_ "{years,months,weeks,days,hours,mins,secs}" _null_ make_interval _null_ _null_ _null_ ));
|
||||
DESCR("construct interval");
|
||||
|
||||
/* spgist support functions */
|
||||
DATA(insert OID = 4001 ( spggettuple PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ spggettuple _null_ _null_ _null_ ));
|
||||
|
|
|
@ -283,6 +283,7 @@ extern int ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
|
|||
extern int DecodeDateTime(char **field, int *ftype,
|
||||
int nf, int *dtype,
|
||||
struct pg_tm * tm, fsec_t *fsec, int *tzp);
|
||||
extern int DecodeTimezone(char *str, int *tzp);
|
||||
extern int DecodeTimeOnly(char **field, int *ftype,
|
||||
int nf, int *dtype,
|
||||
struct pg_tm * tm, fsec_t *fsec, int *tzp);
|
||||
|
|
|
@ -121,6 +121,10 @@ extern Datum timestamp_gt_timestamptz(PG_FUNCTION_ARGS);
|
|||
extern Datum timestamp_ge_timestamptz(PG_FUNCTION_ARGS);
|
||||
extern Datum timestamp_cmp_timestamptz(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum make_timestamp(PG_FUNCTION_ARGS);
|
||||
extern Datum make_timestamptz(PG_FUNCTION_ARGS);
|
||||
extern Datum make_timestamptz_at_timezone(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum timestamptz_eq_timestamp(PG_FUNCTION_ARGS);
|
||||
extern Datum timestamptz_ne_timestamp(PG_FUNCTION_ARGS);
|
||||
extern Datum timestamptz_lt_timestamp(PG_FUNCTION_ARGS);
|
||||
|
@ -151,6 +155,7 @@ extern Datum interval_larger(PG_FUNCTION_ARGS);
|
|||
extern Datum interval_justify_interval(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_justify_hours(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_justify_days(PG_FUNCTION_ARGS);
|
||||
extern Datum make_interval(PG_FUNCTION_ARGS);
|
||||
|
||||
extern Datum timestamp_trunc(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_trunc(PG_FUNCTION_ARGS);
|
||||
|
|
|
@ -807,3 +807,48 @@ select interval_hash('30 days'::interval) = interval_hash('1 month'::interval) a
|
|||
t
|
||||
(1 row)
|
||||
|
||||
-- numeric constructor
|
||||
select make_interval(years := 2);
|
||||
make_interval
|
||||
---------------
|
||||
@ 2 years
|
||||
(1 row)
|
||||
|
||||
select make_interval(years := 1, months := 6);
|
||||
make_interval
|
||||
-----------------
|
||||
@ 1 year 6 mons
|
||||
(1 row)
|
||||
|
||||
select make_interval(years := 1, months := -1, weeks := 5, days := -7, hours := 25, mins := -180);
|
||||
make_interval
|
||||
----------------------------
|
||||
@ 11 mons 28 days 22 hours
|
||||
(1 row)
|
||||
|
||||
select make_interval() = make_interval(years := 0, months := 0, weeks := 0, days := 0, mins := 0, secs := 0.0);
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
select make_interval(hours := -2, mins := -10, secs := -25.3);
|
||||
make_interval
|
||||
---------------------------------
|
||||
@ 2 hours 10 mins 25.3 secs ago
|
||||
(1 row)
|
||||
|
||||
select make_interval(years := 'inf'::float::int);
|
||||
ERROR: integer out of range
|
||||
select make_interval(months := 'NaN'::float::int);
|
||||
ERROR: integer out of range
|
||||
select make_interval(secs := 'inf');
|
||||
ERROR: interval out of range
|
||||
select make_interval(secs := 'NaN');
|
||||
ERROR: interval out of range
|
||||
select make_interval(secs := 7e12);
|
||||
make_interval
|
||||
------------------------------------
|
||||
@ 1944444444 hours 26 mins 40 secs
|
||||
(1 row)
|
||||
|
||||
|
|
|
@ -1585,3 +1585,10 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
|||
| 2001 1 1 1 1 1 1
|
||||
(65 rows)
|
||||
|
||||
-- timestamp numeric fields constructor
|
||||
SELECT make_timestamp(2014,12,28,6,30,45.887);
|
||||
make_timestamp
|
||||
------------------------------
|
||||
Sun Dec 28 06:30:45.887 2014
|
||||
(1 row)
|
||||
|
||||
|
|
|
@ -1697,3 +1697,117 @@ SELECT * FROM TIMESTAMPTZ_TST ORDER BY a;
|
|||
|
||||
--Cleanup
|
||||
DROP TABLE TIMESTAMPTZ_TST;
|
||||
-- test timestamptz constructors
|
||||
set TimeZone to 'America/Santiago';
|
||||
-- numeric timezone
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33);
|
||||
make_timestamptz
|
||||
---------------------------------
|
||||
Sun Jul 15 08:15:55.33 1973 CLT
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2');
|
||||
make_timestamptz
|
||||
---------------------------------
|
||||
Sun Jul 15 02:15:55.33 1973 CLT
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '-2');
|
||||
make_timestamptz
|
||||
---------------------------------
|
||||
Sun Jul 15 06:15:55.33 1973 CLT
|
||||
(1 row)
|
||||
|
||||
WITH tzs (tz) AS (VALUES
|
||||
('+1'), ('+1:'), ('+1:0'), ('+100'), ('+1:00'), ('+01:00'),
|
||||
('+10'), ('+1000'), ('+10:'), ('+10:0'), ('+10:00'), ('+10:00:'),
|
||||
('+10:00:1'), ('+10:00:01'),
|
||||
('+10:00:10'))
|
||||
SELECT make_timestamptz(2010, 2, 27, 3, 45, 00, tz), tz FROM tzs;
|
||||
make_timestamptz | tz
|
||||
-------------------------------+-----------
|
||||
Fri Feb 26 23:45:00 2010 CLST | +1
|
||||
Fri Feb 26 23:45:00 2010 CLST | +1:
|
||||
Fri Feb 26 23:45:00 2010 CLST | +1:0
|
||||
Fri Feb 26 23:45:00 2010 CLST | +100
|
||||
Fri Feb 26 23:45:00 2010 CLST | +1:00
|
||||
Fri Feb 26 23:45:00 2010 CLST | +01:00
|
||||
Fri Feb 26 14:45:00 2010 CLST | +10
|
||||
Fri Feb 26 14:45:00 2010 CLST | +1000
|
||||
Fri Feb 26 14:45:00 2010 CLST | +10:
|
||||
Fri Feb 26 14:45:00 2010 CLST | +10:0
|
||||
Fri Feb 26 14:45:00 2010 CLST | +10:00
|
||||
Fri Feb 26 14:45:00 2010 CLST | +10:00:
|
||||
Fri Feb 26 14:44:59 2010 CLST | +10:00:1
|
||||
Fri Feb 26 14:44:59 2010 CLST | +10:00:01
|
||||
Fri Feb 26 14:44:50 2010 CLST | +10:00:10
|
||||
(15 rows)
|
||||
|
||||
-- these should fail
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '2');
|
||||
ERROR: invalid input syntax for numeric time zone: "2"
|
||||
HINT: Numeric time zones must have "-" or "+" as first character.
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, '+16');
|
||||
ERROR: numeric time zone "+16" out of range
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, '-16');
|
||||
ERROR: numeric time zone "-16" out of range
|
||||
-- should be true
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2') = '1973-07-15 08:15:55.33+02'::timestamptz;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- full timezone name
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') = timestamptz '2014-12-10 00:00:00 Europe/Prague';
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UTC';
|
||||
timezone
|
||||
--------------------------
|
||||
Tue Dec 09 23:00:00 2014
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC';
|
||||
timezone
|
||||
--------------------------
|
||||
Wed Dec 09 15:56:00 1846
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1866, 12, 10, 0, 0, 0, 'America/Metlakatla') AT TIME ZONE 'UTC';
|
||||
timezone
|
||||
--------------------------
|
||||
Sun Dec 09 08:46:18 1866
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1901, 12, 10, 0, 0, 0, 'America/Metlakatla') AT TIME ZONE 'UTC';
|
||||
timezone
|
||||
--------------------------
|
||||
Tue Dec 10 08:00:00 1901
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Mars/Mons_Olympus');
|
||||
ERROR: time zone "Mars/Mons_Olympus" not recognized
|
||||
-- abbreviations
|
||||
SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'CLST');
|
||||
make_timestamptz
|
||||
-------------------------------
|
||||
Wed Dec 10 10:10:10 2008 CLST
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'CLT');
|
||||
make_timestamptz
|
||||
-------------------------------
|
||||
Wed Dec 10 11:10:10 2008 CLST
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT');
|
||||
make_timestamptz
|
||||
-------------------------------
|
||||
Wed Dec 10 15:10:10 2014 CLST
|
||||
(1 row)
|
||||
|
||||
RESET TimeZone;
|
||||
|
|
|
@ -261,3 +261,17 @@ select interval '0:0:0.7', interval '@ 0.70 secs', interval '0.7 seconds';
|
|||
-- check that '30 days' equals '1 month' according to the hash function
|
||||
select '30 days'::interval = '1 month'::interval as t;
|
||||
select interval_hash('30 days'::interval) = interval_hash('1 month'::interval) as t;
|
||||
|
||||
-- numeric constructor
|
||||
select make_interval(years := 2);
|
||||
select make_interval(years := 1, months := 6);
|
||||
select make_interval(years := 1, months := -1, weeks := 5, days := -7, hours := 25, mins := -180);
|
||||
|
||||
select make_interval() = make_interval(years := 0, months := 0, weeks := 0, days := 0, mins := 0, secs := 0.0);
|
||||
select make_interval(hours := -2, mins := -10, secs := -25.3);
|
||||
|
||||
select make_interval(years := 'inf'::float::int);
|
||||
select make_interval(months := 'NaN'::float::int);
|
||||
select make_interval(secs := 'inf');
|
||||
select make_interval(secs := 'NaN');
|
||||
select make_interval(secs := 7e12);
|
||||
|
|
|
@ -222,3 +222,6 @@ SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
|
|||
|
||||
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||
FROM TIMESTAMP_TBL;
|
||||
|
||||
-- timestamp numeric fields constructor
|
||||
SELECT make_timestamp(2014,12,28,6,30,45.887);
|
||||
|
|
|
@ -254,3 +254,40 @@ INSERT INTO TIMESTAMPTZ_TST VALUES(4, '1000000312 23:58:48 IST');
|
|||
SELECT * FROM TIMESTAMPTZ_TST ORDER BY a;
|
||||
--Cleanup
|
||||
DROP TABLE TIMESTAMPTZ_TST;
|
||||
|
||||
-- test timestamptz constructors
|
||||
set TimeZone to 'America/Santiago';
|
||||
|
||||
-- numeric timezone
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33);
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2');
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '-2');
|
||||
WITH tzs (tz) AS (VALUES
|
||||
('+1'), ('+1:'), ('+1:0'), ('+100'), ('+1:00'), ('+01:00'),
|
||||
('+10'), ('+1000'), ('+10:'), ('+10:0'), ('+10:00'), ('+10:00:'),
|
||||
('+10:00:1'), ('+10:00:01'),
|
||||
('+10:00:10'))
|
||||
SELECT make_timestamptz(2010, 2, 27, 3, 45, 00, tz), tz FROM tzs;
|
||||
|
||||
-- these should fail
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '2');
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, '+16');
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, '-16');
|
||||
|
||||
-- should be true
|
||||
SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2') = '1973-07-15 08:15:55.33+02'::timestamptz;
|
||||
|
||||
-- full timezone name
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') = timestamptz '2014-12-10 00:00:00 Europe/Prague';
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(1866, 12, 10, 0, 0, 0, 'America/Metlakatla') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(1901, 12, 10, 0, 0, 0, 'America/Metlakatla') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Mars/Mons_Olympus');
|
||||
|
||||
-- abbreviations
|
||||
SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'CLST');
|
||||
SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'CLT');
|
||||
SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT');
|
||||
|
||||
RESET TimeZone;
|
||||
|
|
Loading…
Reference in New Issue