<entry></entry>
</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>
<entry>
<indexterm>
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.
*/
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()
* Flatten calls to time_scale() and timetz_scale() that solely represent
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);
-static int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
- struct pg_tm * tm);
static void TrimTrailingZeros(char *str);
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
int precision, bool fillzeros);
* Check valid year/month/day values, handle BC and DOY cases
* Return 0 if okay, a DTERR code if not.
*/
-static int
+int
ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
struct pg_tm * tm)
{
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201311162
+#define CATALOG_VERSION_NO 201311171
#endif
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 */
+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 */
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)");
extern Datum date_out(PG_FUNCTION_ARGS);
extern Datum date_recv(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_ne(PG_FUNCTION_ARGS);
extern Datum date_lt(PG_FUNCTION_ARGS);
extern Datum time_send(PG_FUNCTION_ARGS);
extern Datum timetypmodin(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_scale(PG_FUNCTION_ARGS);
extern Datum time_eq(PG_FUNCTION_ARGS);
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 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 DecodeUnits(int field, char *lowtoken, int *val);
f | f | t
(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
select 'infinity'::date > 'today'::date as t;
select '-infinity'::date < 'today'::date as t;
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);