mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Add make_date() and make_time() functions.
Pavel Stehule, reviewed by Jeevan Chalke and Atri Sharma
This commit is contained in:
parent
69c8fbac20
commit
f901bb50e3
@ -6690,6 +6690,48 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
|||||||
<entry></entry>
|
<entry></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>make_date</primary>
|
||||||
|
</indexterm>
|
||||||
|
<literal>
|
||||||
|
<function>
|
||||||
|
make_date(<parameter>year</parameter> <type>int</type>,
|
||||||
|
<parameter>month</parameter> <type>int</type>,
|
||||||
|
<parameter>day</parameter> <type>int</type>)
|
||||||
|
</function>
|
||||||
|
</literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>date</type></entry>
|
||||||
|
<entry>
|
||||||
|
Create date from year, month and day fields
|
||||||
|
</entry>
|
||||||
|
<entry><literal>make_date(2013, 7, 15)</literal></entry>
|
||||||
|
<entry><literal>2013-07-15</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>make_time</primary>
|
||||||
|
</indexterm>
|
||||||
|
<literal>
|
||||||
|
<function>
|
||||||
|
make_time(<parameter>hour</parameter> <type>int</type>,
|
||||||
|
<parameter>min</parameter> <type>int</type>,
|
||||||
|
<parameter>sec</parameter> <type>double precision</type>)
|
||||||
|
</function>
|
||||||
|
</literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>time</type></entry>
|
||||||
|
<entry>
|
||||||
|
Create time from hour, minute and seconds fields
|
||||||
|
</entry>
|
||||||
|
<entry><literal>make_time(8, 15, 23.5)</literal></entry>
|
||||||
|
<entry><literal>08:15:23.5</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
|
@ -235,6 +235,43 @@ date_send(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_date - date constructor
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
make_date(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
struct pg_tm tm;
|
||||||
|
DateADT date;
|
||||||
|
int dterr;
|
||||||
|
|
||||||
|
tm.tm_year = PG_GETARG_INT32(0);
|
||||||
|
tm.tm_mon = PG_GETARG_INT32(1);
|
||||||
|
tm.tm_mday = PG_GETARG_INT32(2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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",
|
||||||
|
tm.tm_year, tm.tm_mon, tm.tm_mday)));
|
||||||
|
|
||||||
|
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",
|
||||||
|
tm.tm_year, tm.tm_mon, tm.tm_mday)));
|
||||||
|
|
||||||
|
date = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
|
||||||
|
|
||||||
|
PG_RETURN_DATEADT(date);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert reserved date values to string.
|
* Convert reserved date values to string.
|
||||||
*/
|
*/
|
||||||
@ -1208,6 +1245,39 @@ timetypmodout(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
|
PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_time - time constructor
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
make_time(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
int tm_hour = PG_GETARG_INT32(0);
|
||||||
|
int tm_min = PG_GETARG_INT32(1);
|
||||||
|
double sec = PG_GETARG_FLOAT8(2);
|
||||||
|
TimeADT time;
|
||||||
|
|
||||||
|
/* This should match the checks in DecodeTimeOnly */
|
||||||
|
if (tm_hour < 0 || tm_min < 0 || tm_min > MINS_PER_HOUR - 1 ||
|
||||||
|
sec < 0 || sec > SECS_PER_MINUTE ||
|
||||||
|
tm_hour > HOURS_PER_DAY ||
|
||||||
|
/* test for > 24:00:00 */
|
||||||
|
(tm_hour == HOURS_PER_DAY && (tm_min > 0 || sec > 0)))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
|
||||||
|
errmsg("time field value out of range: %d:%02d:%02g",
|
||||||
|
tm_hour, tm_min, sec)));
|
||||||
|
|
||||||
|
/* This should match tm2time */
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
|
||||||
|
* USECS_PER_SEC) + rint(sec * USECS_PER_SEC);
|
||||||
|
#else
|
||||||
|
time = ((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE) + sec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PG_RETURN_TIMEADT(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* time_transform()
|
/* time_transform()
|
||||||
* Flatten calls to time_scale() and timetz_scale() that solely represent
|
* Flatten calls to time_scale() and timetz_scale() that solely represent
|
||||||
|
@ -44,8 +44,6 @@ static int DecodeTimezone(char *str, int *tzp);
|
|||||||
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
|
||||||
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
||||||
struct pg_tm * tm);
|
struct pg_tm * tm);
|
||||||
static int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
|
||||||
struct pg_tm * tm);
|
|
||||||
static void TrimTrailingZeros(char *str);
|
static void TrimTrailingZeros(char *str);
|
||||||
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
|
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
|
||||||
int precision, bool fillzeros);
|
int precision, bool fillzeros);
|
||||||
@ -2270,7 +2268,7 @@ DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
|
|||||||
* Check valid year/month/day values, handle BC and DOY cases
|
* Check valid year/month/day values, handle BC and DOY cases
|
||||||
* Return 0 if okay, a DTERR code if not.
|
* Return 0 if okay, a DTERR code if not.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
||||||
struct pg_tm * tm)
|
struct pg_tm * tm)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201311162
|
#define CATALOG_VERSION_NO 201311171
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4673,6 +4673,12 @@ 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_ ));
|
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");
|
DESCR("int8range constructor");
|
||||||
|
|
||||||
|
/* date, time 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");
|
||||||
|
|
||||||
/* spgist support functions */
|
/* 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_ ));
|
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_ ));
|
||||||
DESCR("spgist(internal)");
|
DESCR("spgist(internal)");
|
||||||
|
@ -97,6 +97,7 @@ extern Datum date_in(PG_FUNCTION_ARGS);
|
|||||||
extern Datum date_out(PG_FUNCTION_ARGS);
|
extern Datum date_out(PG_FUNCTION_ARGS);
|
||||||
extern Datum date_recv(PG_FUNCTION_ARGS);
|
extern Datum date_recv(PG_FUNCTION_ARGS);
|
||||||
extern Datum date_send(PG_FUNCTION_ARGS);
|
extern Datum date_send(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum make_date(PG_FUNCTION_ARGS);
|
||||||
extern Datum date_eq(PG_FUNCTION_ARGS);
|
extern Datum date_eq(PG_FUNCTION_ARGS);
|
||||||
extern Datum date_ne(PG_FUNCTION_ARGS);
|
extern Datum date_ne(PG_FUNCTION_ARGS);
|
||||||
extern Datum date_lt(PG_FUNCTION_ARGS);
|
extern Datum date_lt(PG_FUNCTION_ARGS);
|
||||||
@ -154,6 +155,7 @@ extern Datum time_recv(PG_FUNCTION_ARGS);
|
|||||||
extern Datum time_send(PG_FUNCTION_ARGS);
|
extern Datum time_send(PG_FUNCTION_ARGS);
|
||||||
extern Datum timetypmodin(PG_FUNCTION_ARGS);
|
extern Datum timetypmodin(PG_FUNCTION_ARGS);
|
||||||
extern Datum timetypmodout(PG_FUNCTION_ARGS);
|
extern Datum timetypmodout(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum make_time(PG_FUNCTION_ARGS);
|
||||||
extern Datum time_transform(PG_FUNCTION_ARGS);
|
extern Datum time_transform(PG_FUNCTION_ARGS);
|
||||||
extern Datum time_scale(PG_FUNCTION_ARGS);
|
extern Datum time_scale(PG_FUNCTION_ARGS);
|
||||||
extern Datum time_eq(PG_FUNCTION_ARGS);
|
extern Datum time_eq(PG_FUNCTION_ARGS);
|
||||||
|
@ -294,6 +294,9 @@ extern void EncodeTimeOnly(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz
|
|||||||
extern void EncodeDateTime(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str);
|
extern void EncodeDateTime(struct pg_tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str);
|
||||||
extern void EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str);
|
extern void EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str);
|
||||||
|
|
||||||
|
extern int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
|
||||||
|
struct pg_tm * tm);
|
||||||
|
|
||||||
extern int DecodeSpecial(int field, char *lowtoken, int *val);
|
extern int DecodeSpecial(int field, char *lowtoken, int *val);
|
||||||
extern int DecodeUnits(int field, char *lowtoken, int *val);
|
extern int DecodeUnits(int field, char *lowtoken, int *val);
|
||||||
|
|
||||||
|
@ -1184,3 +1184,29 @@ select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'
|
|||||||
f | f | t
|
f | f | t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- test constructors
|
||||||
|
select make_date(2013, 7, 15);
|
||||||
|
make_date
|
||||||
|
------------
|
||||||
|
07-15-2013
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select make_time(8, 20, 0.0);
|
||||||
|
make_time
|
||||||
|
-----------
|
||||||
|
08:20:00
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- should fail
|
||||||
|
select make_date(2013, 2, 30);
|
||||||
|
ERROR: date field value out of range: 2013-02-30
|
||||||
|
select make_date(2013, 13, 1);
|
||||||
|
ERROR: date field value out of range: 2013-13-01
|
||||||
|
select make_date(2013, 11, -1);
|
||||||
|
ERROR: date field value out of range: 2013-11--1
|
||||||
|
select make_date(-44, 3, 15); -- perhaps we should allow this sometime?
|
||||||
|
ERROR: date field value out of range: -44-03-15
|
||||||
|
select make_time(10, 55, 100.1);
|
||||||
|
ERROR: time field value out of range: 10:55:100.1
|
||||||
|
select make_time(24, 0, 2.1);
|
||||||
|
ERROR: time field value out of range: 24:00:2.1
|
||||||
|
@ -276,3 +276,14 @@ select 'infinity'::date, '-infinity'::date;
|
|||||||
select 'infinity'::date > 'today'::date as t;
|
select 'infinity'::date > 'today'::date as t;
|
||||||
select '-infinity'::date < 'today'::date as t;
|
select '-infinity'::date < 'today'::date as t;
|
||||||
select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'::date);
|
select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'::date);
|
||||||
|
|
||||||
|
-- test constructors
|
||||||
|
select make_date(2013, 7, 15);
|
||||||
|
select make_time(8, 20, 0.0);
|
||||||
|
-- should fail
|
||||||
|
select make_date(2013, 2, 30);
|
||||||
|
select make_date(2013, 13, 1);
|
||||||
|
select make_date(2013, 11, -1);
|
||||||
|
select make_date(-44, 3, 15); -- perhaps we should allow this sometime?
|
||||||
|
select make_time(10, 55, 100.1);
|
||||||
|
select make_time(24, 0, 2.1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user