PostgreSQL Source Code git master
date.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * date.c
4 * implements DATE and TIME data types specified in SQL standard
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994-5, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/date.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include <ctype.h>
19#include <limits.h>
20#include <float.h>
21#include <math.h>
22#include <time.h>
23
24#include "access/xact.h"
25#include "catalog/pg_type.h"
26#include "common/hashfn.h"
27#include "common/int.h"
28#include "libpq/pqformat.h"
29#include "miscadmin.h"
30#include "nodes/miscnodes.h"
31#include "nodes/supportnodes.h"
32#include "parser/scansup.h"
33#include "utils/array.h"
34#include "utils/builtins.h"
35#include "utils/date.h"
36#include "utils/datetime.h"
37#include "utils/numeric.h"
38#include "utils/skipsupport.h"
39#include "utils/sortsupport.h"
40
41/*
42 * gcc's -ffast-math switch breaks routines that expect exact results from
43 * expressions like timeval / SECS_PER_HOUR, where timeval is double.
44 */
45#ifdef __FAST_MATH__
46#error -ffast-math is known to break this code
47#endif
48
49
50/* common code for timetypmodin and timetztypmodin */
51static int32
53{
54 int32 *tl;
55 int n;
56
57 tl = ArrayGetIntegerTypmods(ta, &n);
58
59 /*
60 * we're not too tense about good error message here because grammar
61 * shouldn't allow wrong number of modifiers for TIME
62 */
63 if (n != 1)
65 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
66 errmsg("invalid type modifier")));
67
68 return anytime_typmod_check(istz, tl[0]);
69}
70
71/* exported so parse_expr.c can use it */
73anytime_typmod_check(bool istz, int32 typmod)
74{
75 if (typmod < 0)
77 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
78 errmsg("TIME(%d)%s precision must not be negative",
79 typmod, (istz ? " WITH TIME ZONE" : ""))));
80 if (typmod > MAX_TIME_PRECISION)
81 {
83 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
84 errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
85 typmod, (istz ? " WITH TIME ZONE" : ""),
87 typmod = MAX_TIME_PRECISION;
88 }
89
90 return typmod;
91}
92
93/* common code for timetypmodout and timetztypmodout */
94static char *
95anytime_typmodout(bool istz, int32 typmod)
96{
97 const char *tz = istz ? " with time zone" : " without time zone";
98
99 if (typmod >= 0)
100 return psprintf("(%d)%s", (int) typmod, tz);
101 else
102 return pstrdup(tz);
103}
104
105
106/*****************************************************************************
107 * Date ADT
108 *****************************************************************************/
109
110
111/* date_in()
112 * Given date text string, convert to internal date format.
113 */
114Datum
116{
117 char *str = PG_GETARG_CSTRING(0);
118 Node *escontext = fcinfo->context;
120 fsec_t fsec;
121 struct pg_tm tt,
122 *tm = &tt;
123 int tzp;
124 int dtype;
125 int nf;
126 int dterr;
127 char *field[MAXDATEFIELDS];
128 int ftype[MAXDATEFIELDS];
129 char workbuf[MAXDATELEN + 1];
130 DateTimeErrorExtra extra;
131
132 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
133 field, ftype, MAXDATEFIELDS, &nf);
134 if (dterr == 0)
135 dterr = DecodeDateTime(field, ftype, nf,
136 &dtype, tm, &fsec, &tzp, &extra);
137 if (dterr != 0)
138 {
139 DateTimeParseError(dterr, &extra, str, "date", escontext);
141 }
142
143 switch (dtype)
144 {
145 case DTK_DATE:
146 break;
147
148 case DTK_EPOCH:
150 break;
151
152 case DTK_LATE:
155
156 case DTK_EARLY:
159
160 default:
161 DateTimeParseError(DTERR_BAD_FORMAT, &extra, str, "date", escontext);
163 }
164
165 /* Prevent overflow in Julian-day routines */
167 ereturn(escontext, (Datum) 0,
168 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
169 errmsg("date out of range: \"%s\"", str)));
170
172
173 /* Now check for just-out-of-range dates */
174 if (!IS_VALID_DATE(date))
175 ereturn(escontext, (Datum) 0,
176 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
177 errmsg("date out of range: \"%s\"", str)));
178
180}
181
182/* date_out()
183 * Given internal format date, convert to text string.
184 */
185Datum
187{
189 char *result;
190 struct pg_tm tt,
191 *tm = &tt;
192 char buf[MAXDATELEN + 1];
193
196 else
197 {
199 &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
201 }
202
203 result = pstrdup(buf);
204 PG_RETURN_CSTRING(result);
205}
206
207/*
208 * date_recv - converts external binary format to date
209 */
210Datum
212{
214 DateADT result;
215
216 result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
217
218 /* Limit to the same range that date_in() accepts. */
219 if (DATE_NOT_FINITE(result))
220 /* ok */ ;
221 else if (!IS_VALID_DATE(result))
223 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
224 errmsg("date out of range")));
225
226 PG_RETURN_DATEADT(result);
227}
228
229/*
230 * date_send - converts date to binary format
231 */
232Datum
234{
237
241}
242
243/*
244 * make_date - date constructor
245 */
246Datum
248{
249 struct pg_tm tm;
251 int dterr;
252 bool bc = false;
253
257
258 /* Handle negative years as BC */
259 if (tm.tm_year < 0)
260 {
261 int year = tm.tm_year;
262
263 bc = true;
264 if (pg_neg_s32_overflow(year, &year))
266 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
267 errmsg("date field value out of range: %d-%02d-%02d",
269 tm.tm_year = year;
270 }
271
272 dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm);
273
274 if (dterr != 0)
276 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
277 errmsg("date field value out of range: %d-%02d-%02d",
279
280 /* Prevent overflow in Julian-day routines */
283 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
284 errmsg("date out of range: %d-%02d-%02d",
286
288
289 /* Now check for just-out-of-range dates */
290 if (!IS_VALID_DATE(date))
292 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
293 errmsg("date out of range: %d-%02d-%02d",
295
297}
298
299/*
300 * Convert reserved date values to string.
301 */
302void
304{
305 if (DATE_IS_NOBEGIN(dt))
306 strcpy(str, EARLY);
307 else if (DATE_IS_NOEND(dt))
308 strcpy(str, LATE);
309 else /* shouldn't happen */
310 elog(ERROR, "invalid argument for EncodeSpecialDate");
311}
312
313
314/*
315 * GetSQLCurrentDate -- implements CURRENT_DATE
316 */
319{
320 struct pg_tm tm;
321
322 static int cache_year = 0;
323 static int cache_mon = 0;
324 static int cache_mday = 0;
325 static DateADT cache_date;
326
328
329 /*
330 * date2j involves several integer divisions; moreover, unless our session
331 * lives across local midnight, we don't really have to do it more than
332 * once. So it seems worth having a separate cache here.
333 */
334 if (tm.tm_year != cache_year ||
335 tm.tm_mon != cache_mon ||
336 tm.tm_mday != cache_mday)
337 {
339 cache_year = tm.tm_year;
340 cache_mon = tm.tm_mon;
341 cache_mday = tm.tm_mday;
342 }
343
344 return cache_date;
345}
346
347/*
348 * GetSQLCurrentTime -- implements CURRENT_TIME, CURRENT_TIME(n)
349 */
350TimeTzADT *
352{
353 TimeTzADT *result;
354 struct pg_tm tt,
355 *tm = &tt;
356 fsec_t fsec;
357 int tz;
358
359 GetCurrentTimeUsec(tm, &fsec, &tz);
360
361 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
362 tm2timetz(tm, fsec, tz, result);
363 AdjustTimeForTypmod(&(result->time), typmod);
364 return result;
365}
366
367/*
368 * GetSQLLocalTime -- implements LOCALTIME, LOCALTIME(n)
369 */
372{
373 TimeADT result;
374 struct pg_tm tt,
375 *tm = &tt;
376 fsec_t fsec;
377 int tz;
378
379 GetCurrentTimeUsec(tm, &fsec, &tz);
380
381 tm2time(tm, fsec, &result);
382 AdjustTimeForTypmod(&result, typmod);
383 return result;
384}
385
386
387/*
388 * Comparison functions for dates
389 */
390
391Datum
393{
394 DateADT dateVal1 = PG_GETARG_DATEADT(0);
395 DateADT dateVal2 = PG_GETARG_DATEADT(1);
396
397 PG_RETURN_BOOL(dateVal1 == dateVal2);
398}
399
400Datum
402{
403 DateADT dateVal1 = PG_GETARG_DATEADT(0);
404 DateADT dateVal2 = PG_GETARG_DATEADT(1);
405
406 PG_RETURN_BOOL(dateVal1 != dateVal2);
407}
408
409Datum
411{
412 DateADT dateVal1 = PG_GETARG_DATEADT(0);
413 DateADT dateVal2 = PG_GETARG_DATEADT(1);
414
415 PG_RETURN_BOOL(dateVal1 < dateVal2);
416}
417
418Datum
420{
421 DateADT dateVal1 = PG_GETARG_DATEADT(0);
422 DateADT dateVal2 = PG_GETARG_DATEADT(1);
423
424 PG_RETURN_BOOL(dateVal1 <= dateVal2);
425}
426
427Datum
429{
430 DateADT dateVal1 = PG_GETARG_DATEADT(0);
431 DateADT dateVal2 = PG_GETARG_DATEADT(1);
432
433 PG_RETURN_BOOL(dateVal1 > dateVal2);
434}
435
436Datum
438{
439 DateADT dateVal1 = PG_GETARG_DATEADT(0);
440 DateADT dateVal2 = PG_GETARG_DATEADT(1);
441
442 PG_RETURN_BOOL(dateVal1 >= dateVal2);
443}
444
445Datum
447{
448 DateADT dateVal1 = PG_GETARG_DATEADT(0);
449 DateADT dateVal2 = PG_GETARG_DATEADT(1);
450
451 if (dateVal1 < dateVal2)
452 PG_RETURN_INT32(-1);
453 else if (dateVal1 > dateVal2)
456}
457
458Datum
460{
462
465}
466
467static Datum
468date_decrement(Relation rel, Datum existing, bool *underflow)
469{
470 DateADT dexisting = DatumGetDateADT(existing);
471
472 if (dexisting == DATEVAL_NOBEGIN)
473 {
474 /* return value is undefined */
475 *underflow = true;
476 return (Datum) 0;
477 }
478
479 *underflow = false;
480 return DateADTGetDatum(dexisting - 1);
481}
482
483static Datum
484date_increment(Relation rel, Datum existing, bool *overflow)
485{
486 DateADT dexisting = DatumGetDateADT(existing);
487
488 if (dexisting == DATEVAL_NOEND)
489 {
490 /* return value is undefined */
491 *overflow = true;
492 return (Datum) 0;
493 }
494
495 *overflow = false;
496 return DateADTGetDatum(dexisting + 1);
497}
498
499Datum
501{
503
504 sksup->decrement = date_decrement;
505 sksup->increment = date_increment;
508
510}
511
512Datum
514{
516}
517
518Datum
520{
522}
523
524Datum
526{
528
530}
531
532Datum
534{
535 DateADT dateVal1 = PG_GETARG_DATEADT(0);
536 DateADT dateVal2 = PG_GETARG_DATEADT(1);
537
538 PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);
539}
540
541Datum
543{
544 DateADT dateVal1 = PG_GETARG_DATEADT(0);
545 DateADT dateVal2 = PG_GETARG_DATEADT(1);
546
547 PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);
548}
549
550/* Compute difference between two dates in days.
551 */
552Datum
554{
555 DateADT dateVal1 = PG_GETARG_DATEADT(0);
556 DateADT dateVal2 = PG_GETARG_DATEADT(1);
557
558 if (DATE_NOT_FINITE(dateVal1) || DATE_NOT_FINITE(dateVal2))
560 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
561 errmsg("cannot subtract infinite dates")));
562
563 PG_RETURN_INT32((int32) (dateVal1 - dateVal2));
564}
565
566/* Add a number of days to a date, giving a new date.
567 * Must handle both positive and negative numbers of days.
568 */
569Datum
571{
572 DateADT dateVal = PG_GETARG_DATEADT(0);
574 DateADT result;
575
576 if (DATE_NOT_FINITE(dateVal))
577 PG_RETURN_DATEADT(dateVal); /* can't change infinity */
578
579 result = dateVal + days;
580
581 /* Check for integer overflow and out-of-allowed-range */
582 if ((days >= 0 ? (result < dateVal) : (result > dateVal)) ||
583 !IS_VALID_DATE(result))
585 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
586 errmsg("date out of range")));
587
588 PG_RETURN_DATEADT(result);
589}
590
591/* Subtract a number of days from a date, giving a new date.
592 */
593Datum
595{
596 DateADT dateVal = PG_GETARG_DATEADT(0);
598 DateADT result;
599
600 if (DATE_NOT_FINITE(dateVal))
601 PG_RETURN_DATEADT(dateVal); /* can't change infinity */
602
603 result = dateVal - days;
604
605 /* Check for integer overflow and out-of-allowed-range */
606 if ((days >= 0 ? (result > dateVal) : (result < dateVal)) ||
607 !IS_VALID_DATE(result))
609 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
610 errmsg("date out of range")));
611
612 PG_RETURN_DATEADT(result);
613}
614
615
616/*
617 * Promote date to timestamp.
618 *
619 * If the date falls out of the valid range for the timestamp type, error
620 * handling proceeds based on escontext.
621 *
622 * If escontext is NULL, we throw an out-of-range error (hard error).
623 * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or
624 * upper bound overflow, respectively, and record a soft error.
625 *
626 * Note: Lower bound overflow is currently not possible, as both date and
627 * timestamp datatypes share the same lower boundary: Julian day zero.
628 */
630date2timestamp_safe(DateADT dateVal, Node *escontext)
631{
632 Timestamp result;
633
634 if (DATE_IS_NOBEGIN(dateVal))
635 TIMESTAMP_NOBEGIN(result);
636 else if (DATE_IS_NOEND(dateVal))
637 TIMESTAMP_NOEND(result);
638 else
639 {
640 /*
641 * Since dates have the same minimum values as timestamps, only upper
642 * boundary need be checked for overflow.
643 */
645 {
646 TIMESTAMP_NOEND(result);
647 ereturn(escontext, result,
648 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
649 errmsg("date out of range for timestamp")));
650 }
651
652 /* date is days since 2000, timestamp is microseconds since same... */
653 result = dateVal * USECS_PER_DAY;
654 }
655
656 return result;
657}
658
659/*
660 * Promote date to timestamp, throwing error for overflow.
661 */
662static TimestampTz
664{
665 return date2timestamp_safe(dateVal, NULL);
666}
667
668/*
669 * Promote date to timestamp with time zone.
670 *
671 * If the date falls out of the valid range for the timestamp type, error
672 * handling proceeds based on escontext.
673 *
674 * If escontext is NULL, we throw an out-of-range error (hard error).
675 * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or
676 * upper bound overflow, respectively, and record a soft error.
677 */
680{
681 TimestampTz result;
682 struct pg_tm tt,
683 *tm = &tt;
684 int tz;
685
686 if (DATE_IS_NOBEGIN(dateVal))
687 TIMESTAMP_NOBEGIN(result);
688 else if (DATE_IS_NOEND(dateVal))
689 TIMESTAMP_NOEND(result);
690 else
691 {
692 /*
693 * Since dates have the same minimum values as timestamps, only upper
694 * boundary need be checked for overflow.
695 */
697 {
698 TIMESTAMP_NOEND(result);
699 ereturn(escontext, result,
700 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
701 errmsg("date out of range for timestamp")));
702 }
703
705 &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
706 tm->tm_hour = 0;
707 tm->tm_min = 0;
708 tm->tm_sec = 0;
710
711 result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
712
713 /*
714 * Since it is possible to go beyond allowed timestamptz range because
715 * of time zone, check for allowed timestamp range after adding tz.
716 */
717 if (!IS_VALID_TIMESTAMP(result))
718 {
719 if (result < MIN_TIMESTAMP)
720 TIMESTAMP_NOBEGIN(result);
721 else
722 TIMESTAMP_NOEND(result);
723
724 ereturn(escontext, result,
725 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
726 errmsg("date out of range for timestamp")));
727 }
728 }
729
730 return result;
731}
732
733/*
734 * Promote date to timestamptz, throwing error for overflow.
735 */
736static TimestampTz
738{
739 return date2timestamptz_safe(dateVal, NULL);
740}
741
742/*
743 * date2timestamp_no_overflow
744 *
745 * This is chartered to produce a double value that is numerically
746 * equivalent to the corresponding Timestamp value, if the date is in the
747 * valid range of Timestamps, but in any case not throw an overflow error.
748 * We can do this since the numerical range of double is greater than
749 * that of non-erroneous timestamps. The results are currently only
750 * used for statistical estimation purposes.
751 */
752double
754{
755 double result;
756
757 if (DATE_IS_NOBEGIN(dateVal))
758 result = -DBL_MAX;
759 else if (DATE_IS_NOEND(dateVal))
760 result = DBL_MAX;
761 else
762 {
763 /* date is days since 2000, timestamp is microseconds since same... */
764 result = dateVal * (double) USECS_PER_DAY;
765 }
766
767 return result;
768}
769
770
771/*
772 * Crosstype comparison functions for dates
773 */
774
775int32
777{
778 Timestamp dt1;
779 ErrorSaveContext escontext = {T_ErrorSaveContext};
780
781 dt1 = date2timestamp_safe(dateVal, (Node *) &escontext);
782 if (escontext.error_occurred)
783 {
784 Assert(TIMESTAMP_IS_NOEND(dt1)); /* NOBEGIN case cannot occur */
785
786 /* dt1 is larger than any finite timestamp, but less than infinity */
787 return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
788 }
789
790 return timestamp_cmp_internal(dt1, dt2);
791}
792
793Datum
795{
796 DateADT dateVal = PG_GETARG_DATEADT(0);
798
800}
801
802Datum
804{
805 DateADT dateVal = PG_GETARG_DATEADT(0);
807
809}
810
811Datum
813{
814 DateADT dateVal = PG_GETARG_DATEADT(0);
816
818}
819
820Datum
822{
823 DateADT dateVal = PG_GETARG_DATEADT(0);
825
827}
828
829Datum
831{
832 DateADT dateVal = PG_GETARG_DATEADT(0);
834
836}
837
838Datum
840{
841 DateADT dateVal = PG_GETARG_DATEADT(0);
843
845}
846
847Datum
849{
850 DateADT dateVal = PG_GETARG_DATEADT(0);
852
854}
855
856int32
858{
859 TimestampTz dt1;
860 ErrorSaveContext escontext = {T_ErrorSaveContext};
861
862 dt1 = date2timestamptz_safe(dateVal, (Node *) &escontext);
863
864 if (escontext.error_occurred)
865 {
866 if (TIMESTAMP_IS_NOEND(dt1))
867 {
868 /* dt1 is larger than any finite timestamp, but less than infinity */
869 return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
870 }
871 if (TIMESTAMP_IS_NOBEGIN(dt1))
872 {
873 /* dt1 is less than any finite timestamp, but more than -infinity */
874 return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
875 }
876 }
877
878 return timestamptz_cmp_internal(dt1, dt2);
879}
880
881Datum
883{
884 DateADT dateVal = PG_GETARG_DATEADT(0);
886
888}
889
890Datum
892{
893 DateADT dateVal = PG_GETARG_DATEADT(0);
895
897}
898
899Datum
901{
902 DateADT dateVal = PG_GETARG_DATEADT(0);
904
906}
907
908Datum
910{
911 DateADT dateVal = PG_GETARG_DATEADT(0);
913
915}
916
917Datum
919{
920 DateADT dateVal = PG_GETARG_DATEADT(0);
922
924}
925
926Datum
928{
929 DateADT dateVal = PG_GETARG_DATEADT(0);
931
933}
934
935Datum
937{
938 DateADT dateVal = PG_GETARG_DATEADT(0);
940
942}
943
944Datum
946{
948 DateADT dateVal = PG_GETARG_DATEADT(1);
949
951}
952
953Datum
955{
957 DateADT dateVal = PG_GETARG_DATEADT(1);
958
960}
961
962Datum
964{
966 DateADT dateVal = PG_GETARG_DATEADT(1);
967
969}
970
971Datum
973{
975 DateADT dateVal = PG_GETARG_DATEADT(1);
976
978}
979
980Datum
982{
984 DateADT dateVal = PG_GETARG_DATEADT(1);
985
987}
988
989Datum
991{
993 DateADT dateVal = PG_GETARG_DATEADT(1);
994
996}
997
998Datum
1000{
1002 DateADT dateVal = PG_GETARG_DATEADT(1);
1003
1005}
1006
1007Datum
1009{
1011 DateADT dateVal = PG_GETARG_DATEADT(1);
1012
1014}
1015
1016Datum
1018{
1020 DateADT dateVal = PG_GETARG_DATEADT(1);
1021
1023}
1024
1025Datum
1027{
1029 DateADT dateVal = PG_GETARG_DATEADT(1);
1030
1032}
1033
1034Datum
1036{
1038 DateADT dateVal = PG_GETARG_DATEADT(1);
1039
1041}
1042
1043Datum
1045{
1047 DateADT dateVal = PG_GETARG_DATEADT(1);
1048
1050}
1051
1052Datum
1054{
1056 DateADT dateVal = PG_GETARG_DATEADT(1);
1057
1059}
1060
1061Datum
1063{
1065 DateADT dateVal = PG_GETARG_DATEADT(1);
1066
1068}
1069
1070/*
1071 * in_range support function for date.
1072 *
1073 * We implement this by promoting the dates to timestamp (without time zone)
1074 * and then using the timestamp-and-interval in_range function.
1075 */
1076Datum
1078{
1080 DateADT base = PG_GETARG_DATEADT(1);
1081 Interval *offset = PG_GETARG_INTERVAL_P(2);
1082 bool sub = PG_GETARG_BOOL(3);
1083 bool less = PG_GETARG_BOOL(4);
1084 Timestamp valStamp;
1085 Timestamp baseStamp;
1086
1087 /* XXX we could support out-of-range cases here, perhaps */
1088 valStamp = date2timestamp(val);
1089 baseStamp = date2timestamp(base);
1090
1092 TimestampGetDatum(valStamp),
1093 TimestampGetDatum(baseStamp),
1094 IntervalPGetDatum(offset),
1095 BoolGetDatum(sub),
1096 BoolGetDatum(less));
1097}
1098
1099
1100/* extract_date()
1101 * Extract specified field from date type.
1102 */
1103Datum
1105{
1106 text *units = PG_GETARG_TEXT_PP(0);
1108 int64 intresult;
1109 int type,
1110 val;
1111 char *lowunits;
1112 int year,
1113 mon,
1114 mday;
1115
1116 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
1117 VARSIZE_ANY_EXHDR(units),
1118 false);
1119
1120 type = DecodeUnits(0, lowunits, &val);
1121 if (type == UNKNOWN_FIELD)
1122 type = DecodeSpecial(0, lowunits, &val);
1123
1124 if (DATE_NOT_FINITE(date) && (type == UNITS || type == RESERV))
1125 {
1126 switch (val)
1127 {
1128 /* Oscillating units */
1129 case DTK_DAY:
1130 case DTK_MONTH:
1131 case DTK_QUARTER:
1132 case DTK_WEEK:
1133 case DTK_DOW:
1134 case DTK_ISODOW:
1135 case DTK_DOY:
1137 break;
1138
1139 /* Monotonically-increasing units */
1140 case DTK_YEAR:
1141 case DTK_DECADE:
1142 case DTK_CENTURY:
1143 case DTK_MILLENNIUM:
1144 case DTK_JULIAN:
1145 case DTK_ISOYEAR:
1146 case DTK_EPOCH:
1147 if (DATE_IS_NOBEGIN(date))
1149 CStringGetDatum("-Infinity"),
1151 Int32GetDatum(-1))));
1152 else
1154 CStringGetDatum("Infinity"),
1156 Int32GetDatum(-1))));
1157 default:
1158 ereport(ERROR,
1159 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1160 errmsg("unit \"%s\" not supported for type %s",
1161 lowunits, format_type_be(DATEOID))));
1162 }
1163 }
1164 else if (type == UNITS)
1165 {
1166 j2date(date + POSTGRES_EPOCH_JDATE, &year, &mon, &mday);
1167
1168 switch (val)
1169 {
1170 case DTK_DAY:
1171 intresult = mday;
1172 break;
1173
1174 case DTK_MONTH:
1175 intresult = mon;
1176 break;
1177
1178 case DTK_QUARTER:
1179 intresult = (mon - 1) / 3 + 1;
1180 break;
1181
1182 case DTK_WEEK:
1183 intresult = date2isoweek(year, mon, mday);
1184 break;
1185
1186 case DTK_YEAR:
1187 if (year > 0)
1188 intresult = year;
1189 else
1190 /* there is no year 0, just 1 BC and 1 AD */
1191 intresult = year - 1;
1192 break;
1193
1194 case DTK_DECADE:
1195 /* see comments in timestamp_part */
1196 if (year >= 0)
1197 intresult = year / 10;
1198 else
1199 intresult = -((8 - (year - 1)) / 10);
1200 break;
1201
1202 case DTK_CENTURY:
1203 /* see comments in timestamp_part */
1204 if (year > 0)
1205 intresult = (year + 99) / 100;
1206 else
1207 intresult = -((99 - (year - 1)) / 100);
1208 break;
1209
1210 case DTK_MILLENNIUM:
1211 /* see comments in timestamp_part */
1212 if (year > 0)
1213 intresult = (year + 999) / 1000;
1214 else
1215 intresult = -((999 - (year - 1)) / 1000);
1216 break;
1217
1218 case DTK_JULIAN:
1219 intresult = date + POSTGRES_EPOCH_JDATE;
1220 break;
1221
1222 case DTK_ISOYEAR:
1223 intresult = date2isoyear(year, mon, mday);
1224 /* Adjust BC years */
1225 if (intresult <= 0)
1226 intresult -= 1;
1227 break;
1228
1229 case DTK_DOW:
1230 case DTK_ISODOW:
1231 intresult = j2day(date + POSTGRES_EPOCH_JDATE);
1232 if (val == DTK_ISODOW && intresult == 0)
1233 intresult = 7;
1234 break;
1235
1236 case DTK_DOY:
1237 intresult = date2j(year, mon, mday) - date2j(year, 1, 1) + 1;
1238 break;
1239
1240 default:
1241 ereport(ERROR,
1242 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1243 errmsg("unit \"%s\" not supported for type %s",
1244 lowunits, format_type_be(DATEOID))));
1245 intresult = 0;
1246 }
1247 }
1248 else if (type == RESERV)
1249 {
1250 switch (val)
1251 {
1252 case DTK_EPOCH:
1254 break;
1255
1256 default:
1257 ereport(ERROR,
1258 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1259 errmsg("unit \"%s\" not supported for type %s",
1260 lowunits, format_type_be(DATEOID))));
1261 intresult = 0;
1262 }
1263 }
1264 else
1265 {
1266 ereport(ERROR,
1267 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1268 errmsg("unit \"%s\" not recognized for type %s",
1269 lowunits, format_type_be(DATEOID))));
1270 intresult = 0;
1271 }
1272
1274}
1275
1276
1277/* Add an interval to a date, giving a new date.
1278 * Must handle both positive and negative intervals.
1279 *
1280 * We implement this by promoting the date to timestamp (without time zone)
1281 * and then using the timestamp plus interval function.
1282 */
1283Datum
1285{
1286 DateADT dateVal = PG_GETARG_DATEADT(0);
1287 Interval *span = PG_GETARG_INTERVAL_P(1);
1288 Timestamp dateStamp;
1289
1290 dateStamp = date2timestamp(dateVal);
1291
1293 TimestampGetDatum(dateStamp),
1294 PointerGetDatum(span));
1295}
1296
1297/* Subtract an interval from a date, giving a new date.
1298 * Must handle both positive and negative intervals.
1299 *
1300 * We implement this by promoting the date to timestamp (without time zone)
1301 * and then using the timestamp minus interval function.
1302 */
1303Datum
1305{
1306 DateADT dateVal = PG_GETARG_DATEADT(0);
1307 Interval *span = PG_GETARG_INTERVAL_P(1);
1308 Timestamp dateStamp;
1309
1310 dateStamp = date2timestamp(dateVal);
1311
1313 TimestampGetDatum(dateStamp),
1314 PointerGetDatum(span));
1315}
1316
1317/* date_timestamp()
1318 * Convert date to timestamp data type.
1319 */
1320Datum
1322{
1323 DateADT dateVal = PG_GETARG_DATEADT(0);
1324 Timestamp result;
1325
1326 result = date2timestamp(dateVal);
1327
1328 PG_RETURN_TIMESTAMP(result);
1329}
1330
1331/* timestamp_date()
1332 * Convert timestamp to date data type.
1333 */
1334Datum
1336{
1338 DateADT result;
1339
1340 result = timestamp2date_safe(timestamp, NULL);
1341 PG_RETURN_DATEADT(result);
1342}
1343
1344/*
1345 * Convert timestamp to date.
1346 *
1347 * If the timestamp falls out of the valid range for the date type, error
1348 * handling proceeds based on escontext.
1349 *
1350 * If escontext is NULL, we throw an out-of-range error (hard error).
1351 * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or
1352 * upper bound overflow, respectively, and record a soft error.
1353 *
1354 * Note: given the ranges of the types, overflow is only possible at
1355 * the lower bound of the range, but we don't assume that in this code.
1356 */
1357DateADT
1359{
1360 DateADT result;
1361 struct pg_tm tt,
1362 *tm = &tt;
1363 fsec_t fsec;
1364
1366 DATE_NOBEGIN(result);
1367 else if (TIMESTAMP_IS_NOEND(timestamp))
1368 DATE_NOEND(result);
1369 else
1370 {
1371 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1372 {
1373 if (timestamp < 0)
1374 DATE_NOBEGIN(result);
1375 else
1376 DATE_NOEND(result); /* not actually reachable */
1377
1378 ereturn(escontext, result,
1379 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1380 errmsg("timestamp out of range")));
1381 }
1382
1384 }
1385
1386 return result;
1387}
1388
1389
1390/* date_timestamptz()
1391 * Convert date to timestamp with time zone data type.
1392 */
1393Datum
1395{
1396 DateADT dateVal = PG_GETARG_DATEADT(0);
1397 TimestampTz result;
1398
1399 result = date2timestamptz(dateVal);
1400
1401 PG_RETURN_TIMESTAMP(result);
1402}
1403
1404
1405/* timestamptz_date()
1406 * Convert timestamp with time zone to date data type.
1407 */
1408Datum
1410{
1412 DateADT result;
1413
1414 result = timestamptz2date_safe(timestamp, NULL);
1415 PG_RETURN_DATEADT(result);
1416}
1417
1418/*
1419 * Convert timestamptz to date.
1420 *
1421 * If the timestamp falls out of the valid range for the date type, error
1422 * handling proceeds based on escontext.
1423 *
1424 * If escontext is NULL, we throw an out-of-range error (hard error).
1425 * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or
1426 * upper bound overflow, respectively, and record a soft error.
1427 *
1428 * Note: given the ranges of the types, overflow is only possible at
1429 * the lower bound of the range, but we don't assume that in this code.
1430 */
1431DateADT
1433{
1434 DateADT result;
1435 struct pg_tm tt,
1436 *tm = &tt;
1437 fsec_t fsec;
1438 int tz;
1439
1441 DATE_NOBEGIN(result);
1442 else if (TIMESTAMP_IS_NOEND(timestamp))
1443 DATE_NOEND(result);
1444 else
1445 {
1446 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1447 {
1448 if (timestamp < 0)
1449 DATE_NOBEGIN(result);
1450 else
1451 DATE_NOEND(result); /* not actually reachable */
1452
1453 ereturn(escontext, result,
1454 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1455 errmsg("timestamp out of range")));
1456 }
1457
1459 }
1460
1461 return result;
1462}
1463
1464
1465/*****************************************************************************
1466 * Time ADT
1467 *****************************************************************************/
1468
1469Datum
1471{
1472 char *str = PG_GETARG_CSTRING(0);
1473#ifdef NOT_USED
1474 Oid typelem = PG_GETARG_OID(1);
1475#endif
1476 int32 typmod = PG_GETARG_INT32(2);
1477 Node *escontext = fcinfo->context;
1478 TimeADT result;
1479 fsec_t fsec;
1480 struct pg_tm tt,
1481 *tm = &tt;
1482 int tz;
1483 int nf;
1484 int dterr;
1485 char workbuf[MAXDATELEN + 1];
1486 char *field[MAXDATEFIELDS];
1487 int dtype;
1488 int ftype[MAXDATEFIELDS];
1489 DateTimeErrorExtra extra;
1490
1491 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
1492 field, ftype, MAXDATEFIELDS, &nf);
1493 if (dterr == 0)
1494 dterr = DecodeTimeOnly(field, ftype, nf,
1495 &dtype, tm, &fsec, &tz, &extra);
1496 if (dterr != 0)
1497 {
1498 DateTimeParseError(dterr, &extra, str, "time", escontext);
1500 }
1501
1502 tm2time(tm, fsec, &result);
1503 AdjustTimeForTypmod(&result, typmod);
1504
1505 PG_RETURN_TIMEADT(result);
1506}
1507
1508/* tm2time()
1509 * Convert a tm structure to a time data type.
1510 */
1511int
1512tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
1513{
1514 *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
1515 * USECS_PER_SEC) + fsec;
1516 return 0;
1517}
1518
1519/* time_overflows()
1520 * Check to see if a broken-down time-of-day is out of range.
1521 */
1522bool
1523time_overflows(int hour, int min, int sec, fsec_t fsec)
1524{
1525 /* Range-check the fields individually. */
1526 if (hour < 0 || hour > HOURS_PER_DAY ||
1527 min < 0 || min >= MINS_PER_HOUR ||
1528 sec < 0 || sec > SECS_PER_MINUTE ||
1529 fsec < 0 || fsec > USECS_PER_SEC)
1530 return true;
1531
1532 /*
1533 * Because we allow, eg, hour = 24 or sec = 60, we must check separately
1534 * that the total time value doesn't exceed 24:00:00.
1535 */
1536 if ((((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
1537 + sec) * USECS_PER_SEC) + fsec) > USECS_PER_DAY)
1538 return true;
1539
1540 return false;
1541}
1542
1543/* float_time_overflows()
1544 * Same, when we have seconds + fractional seconds as one "double" value.
1545 */
1546bool
1547float_time_overflows(int hour, int min, double sec)
1548{
1549 /* Range-check the fields individually. */
1550 if (hour < 0 || hour > HOURS_PER_DAY ||
1551 min < 0 || min >= MINS_PER_HOUR)
1552 return true;
1553
1554 /*
1555 * "sec", being double, requires extra care. Cope with NaN, and round off
1556 * before applying the range check to avoid unexpected errors due to
1557 * imprecise input. (We assume rint() behaves sanely with infinities.)
1558 */
1559 if (isnan(sec))
1560 return true;
1561 sec = rint(sec * USECS_PER_SEC);
1562 if (sec < 0 || sec > SECS_PER_MINUTE * USECS_PER_SEC)
1563 return true;
1564
1565 /*
1566 * Because we allow, eg, hour = 24 or sec = 60, we must check separately
1567 * that the total time value doesn't exceed 24:00:00. This must match the
1568 * way that callers will convert the fields to a time.
1569 */
1570 if (((((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
1571 * USECS_PER_SEC) + (int64) sec) > USECS_PER_DAY)
1572 return true;
1573
1574 return false;
1575}
1576
1577
1578/* time2tm()
1579 * Convert time data type to POSIX time structure.
1580 *
1581 * Note that only the hour/min/sec/fractional-sec fields are filled in.
1582 */
1583int
1584time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
1585{
1586 tm->tm_hour = time / USECS_PER_HOUR;
1587 time -= tm->tm_hour * USECS_PER_HOUR;
1588 tm->tm_min = time / USECS_PER_MINUTE;
1589 time -= tm->tm_min * USECS_PER_MINUTE;
1590 tm->tm_sec = time / USECS_PER_SEC;
1591 time -= tm->tm_sec * USECS_PER_SEC;
1592 *fsec = time;
1593 return 0;
1594}
1595
1596Datum
1598{
1599 TimeADT time = PG_GETARG_TIMEADT(0);
1600 char *result;
1601 struct pg_tm tt,
1602 *tm = &tt;
1603 fsec_t fsec;
1604 char buf[MAXDATELEN + 1];
1605
1606 time2tm(time, tm, &fsec);
1607 EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
1608
1609 result = pstrdup(buf);
1610 PG_RETURN_CSTRING(result);
1611}
1612
1613/*
1614 * time_recv - converts external binary format to time
1615 */
1616Datum
1618{
1620
1621#ifdef NOT_USED
1622 Oid typelem = PG_GETARG_OID(1);
1623#endif
1624 int32 typmod = PG_GETARG_INT32(2);
1625 TimeADT result;
1626
1627 result = pq_getmsgint64(buf);
1628
1629 if (result < INT64CONST(0) || result > USECS_PER_DAY)
1630 ereport(ERROR,
1631 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1632 errmsg("time out of range")));
1633
1634 AdjustTimeForTypmod(&result, typmod);
1635
1636 PG_RETURN_TIMEADT(result);
1637}
1638
1639/*
1640 * time_send - converts time to binary format
1641 */
1642Datum
1644{
1645 TimeADT time = PG_GETARG_TIMEADT(0);
1647
1649 pq_sendint64(&buf, time);
1651}
1652
1653Datum
1655{
1657
1659}
1660
1661Datum
1663{
1664 int32 typmod = PG_GETARG_INT32(0);
1665
1666 PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
1667}
1668
1669/*
1670 * make_time - time constructor
1671 */
1672Datum
1674{
1675 int tm_hour = PG_GETARG_INT32(0);
1676 int tm_min = PG_GETARG_INT32(1);
1677 double sec = PG_GETARG_FLOAT8(2);
1678 TimeADT time;
1679
1680 /* Check for time overflow */
1682 ereport(ERROR,
1683 (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
1684 errmsg("time field value out of range: %d:%02d:%02g",
1685 tm_hour, tm_min, sec)));
1686
1687 /* This should match tm2time */
1689 * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
1690
1691 PG_RETURN_TIMEADT(time);
1692}
1693
1694
1695/* time_support()
1696 *
1697 * Planner support function for the time_scale() and timetz_scale()
1698 * length coercion functions (we need not distinguish them here).
1699 */
1700Datum
1702{
1703 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1704 Node *ret = NULL;
1705
1706 if (IsA(rawreq, SupportRequestSimplify))
1707 {
1709
1711 }
1712
1713 PG_RETURN_POINTER(ret);
1714}
1715
1716/* time_scale()
1717 * Adjust time type for specified scale factor.
1718 * Used by PostgreSQL type system to stuff columns.
1719 */
1720Datum
1722{
1723 TimeADT time = PG_GETARG_TIMEADT(0);
1724 int32 typmod = PG_GETARG_INT32(1);
1725 TimeADT result;
1726
1727 result = time;
1728 AdjustTimeForTypmod(&result, typmod);
1729
1730 PG_RETURN_TIMEADT(result);
1731}
1732
1733/* AdjustTimeForTypmod()
1734 * Force the precision of the time value to a specified value.
1735 * Uses *exactly* the same code as in AdjustTimestampForTypmod()
1736 * but we make a separate copy because those types do not
1737 * have a fundamental tie together but rather a coincidence of
1738 * implementation. - thomas
1739 */
1740void
1742{
1743 static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
1744 INT64CONST(1000000),
1745 INT64CONST(100000),
1746 INT64CONST(10000),
1747 INT64CONST(1000),
1748 INT64CONST(100),
1749 INT64CONST(10),
1750 INT64CONST(1)
1751 };
1752
1753 static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
1754 INT64CONST(500000),
1755 INT64CONST(50000),
1756 INT64CONST(5000),
1757 INT64CONST(500),
1758 INT64CONST(50),
1759 INT64CONST(5),
1760 INT64CONST(0)
1761 };
1762
1763 if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
1764 {
1765 if (*time >= INT64CONST(0))
1766 *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
1767 TimeScales[typmod];
1768 else
1769 *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
1770 TimeScales[typmod]);
1771 }
1772}
1773
1774
1775Datum
1777{
1778 TimeADT time1 = PG_GETARG_TIMEADT(0);
1779 TimeADT time2 = PG_GETARG_TIMEADT(1);
1780
1781 PG_RETURN_BOOL(time1 == time2);
1782}
1783
1784Datum
1786{
1787 TimeADT time1 = PG_GETARG_TIMEADT(0);
1788 TimeADT time2 = PG_GETARG_TIMEADT(1);
1789
1790 PG_RETURN_BOOL(time1 != time2);
1791}
1792
1793Datum
1795{
1796 TimeADT time1 = PG_GETARG_TIMEADT(0);
1797 TimeADT time2 = PG_GETARG_TIMEADT(1);
1798
1799 PG_RETURN_BOOL(time1 < time2);
1800}
1801
1802Datum
1804{
1805 TimeADT time1 = PG_GETARG_TIMEADT(0);
1806 TimeADT time2 = PG_GETARG_TIMEADT(1);
1807
1808 PG_RETURN_BOOL(time1 <= time2);
1809}
1810
1811Datum
1813{
1814 TimeADT time1 = PG_GETARG_TIMEADT(0);
1815 TimeADT time2 = PG_GETARG_TIMEADT(1);
1816
1817 PG_RETURN_BOOL(time1 > time2);
1818}
1819
1820Datum
1822{
1823 TimeADT time1 = PG_GETARG_TIMEADT(0);
1824 TimeADT time2 = PG_GETARG_TIMEADT(1);
1825
1826 PG_RETURN_BOOL(time1 >= time2);
1827}
1828
1829Datum
1831{
1832 TimeADT time1 = PG_GETARG_TIMEADT(0);
1833 TimeADT time2 = PG_GETARG_TIMEADT(1);
1834
1835 if (time1 < time2)
1836 PG_RETURN_INT32(-1);
1837 if (time1 > time2)
1838 PG_RETURN_INT32(1);
1839 PG_RETURN_INT32(0);
1840}
1841
1842Datum
1844{
1845 return hashint8(fcinfo);
1846}
1847
1848Datum
1850{
1851 return hashint8extended(fcinfo);
1852}
1853
1854Datum
1856{
1857 TimeADT time1 = PG_GETARG_TIMEADT(0);
1858 TimeADT time2 = PG_GETARG_TIMEADT(1);
1859
1860 PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
1861}
1862
1863Datum
1865{
1866 TimeADT time1 = PG_GETARG_TIMEADT(0);
1867 TimeADT time2 = PG_GETARG_TIMEADT(1);
1868
1869 PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
1870}
1871
1872/* overlaps_time() --- implements the SQL OVERLAPS operator.
1873 *
1874 * Algorithm is per SQL spec. This is much harder than you'd think
1875 * because the spec requires us to deliver a non-null answer in some cases
1876 * where some of the inputs are null.
1877 */
1878Datum
1880{
1881 /*
1882 * The arguments are TimeADT, but we leave them as generic Datums to avoid
1883 * dereferencing nulls (TimeADT is pass-by-reference!)
1884 */
1885 Datum ts1 = PG_GETARG_DATUM(0);
1886 Datum te1 = PG_GETARG_DATUM(1);
1887 Datum ts2 = PG_GETARG_DATUM(2);
1888 Datum te2 = PG_GETARG_DATUM(3);
1889 bool ts1IsNull = PG_ARGISNULL(0);
1890 bool te1IsNull = PG_ARGISNULL(1);
1891 bool ts2IsNull = PG_ARGISNULL(2);
1892 bool te2IsNull = PG_ARGISNULL(3);
1893
1894#define TIMEADT_GT(t1,t2) \
1895 (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
1896#define TIMEADT_LT(t1,t2) \
1897 (DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
1898
1899 /*
1900 * If both endpoints of interval 1 are null, the result is null (unknown).
1901 * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
1902 * take ts1 as the lesser endpoint.
1903 */
1904 if (ts1IsNull)
1905 {
1906 if (te1IsNull)
1908 /* swap null for non-null */
1909 ts1 = te1;
1910 te1IsNull = true;
1911 }
1912 else if (!te1IsNull)
1913 {
1914 if (TIMEADT_GT(ts1, te1))
1915 {
1916 Datum tt = ts1;
1917
1918 ts1 = te1;
1919 te1 = tt;
1920 }
1921 }
1922
1923 /* Likewise for interval 2. */
1924 if (ts2IsNull)
1925 {
1926 if (te2IsNull)
1928 /* swap null for non-null */
1929 ts2 = te2;
1930 te2IsNull = true;
1931 }
1932 else if (!te2IsNull)
1933 {
1934 if (TIMEADT_GT(ts2, te2))
1935 {
1936 Datum tt = ts2;
1937
1938 ts2 = te2;
1939 te2 = tt;
1940 }
1941 }
1942
1943 /*
1944 * At this point neither ts1 nor ts2 is null, so we can consider three
1945 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
1946 */
1947 if (TIMEADT_GT(ts1, ts2))
1948 {
1949 /*
1950 * This case is ts1 < te2 OR te1 < te2, which may look redundant but
1951 * in the presence of nulls it's not quite completely so.
1952 */
1953 if (te2IsNull)
1955 if (TIMEADT_LT(ts1, te2))
1956 PG_RETURN_BOOL(true);
1957 if (te1IsNull)
1959
1960 /*
1961 * If te1 is not null then we had ts1 <= te1 above, and we just found
1962 * ts1 >= te2, hence te1 >= te2.
1963 */
1964 PG_RETURN_BOOL(false);
1965 }
1966 else if (TIMEADT_LT(ts1, ts2))
1967 {
1968 /* This case is ts2 < te1 OR te2 < te1 */
1969 if (te1IsNull)
1971 if (TIMEADT_LT(ts2, te1))
1972 PG_RETURN_BOOL(true);
1973 if (te2IsNull)
1975
1976 /*
1977 * If te2 is not null then we had ts2 <= te2 above, and we just found
1978 * ts2 >= te1, hence te2 >= te1.
1979 */
1980 PG_RETURN_BOOL(false);
1981 }
1982 else
1983 {
1984 /*
1985 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
1986 * rather silly way of saying "true if both are nonnull, else null".
1987 */
1988 if (te1IsNull || te2IsNull)
1990 PG_RETURN_BOOL(true);
1991 }
1992
1993#undef TIMEADT_GT
1994#undef TIMEADT_LT
1995}
1996
1997/* timestamp_time()
1998 * Convert timestamp to time data type.
1999 */
2000Datum
2002{
2004 TimeADT result;
2005 struct pg_tm tt,
2006 *tm = &tt;
2007 fsec_t fsec;
2008
2011
2012 if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
2013 ereport(ERROR,
2014 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2015 errmsg("timestamp out of range")));
2016
2017 /*
2018 * Could also do this with time = (timestamp / USECS_PER_DAY *
2019 * USECS_PER_DAY) - timestamp;
2020 */
2021 result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
2022 USECS_PER_SEC) + fsec;
2023
2024 PG_RETURN_TIMEADT(result);
2025}
2026
2027/* timestamptz_time()
2028 * Convert timestamptz to time data type.
2029 */
2030Datum
2032{
2034 TimeADT result;
2035 struct pg_tm tt,
2036 *tm = &tt;
2037 int tz;
2038 fsec_t fsec;
2039
2042
2043 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
2044 ereport(ERROR,
2045 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2046 errmsg("timestamp out of range")));
2047
2048 /*
2049 * Could also do this with time = (timestamp / USECS_PER_DAY *
2050 * USECS_PER_DAY) - timestamp;
2051 */
2052 result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
2053 USECS_PER_SEC) + fsec;
2054
2055 PG_RETURN_TIMEADT(result);
2056}
2057
2058/* datetime_timestamp()
2059 * Convert date and time to timestamp data type.
2060 */
2061Datum
2063{
2065 TimeADT time = PG_GETARG_TIMEADT(1);
2066 Timestamp result;
2067
2068 result = date2timestamp(date);
2069 if (!TIMESTAMP_NOT_FINITE(result))
2070 {
2071 result += time;
2072 if (!IS_VALID_TIMESTAMP(result))
2073 ereport(ERROR,
2074 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2075 errmsg("timestamp out of range")));
2076 }
2077
2078 PG_RETURN_TIMESTAMP(result);
2079}
2080
2081/* time_interval()
2082 * Convert time to interval data type.
2083 */
2084Datum
2086{
2087 TimeADT time = PG_GETARG_TIMEADT(0);
2088 Interval *result;
2089
2090 result = (Interval *) palloc(sizeof(Interval));
2091
2092 result->time = time;
2093 result->day = 0;
2094 result->month = 0;
2095
2096 PG_RETURN_INTERVAL_P(result);
2097}
2098
2099/* interval_time()
2100 * Convert interval to time data type.
2101 *
2102 * This is defined as producing the fractional-day portion of the interval.
2103 * Therefore, we can just ignore the months field. It is not real clear
2104 * what to do with negative intervals, but we choose to subtract the floor,
2105 * so that, say, '-2 hours' becomes '22:00:00'.
2106 */
2107Datum
2109{
2110 Interval *span = PG_GETARG_INTERVAL_P(0);
2111 TimeADT result;
2112
2113 if (INTERVAL_NOT_FINITE(span))
2114 ereport(ERROR,
2115 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2116 errmsg("cannot convert infinite interval to time")));
2117
2118 result = span->time % USECS_PER_DAY;
2119 if (result < 0)
2120 result += USECS_PER_DAY;
2121
2122 PG_RETURN_TIMEADT(result);
2123}
2124
2125/* time_mi_time()
2126 * Subtract two times to produce an interval.
2127 */
2128Datum
2130{
2131 TimeADT time1 = PG_GETARG_TIMEADT(0);
2132 TimeADT time2 = PG_GETARG_TIMEADT(1);
2133 Interval *result;
2134
2135 result = (Interval *) palloc(sizeof(Interval));
2136
2137 result->month = 0;
2138 result->day = 0;
2139 result->time = time1 - time2;
2140
2141 PG_RETURN_INTERVAL_P(result);
2142}
2143
2144/* time_pl_interval()
2145 * Add interval to time.
2146 */
2147Datum
2149{
2150 TimeADT time = PG_GETARG_TIMEADT(0);
2151 Interval *span = PG_GETARG_INTERVAL_P(1);
2152 TimeADT result;
2153
2154 if (INTERVAL_NOT_FINITE(span))
2155 ereport(ERROR,
2156 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2157 errmsg("cannot add infinite interval to time")));
2158
2159 result = time + span->time;
2160 result -= result / USECS_PER_DAY * USECS_PER_DAY;
2161 if (result < INT64CONST(0))
2162 result += USECS_PER_DAY;
2163
2164 PG_RETURN_TIMEADT(result);
2165}
2166
2167/* time_mi_interval()
2168 * Subtract interval from time.
2169 */
2170Datum
2172{
2173 TimeADT time = PG_GETARG_TIMEADT(0);
2174 Interval *span = PG_GETARG_INTERVAL_P(1);
2175 TimeADT result;
2176
2177 if (INTERVAL_NOT_FINITE(span))
2178 ereport(ERROR,
2179 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2180 errmsg("cannot subtract infinite interval from time")));
2181
2182 result = time - span->time;
2183 result -= result / USECS_PER_DAY * USECS_PER_DAY;
2184 if (result < INT64CONST(0))
2185 result += USECS_PER_DAY;
2186
2187 PG_RETURN_TIMEADT(result);
2188}
2189
2190/*
2191 * in_range support function for time.
2192 */
2193Datum
2195{
2197 TimeADT base = PG_GETARG_TIMEADT(1);
2198 Interval *offset = PG_GETARG_INTERVAL_P(2);
2199 bool sub = PG_GETARG_BOOL(3);
2200 bool less = PG_GETARG_BOOL(4);
2201 TimeADT sum;
2202
2203 /*
2204 * Like time_pl_interval/time_mi_interval, we disregard the month and day
2205 * fields of the offset. So our test for negative should too. This also
2206 * catches -infinity, so we only need worry about +infinity below.
2207 */
2208 if (offset->time < 0)
2209 ereport(ERROR,
2210 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2211 errmsg("invalid preceding or following size in window function")));
2212
2213 /*
2214 * We can't use time_pl_interval/time_mi_interval here, because their
2215 * wraparound behavior would give wrong (or at least undesirable) answers.
2216 * Fortunately the equivalent non-wrapping behavior is trivial, except
2217 * that adding an infinite (or very large) interval might cause integer
2218 * overflow. Subtraction cannot overflow here.
2219 */
2220 if (sub)
2221 sum = base - offset->time;
2222 else if (pg_add_s64_overflow(base, offset->time, &sum))
2223 PG_RETURN_BOOL(less);
2224
2225 if (less)
2226 PG_RETURN_BOOL(val <= sum);
2227 else
2228 PG_RETURN_BOOL(val >= sum);
2229}
2230
2231
2232/* time_part() and extract_time()
2233 * Extract specified field from time type.
2234 */
2235static Datum
2237{
2238 text *units = PG_GETARG_TEXT_PP(0);
2239 TimeADT time = PG_GETARG_TIMEADT(1);
2240 int64 intresult;
2241 int type,
2242 val;
2243 char *lowunits;
2244
2245 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
2246 VARSIZE_ANY_EXHDR(units),
2247 false);
2248
2249 type = DecodeUnits(0, lowunits, &val);
2250 if (type == UNKNOWN_FIELD)
2251 type = DecodeSpecial(0, lowunits, &val);
2252
2253 if (type == UNITS)
2254 {
2255 fsec_t fsec;
2256 struct pg_tm tt,
2257 *tm = &tt;
2258
2259 time2tm(time, tm, &fsec);
2260
2261 switch (val)
2262 {
2263 case DTK_MICROSEC:
2264 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
2265 break;
2266
2267 case DTK_MILLISEC:
2268 if (retnumeric)
2269 /*---
2270 * tm->tm_sec * 1000 + fsec / 1000
2271 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
2272 */
2274 else
2275 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
2276 break;
2277
2278 case DTK_SECOND:
2279 if (retnumeric)
2280 /*---
2281 * tm->tm_sec + fsec / 1'000'000
2282 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
2283 */
2285 else
2286 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
2287 break;
2288
2289 case DTK_MINUTE:
2290 intresult = tm->tm_min;
2291 break;
2292
2293 case DTK_HOUR:
2294 intresult = tm->tm_hour;
2295 break;
2296
2297 case DTK_TZ:
2298 case DTK_TZ_MINUTE:
2299 case DTK_TZ_HOUR:
2300 case DTK_DAY:
2301 case DTK_MONTH:
2302 case DTK_QUARTER:
2303 case DTK_YEAR:
2304 case DTK_DECADE:
2305 case DTK_CENTURY:
2306 case DTK_MILLENNIUM:
2307 case DTK_ISOYEAR:
2308 default:
2309 ereport(ERROR,
2310 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2311 errmsg("unit \"%s\" not supported for type %s",
2312 lowunits, format_type_be(TIMEOID))));
2313 intresult = 0;
2314 }
2315 }
2316 else if (type == RESERV && val == DTK_EPOCH)
2317 {
2318 if (retnumeric)
2320 else
2321 PG_RETURN_FLOAT8(time / 1000000.0);
2322 }
2323 else
2324 {
2325 ereport(ERROR,
2326 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2327 errmsg("unit \"%s\" not recognized for type %s",
2328 lowunits, format_type_be(TIMEOID))));
2329 intresult = 0;
2330 }
2331
2332 if (retnumeric)
2334 else
2335 PG_RETURN_FLOAT8(intresult);
2336}
2337
2338Datum
2340{
2341 return time_part_common(fcinfo, false);
2342}
2343
2344Datum
2346{
2347 return time_part_common(fcinfo, true);
2348}
2349
2350
2351/*****************************************************************************
2352 * Time With Time Zone ADT
2353 *****************************************************************************/
2354
2355/* tm2timetz()
2356 * Convert a tm structure to a time data type.
2357 */
2358int
2359tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
2360{
2361 result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
2362 USECS_PER_SEC) + fsec;
2363 result->zone = tz;
2364
2365 return 0;
2366}
2367
2368Datum
2370{
2371 char *str = PG_GETARG_CSTRING(0);
2372#ifdef NOT_USED
2373 Oid typelem = PG_GETARG_OID(1);
2374#endif
2375 int32 typmod = PG_GETARG_INT32(2);
2376 Node *escontext = fcinfo->context;
2377 TimeTzADT *result;
2378 fsec_t fsec;
2379 struct pg_tm tt,
2380 *tm = &tt;
2381 int tz;
2382 int nf;
2383 int dterr;
2384 char workbuf[MAXDATELEN + 1];
2385 char *field[MAXDATEFIELDS];
2386 int dtype;
2387 int ftype[MAXDATEFIELDS];
2388 DateTimeErrorExtra extra;
2389
2390 dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
2391 field, ftype, MAXDATEFIELDS, &nf);
2392 if (dterr == 0)
2393 dterr = DecodeTimeOnly(field, ftype, nf,
2394 &dtype, tm, &fsec, &tz, &extra);
2395 if (dterr != 0)
2396 {
2397 DateTimeParseError(dterr, &extra, str, "time with time zone",
2398 escontext);
2400 }
2401
2402 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2403 tm2timetz(tm, fsec, tz, result);
2404 AdjustTimeForTypmod(&(result->time), typmod);
2405
2406 PG_RETURN_TIMETZADT_P(result);
2407}
2408
2409Datum
2411{
2413 char *result;
2414 struct pg_tm tt,
2415 *tm = &tt;
2416 fsec_t fsec;
2417 int tz;
2418 char buf[MAXDATELEN + 1];
2419
2420 timetz2tm(time, tm, &fsec, &tz);
2421 EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
2422
2423 result = pstrdup(buf);
2424 PG_RETURN_CSTRING(result);
2425}
2426
2427/*
2428 * timetz_recv - converts external binary format to timetz
2429 */
2430Datum
2432{
2434
2435#ifdef NOT_USED
2436 Oid typelem = PG_GETARG_OID(1);
2437#endif
2438 int32 typmod = PG_GETARG_INT32(2);
2439 TimeTzADT *result;
2440
2441 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2442
2443 result->time = pq_getmsgint64(buf);
2444
2445 if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
2446 ereport(ERROR,
2447 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2448 errmsg("time out of range")));
2449
2450 result->zone = pq_getmsgint(buf, sizeof(result->zone));
2451
2452 /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
2453 if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
2454 ereport(ERROR,
2455 (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
2456 errmsg("time zone displacement out of range")));
2457
2458 AdjustTimeForTypmod(&(result->time), typmod);
2459
2460 PG_RETURN_TIMETZADT_P(result);
2461}
2462
2463/*
2464 * timetz_send - converts timetz to binary format
2465 */
2466Datum
2468{
2471
2473 pq_sendint64(&buf, time->time);
2474 pq_sendint32(&buf, time->zone);
2476}
2477
2478Datum
2480{
2482
2484}
2485
2486Datum
2488{
2489 int32 typmod = PG_GETARG_INT32(0);
2490
2491 PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
2492}
2493
2494
2495/* timetz2tm()
2496 * Convert TIME WITH TIME ZONE data type to POSIX time structure.
2497 */
2498int
2499timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
2500{
2501 TimeOffset trem = time->time;
2502
2503 tm->tm_hour = trem / USECS_PER_HOUR;
2504 trem -= tm->tm_hour * USECS_PER_HOUR;
2505 tm->tm_min = trem / USECS_PER_MINUTE;
2506 trem -= tm->tm_min * USECS_PER_MINUTE;
2507 tm->tm_sec = trem / USECS_PER_SEC;
2508 *fsec = trem - tm->tm_sec * USECS_PER_SEC;
2509
2510 if (tzp != NULL)
2511 *tzp = time->zone;
2512
2513 return 0;
2514}
2515
2516/* timetz_scale()
2517 * Adjust time type for specified scale factor.
2518 * Used by PostgreSQL type system to stuff columns.
2519 */
2520Datum
2522{
2524 int32 typmod = PG_GETARG_INT32(1);
2525 TimeTzADT *result;
2526
2527 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2528
2529 result->time = time->time;
2530 result->zone = time->zone;
2531
2532 AdjustTimeForTypmod(&(result->time), typmod);
2533
2534 PG_RETURN_TIMETZADT_P(result);
2535}
2536
2537
2538static int
2540{
2541 TimeOffset t1,
2542 t2;
2543
2544 /* Primary sort is by true (GMT-equivalent) time */
2545 t1 = time1->time + (time1->zone * USECS_PER_SEC);
2546 t2 = time2->time + (time2->zone * USECS_PER_SEC);
2547
2548 if (t1 > t2)
2549 return 1;
2550 if (t1 < t2)
2551 return -1;
2552
2553 /*
2554 * If same GMT time, sort by timezone; we only want to say that two
2555 * timetz's are equal if both the time and zone parts are equal.
2556 */
2557 if (time1->zone > time2->zone)
2558 return 1;
2559 if (time1->zone < time2->zone)
2560 return -1;
2561
2562 return 0;
2563}
2564
2565Datum
2567{
2568 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2569 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2570
2571 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
2572}
2573
2574Datum
2576{
2577 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2578 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2579
2580 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
2581}
2582
2583Datum
2585{
2586 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2587 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2588
2589 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
2590}
2591
2592Datum
2594{
2595 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2596 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2597
2598 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
2599}
2600
2601Datum
2603{
2604 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2605 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2606
2607 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
2608}
2609
2610Datum
2612{
2613 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2614 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2615
2616 PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
2617}
2618
2619Datum
2621{
2622 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2623 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2624
2625 PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
2626}
2627
2628Datum
2630{
2632 uint32 thash;
2633
2634 /*
2635 * To avoid any problems with padding bytes in the struct, we figure the
2636 * field hashes separately and XOR them.
2637 */
2639 Int64GetDatumFast(key->time)));
2640 thash ^= DatumGetUInt32(hash_uint32(key->zone));
2641 PG_RETURN_UINT32(thash);
2642}
2643
2644Datum
2646{
2648 Datum seed = PG_GETARG_DATUM(1);
2649 uint64 thash;
2650
2651 /* Same approach as timetz_hash */
2653 Int64GetDatumFast(key->time),
2654 seed));
2656 DatumGetInt64(seed)));
2657 PG_RETURN_UINT64(thash);
2658}
2659
2660Datum
2662{
2663 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2664 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2665 TimeTzADT *result;
2666
2667 if (timetz_cmp_internal(time1, time2) > 0)
2668 result = time1;
2669 else
2670 result = time2;
2671 PG_RETURN_TIMETZADT_P(result);
2672}
2673
2674Datum
2676{
2677 TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2678 TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2679 TimeTzADT *result;
2680
2681 if (timetz_cmp_internal(time1, time2) < 0)
2682 result = time1;
2683 else
2684 result = time2;
2685 PG_RETURN_TIMETZADT_P(result);
2686}
2687
2688/* timetz_pl_interval()
2689 * Add interval to timetz.
2690 */
2691Datum
2693{
2695 Interval *span = PG_GETARG_INTERVAL_P(1);
2696 TimeTzADT *result;
2697
2698 if (INTERVAL_NOT_FINITE(span))
2699 ereport(ERROR,
2700 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2701 errmsg("cannot add infinite interval to time")));
2702
2703 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2704
2705 result->time = time->time + span->time;
2706 result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2707 if (result->time < INT64CONST(0))
2708 result->time += USECS_PER_DAY;
2709
2710 result->zone = time->zone;
2711
2712 PG_RETURN_TIMETZADT_P(result);
2713}
2714
2715/* timetz_mi_interval()
2716 * Subtract interval from timetz.
2717 */
2718Datum
2720{
2722 Interval *span = PG_GETARG_INTERVAL_P(1);
2723 TimeTzADT *result;
2724
2725 if (INTERVAL_NOT_FINITE(span))
2726 ereport(ERROR,
2727 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2728 errmsg("cannot subtract infinite interval from time")));
2729
2730 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2731
2732 result->time = time->time - span->time;
2733 result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2734 if (result->time < INT64CONST(0))
2735 result->time += USECS_PER_DAY;
2736
2737 result->zone = time->zone;
2738
2739 PG_RETURN_TIMETZADT_P(result);
2740}
2741
2742/*
2743 * in_range support function for timetz.
2744 */
2745Datum
2747{
2750 Interval *offset = PG_GETARG_INTERVAL_P(2);
2751 bool sub = PG_GETARG_BOOL(3);
2752 bool less = PG_GETARG_BOOL(4);
2753 TimeTzADT sum;
2754
2755 /*
2756 * Like timetz_pl_interval/timetz_mi_interval, we disregard the month and
2757 * day fields of the offset. So our test for negative should too. This
2758 * also catches -infinity, so we only need worry about +infinity below.
2759 */
2760 if (offset->time < 0)
2761 ereport(ERROR,
2762 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2763 errmsg("invalid preceding or following size in window function")));
2764
2765 /*
2766 * We can't use timetz_pl_interval/timetz_mi_interval here, because their
2767 * wraparound behavior would give wrong (or at least undesirable) answers.
2768 * Fortunately the equivalent non-wrapping behavior is trivial, except
2769 * that adding an infinite (or very large) interval might cause integer
2770 * overflow. Subtraction cannot overflow here.
2771 */
2772 if (sub)
2773 sum.time = base->time - offset->time;
2774 else if (pg_add_s64_overflow(base->time, offset->time, &sum.time))
2775 PG_RETURN_BOOL(less);
2776 sum.zone = base->zone;
2777
2778 if (less)
2780 else
2782}
2783
2784/* overlaps_timetz() --- implements the SQL OVERLAPS operator.
2785 *
2786 * Algorithm is per SQL spec. This is much harder than you'd think
2787 * because the spec requires us to deliver a non-null answer in some cases
2788 * where some of the inputs are null.
2789 */
2790Datum
2792{
2793 /*
2794 * The arguments are TimeTzADT *, but we leave them as generic Datums for
2795 * convenience of notation --- and to avoid dereferencing nulls.
2796 */
2797 Datum ts1 = PG_GETARG_DATUM(0);
2798 Datum te1 = PG_GETARG_DATUM(1);
2799 Datum ts2 = PG_GETARG_DATUM(2);
2800 Datum te2 = PG_GETARG_DATUM(3);
2801 bool ts1IsNull = PG_ARGISNULL(0);
2802 bool te1IsNull = PG_ARGISNULL(1);
2803 bool ts2IsNull = PG_ARGISNULL(2);
2804 bool te2IsNull = PG_ARGISNULL(3);
2805
2806#define TIMETZ_GT(t1,t2) \
2807 DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
2808#define TIMETZ_LT(t1,t2) \
2809 DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
2810
2811 /*
2812 * If both endpoints of interval 1 are null, the result is null (unknown).
2813 * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2814 * take ts1 as the lesser endpoint.
2815 */
2816 if (ts1IsNull)
2817 {
2818 if (te1IsNull)
2820 /* swap null for non-null */
2821 ts1 = te1;
2822 te1IsNull = true;
2823 }
2824 else if (!te1IsNull)
2825 {
2826 if (TIMETZ_GT(ts1, te1))
2827 {
2828 Datum tt = ts1;
2829
2830 ts1 = te1;
2831 te1 = tt;
2832 }
2833 }
2834
2835 /* Likewise for interval 2. */
2836 if (ts2IsNull)
2837 {
2838 if (te2IsNull)
2840 /* swap null for non-null */
2841 ts2 = te2;
2842 te2IsNull = true;
2843 }
2844 else if (!te2IsNull)
2845 {
2846 if (TIMETZ_GT(ts2, te2))
2847 {
2848 Datum tt = ts2;
2849
2850 ts2 = te2;
2851 te2 = tt;
2852 }
2853 }
2854
2855 /*
2856 * At this point neither ts1 nor ts2 is null, so we can consider three
2857 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2858 */
2859 if (TIMETZ_GT(ts1, ts2))
2860 {
2861 /*
2862 * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2863 * in the presence of nulls it's not quite completely so.
2864 */
2865 if (te2IsNull)
2867 if (TIMETZ_LT(ts1, te2))
2868 PG_RETURN_BOOL(true);
2869 if (te1IsNull)
2871
2872 /*
2873 * If te1 is not null then we had ts1 <= te1 above, and we just found
2874 * ts1 >= te2, hence te1 >= te2.
2875 */
2876 PG_RETURN_BOOL(false);
2877 }
2878 else if (TIMETZ_LT(ts1, ts2))
2879 {
2880 /* This case is ts2 < te1 OR te2 < te1 */
2881 if (te1IsNull)
2883 if (TIMETZ_LT(ts2, te1))
2884 PG_RETURN_BOOL(true);
2885 if (te2IsNull)
2887
2888 /*
2889 * If te2 is not null then we had ts2 <= te2 above, and we just found
2890 * ts2 >= te1, hence te2 >= te1.
2891 */
2892 PG_RETURN_BOOL(false);
2893 }
2894 else
2895 {
2896 /*
2897 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2898 * rather silly way of saying "true if both are nonnull, else null".
2899 */
2900 if (te1IsNull || te2IsNull)
2902 PG_RETURN_BOOL(true);
2903 }
2904
2905#undef TIMETZ_GT
2906#undef TIMETZ_LT
2907}
2908
2909
2910Datum
2912{
2913 TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
2914 TimeADT result;
2915
2916 /* swallow the time zone and just return the time */
2917 result = timetz->time;
2918
2919 PG_RETURN_TIMEADT(result);
2920}
2921
2922
2923Datum
2925{
2926 TimeADT time = PG_GETARG_TIMEADT(0);
2927 TimeTzADT *result;
2928 struct pg_tm tt,
2929 *tm = &tt;
2930 fsec_t fsec;
2931 int tz;
2932
2934 time2tm(time, tm, &fsec);
2936
2937 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2938
2939 result->time = time;
2940 result->zone = tz;
2941
2942 PG_RETURN_TIMETZADT_P(result);
2943}
2944
2945
2946/* timestamptz_timetz()
2947 * Convert timestamp to timetz data type.
2948 */
2949Datum
2951{
2953 TimeTzADT *result;
2954 struct pg_tm tt,
2955 *tm = &tt;
2956 int tz;
2957 fsec_t fsec;
2958
2961
2962 if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
2963 ereport(ERROR,
2964 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2965 errmsg("timestamp out of range")));
2966
2967 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2968
2969 tm2timetz(tm, fsec, tz, result);
2970
2971 PG_RETURN_TIMETZADT_P(result);
2972}
2973
2974
2975/* datetimetz_timestamptz()
2976 * Convert date and timetz to timestamp with time zone data type.
2977 * Timestamp is stored in GMT, so add the time zone
2978 * stored with the timetz to the result.
2979 * - thomas 2000-03-10
2980 */
2981Datum
2983{
2986 TimestampTz result;
2987
2988 if (DATE_IS_NOBEGIN(date))
2989 TIMESTAMP_NOBEGIN(result);
2990 else if (DATE_IS_NOEND(date))
2991 TIMESTAMP_NOEND(result);
2992 else
2993 {
2994 /*
2995 * Date's range is wider than timestamp's, so check for boundaries.
2996 * Since dates have the same minimum values as timestamps, only upper
2997 * boundary need be checked for overflow.
2998 */
3000 ereport(ERROR,
3001 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3002 errmsg("date out of range for timestamp")));
3003 result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
3004
3005 /*
3006 * Since it is possible to go beyond allowed timestamptz range because
3007 * of time zone, check for allowed timestamp range after adding tz.
3008 */
3009 if (!IS_VALID_TIMESTAMP(result))
3010 ereport(ERROR,
3011 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3012 errmsg("date out of range for timestamp")));
3013 }
3014
3015 PG_RETURN_TIMESTAMP(result);
3016}
3017
3018
3019/* timetz_part() and extract_timetz()
3020 * Extract specified field from time type.
3021 */
3022static Datum
3024{
3025 text *units = PG_GETARG_TEXT_PP(0);
3027 int64 intresult;
3028 int type,
3029 val;
3030 char *lowunits;
3031
3032 lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
3033 VARSIZE_ANY_EXHDR(units),
3034 false);
3035
3036 type = DecodeUnits(0, lowunits, &val);
3037 if (type == UNKNOWN_FIELD)
3038 type = DecodeSpecial(0, lowunits, &val);
3039
3040 if (type == UNITS)
3041 {
3042 int tz;
3043 fsec_t fsec;
3044 struct pg_tm tt,
3045 *tm = &tt;
3046
3047 timetz2tm(time, tm, &fsec, &tz);
3048
3049 switch (val)
3050 {
3051 case DTK_TZ:
3052 intresult = -tz;
3053 break;
3054
3055 case DTK_TZ_MINUTE:
3056 intresult = (-tz / SECS_PER_MINUTE) % MINS_PER_HOUR;
3057 break;
3058
3059 case DTK_TZ_HOUR:
3060 intresult = -tz / SECS_PER_HOUR;
3061 break;
3062
3063 case DTK_MICROSEC:
3064 intresult = tm->tm_sec * INT64CONST(1000000) + fsec;
3065 break;
3066
3067 case DTK_MILLISEC:
3068 if (retnumeric)
3069 /*---
3070 * tm->tm_sec * 1000 + fsec / 1000
3071 * = (tm->tm_sec * 1'000'000 + fsec) / 1000
3072 */
3074 else
3075 PG_RETURN_FLOAT8(tm->tm_sec * 1000.0 + fsec / 1000.0);
3076 break;
3077
3078 case DTK_SECOND:
3079 if (retnumeric)
3080 /*---
3081 * tm->tm_sec + fsec / 1'000'000
3082 * = (tm->tm_sec * 1'000'000 + fsec) / 1'000'000
3083 */
3085 else
3086 PG_RETURN_FLOAT8(tm->tm_sec + fsec / 1000000.0);
3087 break;
3088
3089 case DTK_MINUTE:
3090 intresult = tm->tm_min;
3091 break;
3092
3093 case DTK_HOUR:
3094 intresult = tm->tm_hour;
3095 break;
3096
3097 case DTK_DAY:
3098 case DTK_MONTH:
3099 case DTK_QUARTER:
3100 case DTK_YEAR:
3101 case DTK_DECADE:
3102 case DTK_CENTURY:
3103 case DTK_MILLENNIUM:
3104 default:
3105 ereport(ERROR,
3106 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3107 errmsg("unit \"%s\" not supported for type %s",
3108 lowunits, format_type_be(TIMETZOID))));
3109 intresult = 0;
3110 }
3111 }
3112 else if (type == RESERV && val == DTK_EPOCH)
3113 {
3114 if (retnumeric)
3115 /*---
3116 * time->time / 1'000'000 + time->zone
3117 * = (time->time + time->zone * 1'000'000) / 1'000'000
3118 */
3119 PG_RETURN_NUMERIC(int64_div_fast_to_numeric(time->time + time->zone * INT64CONST(1000000), 6));
3120 else
3121 PG_RETURN_FLOAT8(time->time / 1000000.0 + time->zone);
3122 }
3123 else
3124 {
3125 ereport(ERROR,
3126 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3127 errmsg("unit \"%s\" not recognized for type %s",
3128 lowunits, format_type_be(TIMETZOID))));
3129 intresult = 0;
3130 }
3131
3132 if (retnumeric)
3134 else
3135 PG_RETURN_FLOAT8(intresult);
3136}
3137
3138
3139Datum
3141{
3142 return timetz_part_common(fcinfo, false);
3143}
3144
3145Datum
3147{
3148 return timetz_part_common(fcinfo, true);
3149}
3150
3151/* timetz_zone()
3152 * Encode time with time zone type with specified time zone.
3153 * Applies DST rules as of the transaction start time.
3154 */
3155Datum
3157{
3160 TimeTzADT *result;
3161 int tz;
3162 char tzname[TZ_STRLEN_MAX + 1];
3163 int type,
3164 val;
3165 pg_tz *tzp;
3166
3167 /*
3168 * Look up the requested timezone.
3169 */
3170 text_to_cstring_buffer(zone, tzname, sizeof(tzname));
3171
3172 type = DecodeTimezoneName(tzname, &val, &tzp);
3173
3175 {
3176 /* fixed-offset abbreviation */
3177 tz = -val;
3178 }
3179 else if (type == TZNAME_DYNTZ)
3180 {
3181 /* dynamic-offset abbreviation, resolve using transaction start time */
3183 int isdst;
3184
3185 tz = DetermineTimeZoneAbbrevOffsetTS(now, tzname, tzp, &isdst);
3186 }
3187 else
3188 {
3189 /* Get the offset-from-GMT that is valid now for the zone name */
3191 struct pg_tm tm;
3192 fsec_t fsec;
3193
3194 if (timestamp2tm(now, &tz, &tm, &fsec, NULL, tzp) != 0)
3195 ereport(ERROR,
3196 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3197 errmsg("timestamp out of range")));
3198 }
3199
3200 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
3201
3202 result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
3203 /* C99 modulo has the wrong sign convention for negative input */
3204 while (result->time < INT64CONST(0))
3205 result->time += USECS_PER_DAY;
3206 if (result->time >= USECS_PER_DAY)
3207 result->time %= USECS_PER_DAY;
3208
3209 result->zone = tz;
3210
3211 PG_RETURN_TIMETZADT_P(result);
3212}
3213
3214/* timetz_izone()
3215 * Encode time with time zone type with specified time interval as time zone.
3216 */
3217Datum
3219{
3222 TimeTzADT *result;
3223 int tz;
3224
3226 ereport(ERROR,
3227 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3228 errmsg("interval time zone \"%s\" must be finite",
3230 PointerGetDatum(zone))))));
3231
3232 if (zone->month != 0 || zone->day != 0)
3233 ereport(ERROR,
3234 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3235 errmsg("interval time zone \"%s\" must not include months or days",
3237 PointerGetDatum(zone))))));
3238
3239 tz = -(zone->time / USECS_PER_SEC);
3240
3241 result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
3242
3243 result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
3244 /* C99 modulo has the wrong sign convention for negative input */
3245 while (result->time < INT64CONST(0))
3246 result->time += USECS_PER_DAY;
3247 if (result->time >= USECS_PER_DAY)
3248 result->time %= USECS_PER_DAY;
3249
3250 result->zone = tz;
3251
3252 PG_RETURN_TIMETZADT_P(result);
3253}
3254
3255/* timetz_at_local()
3256 *
3257 * Unlike for timestamp[tz]_at_local, the type for timetz does not flip between
3258 * time with/without time zone, so we cannot just call the conversion function.
3259 */
3260Datum
3262{
3263 Datum time = PG_GETARG_DATUM(0);
3264 const char *tzn = pg_get_timezone_name(session_timezone);
3266
3267 return DirectFunctionCall2(timetz_zone, zone, time);
3268}
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
int32 * ArrayGetIntegerTypmods(ArrayType *arr, int *n)
Definition: arrayutils.c:233
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4962
int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
Definition: datetime.c:1803
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:4169
int DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:1917
int j2day(int date)
Definition: datetime.c:354
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:773
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1604
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:4214
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4434
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2561
int DecodeSpecial(int field, const char *lowtoken, int *val)
Definition: datetime.c:3246
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:321
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:376
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4349
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:997
int date2j(int year, int month, int day)
Definition: datetime.c:296
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:397
const char *const days[]
Definition: datetime.c:84
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3288
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4260
Numeric int64_div_fast_to_numeric(int64 val1, int log10val2)
Definition: numeric.c:4281
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:626
Datum interval_out(PG_FUNCTION_ARGS)
Definition: timestamp.c:973
int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
Definition: timestamp.c:2210
Datum in_range_timestamp_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3873
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2168
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3087
int date2isoweek(int year, int mon, int mday)
Definition: timestamp.c:5292
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:3204
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1910
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1609
int date2isoyear(int year, int mon, int mday)
Definition: timestamp.c:5347
#define INT64CONST(x)
Definition: c.h:557
int64_t int64
Definition: c.h:540
int32_t int32
Definition: c.h:539
uint64_t uint64
Definition: c.h:544
uint32_t uint32
Definition: c.h:543
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define IS_VALID_DATE(d)
Definition: timestamp.h:262
int32 fsec_t
Definition: timestamp.h:41
#define INTERVAL_NOT_FINITE(i)
Definition: timestamp.h:195
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:159
#define USECS_PER_HOUR
Definition: timestamp.h:132
#define TIMESTAMP_END_JULIAN
Definition: timestamp.h:253
#define MINS_PER_HOUR
Definition: timestamp.h:129
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define TZDISP_LIMIT
Definition: timestamp.h:144
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:267
#define SECS_PER_MINUTE
Definition: timestamp.h:128
#define USECS_PER_DAY
Definition: timestamp.h:131
#define USECS_PER_SEC
Definition: timestamp.h:134
#define HOURS_PER_DAY
Definition: timestamp.h:118
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:167
#define USECS_PER_MINUTE
Definition: timestamp.h:133
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:162
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:234
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define SECS_PER_DAY
Definition: timestamp.h:126
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
#define TIMESTAMP_NOEND(j)
Definition: timestamp.h:164
#define MIN_TIMESTAMP
Definition: timestamp.h:256
int64 TimeOffset
Definition: timestamp.h:40
Datum timestamp_eq_date(PG_FUNCTION_ARGS)
Definition: date.c:945
int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2)
Definition: date.c:776
Datum date_send(PG_FUNCTION_ARGS)
Definition: date.c:233
Datum timetz_izone(PG_FUNCTION_ARGS)
Definition: date.c:3218
Timestamp date2timestamp_safe(DateADT dateVal, Node *escontext)
Definition: date.c:630
int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: date.c:2499
Datum timestamp_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:954
Datum date_ne_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:891
Datum date_sortsupport(PG_FUNCTION_ARGS)
Definition: date.c:459
Datum date_cmp(PG_FUNCTION_ARGS)
Definition: date.c:446
Datum date_le(PG_FUNCTION_ARGS)
Definition: date.c:419
Datum time_part(PG_FUNCTION_ARGS)
Definition: date.c:2339
Datum time_eq(PG_FUNCTION_ARGS)
Definition: date.c:1776
Datum timetz_send(PG_FUNCTION_ARGS)
Definition: date.c:2467
Datum timetztypmodout(PG_FUNCTION_ARGS)
Definition: date.c:2487
#define TIMETZ_GT(t1, t2)
Datum timestamp_ge_date(PG_FUNCTION_ARGS)
Definition: date.c:990
static char * anytime_typmodout(bool istz, int32 typmod)
Definition: date.c:95
Datum timetz_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:2692
Datum timetz_smaller(PG_FUNCTION_ARGS)
Definition: date.c:2675
Datum timetypmodin(PG_FUNCTION_ARGS)
Definition: date.c:1654
Datum date_lt_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:900
Datum make_time(PG_FUNCTION_ARGS)
Definition: date.c:1673
static Datum date_decrement(Relation rel, Datum existing, bool *underflow)
Definition: date.c:468
Datum date_larger(PG_FUNCTION_ARGS)
Definition: date.c:533
Datum in_range_time_interval(PG_FUNCTION_ARGS)
Definition: date.c:2194
Datum date_gt_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:909
Datum date_lt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:812
Datum timetz_ne(PG_FUNCTION_ARGS)
Definition: date.c:2575
Datum time_interval(PG_FUNCTION_ARGS)
Definition: date.c:2085
Datum date_eq(PG_FUNCTION_ARGS)
Definition: date.c:392
Datum timetz_larger(PG_FUNCTION_ARGS)
Definition: date.c:2661
Datum time_le(PG_FUNCTION_ARGS)
Definition: date.c:1803
Datum timetz_part(PG_FUNCTION_ARGS)
Definition: date.c:3140
Datum in_range_timetz_interval(PG_FUNCTION_ARGS)
Definition: date.c:2746
Datum extract_time(PG_FUNCTION_ARGS)
Definition: date.c:2345
Datum interval_time(PG_FUNCTION_ARGS)
Definition: date.c:2108
TimestampTz date2timestamptz_safe(DateADT dateVal, Node *escontext)
Definition: date.c:679
Datum date_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:1304
Datum hashdateextended(PG_FUNCTION_ARGS)
Definition: date.c:519
Datum date_eq_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:882
bool float_time_overflows(int hour, int min, double sec)
Definition: date.c:1547
Datum timetz_gt(PG_FUNCTION_ARGS)
Definition: date.c:2602
Datum timetz_at_local(PG_FUNCTION_ARGS)
Definition: date.c:3261
Datum timestamp_gt_date(PG_FUNCTION_ARGS)
Definition: date.c:972
Datum date_finite(PG_FUNCTION_ARGS)
Definition: date.c:525
DateADT timestamp2date_safe(Timestamp timestamp, Node *escontext)
Definition: date.c:1358
Datum in_range_date_interval(PG_FUNCTION_ARGS)
Definition: date.c:1077
Datum time_cmp(PG_FUNCTION_ARGS)
Definition: date.c:1830
Datum timestamp_time(PG_FUNCTION_ARGS)
Definition: date.c:2001
Datum time_mi_time(PG_FUNCTION_ARGS)
Definition: date.c:2129
Datum time_ge(PG_FUNCTION_ARGS)
Definition: date.c:1821
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition: date.c:73
#define TIMEADT_GT(t1, t2)
Datum datetime_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:2062
static Datum timetz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: date.c:3023
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:1394
Datum date_ne_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:803
Datum timestamptz_ge_date(PG_FUNCTION_ARGS)
Definition: date.c:1053
Datum date_eq_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:794
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1512
Datum timetz_ge(PG_FUNCTION_ARGS)
Definition: date.c:2611
Datum timestamp_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:963
Datum timestamptz_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:1026
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2620
TimeADT GetSQLLocalTime(int32 typmod)
Definition: date.c:371
Datum timetztypmodin(PG_FUNCTION_ARGS)
Definition: date.c:2479
Datum timetz_recv(PG_FUNCTION_ARGS)
Definition: date.c:2431
static TimestampTz date2timestamptz(DateADT dateVal)
Definition: date.c:737
Datum time_recv(PG_FUNCTION_ARGS)
Definition: date.c:1617
Datum time_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:2171
Datum time_support(PG_FUNCTION_ARGS)
Definition: date.c:1701
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2359
Datum date_out(PG_FUNCTION_ARGS)
Definition: date.c:186
DateADT timestamptz2date_safe(TimestampTz timestamp, Node *escontext)
Definition: date.c:1432
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2911
Datum timetz_in(PG_FUNCTION_ARGS)
Definition: date.c:2369
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2924
Datum time_lt(PG_FUNCTION_ARGS)
Definition: date.c:1794
Datum date_in(PG_FUNCTION_ARGS)
Definition: date.c:115
Datum date_gt(PG_FUNCTION_ARGS)
Definition: date.c:428
bool time_overflows(int hour, int min, int sec, fsec_t fsec)
Definition: date.c:1523
Datum timetz_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:2719
Datum extract_timetz(PG_FUNCTION_ARGS)
Definition: date.c:3146
Datum date_ge_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:839
static int32 anytime_typmodin(bool istz, ArrayType *ta)
Definition: date.c:52
Datum date_mii(PG_FUNCTION_ARGS)
Definition: date.c:594
Datum date_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:1284
Datum overlaps_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2791
static Datum time_part_common(PG_FUNCTION_ARGS, bool retnumeric)
Definition: date.c:2236
Datum time_gt(PG_FUNCTION_ARGS)
Definition: date.c:1812
Datum date_recv(PG_FUNCTION_ARGS)
Definition: date.c:211
Datum timetz_lt(PG_FUNCTION_ARGS)
Definition: date.c:2584
Datum time_out(PG_FUNCTION_ARGS)
Definition: date.c:1597
Datum date_cmp_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:848
Datum time_hash(PG_FUNCTION_ARGS)
Definition: date.c:1843
Datum time_larger(PG_FUNCTION_ARGS)
Definition: date.c:1855
#define TIMETZ_LT(t1, t2)
Datum time_smaller(PG_FUNCTION_ARGS)
Definition: date.c:1864
Datum time_ne(PG_FUNCTION_ARGS)
Definition: date.c:1785
DateADT GetSQLCurrentDate(void)
Definition: date.c:318
Datum timetz_eq(PG_FUNCTION_ARGS)
Definition: date.c:2566
Datum date_gt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:821
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2950
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1741
Datum date_le_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:918
Datum date_pli(PG_FUNCTION_ARGS)
Definition: date.c:570
Datum extract_date(PG_FUNCTION_ARGS)
Definition: date.c:1104
Datum timestamptz_date(PG_FUNCTION_ARGS)
Definition: date.c:1409
Datum timetz_le(PG_FUNCTION_ARGS)
Definition: date.c:2593
Datum date_lt(PG_FUNCTION_ARGS)
Definition: date.c:410
Datum timetz_hash(PG_FUNCTION_ARGS)
Definition: date.c:2629
static Datum date_increment(Relation rel, Datum existing, bool *overflow)
Definition: date.c:484
static TimestampTz date2timestamp(DateADT dateVal)
Definition: date.c:663
static int timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
Definition: date.c:2539
Datum timestamptz_gt_date(PG_FUNCTION_ARGS)
Definition: date.c:1035
Datum hashdate(PG_FUNCTION_ARGS)
Definition: date.c:513
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition: date.c:1335
Datum date_ge(PG_FUNCTION_ARGS)
Definition: date.c:437
Datum time_in(PG_FUNCTION_ARGS)
Definition: date.c:1470
Datum time_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:1849
Datum time_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:2148
Datum datetimetz_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:2982
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1584
Datum timestamptz_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:1017
Datum date_smaller(PG_FUNCTION_ARGS)
Definition: date.c:542
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:303
Datum timestamp_le_date(PG_FUNCTION_ARGS)
Definition: date.c:981
Datum timetypmodout(PG_FUNCTION_ARGS)
Definition: date.c:1662
Datum timestamptz_eq_date(PG_FUNCTION_ARGS)
Definition: date.c:1008
Datum timetz_scale(PG_FUNCTION_ARGS)
Definition: date.c:2521
Datum timestamptz_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:1062
Datum date_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:927
Datum timetz_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:2645
Datum date_skipsupport(PG_FUNCTION_ARGS)
Definition: date.c:500
Datum timetz_zone(PG_FUNCTION_ARGS)
Definition: date.c:3156
Datum date_cmp_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:936
int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2)
Definition: date.c:857
double date2timestamp_no_overflow(DateADT dateVal)
Definition: date.c:753
Datum make_date(PG_FUNCTION_ARGS)
Definition: date.c:247
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:351
Datum date_le_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:830
Datum time_send(PG_FUNCTION_ARGS)
Definition: date.c:1643
Datum date_mi(PG_FUNCTION_ARGS)
Definition: date.c:553
Datum timestamp_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:999
Datum date_ne(PG_FUNCTION_ARGS)
Definition: date.c:401
Datum time_scale(PG_FUNCTION_ARGS)
Definition: date.c:1721
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition: date.c:2031
#define TIMEADT_LT(t1, t2)
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:2410
Datum overlaps_time(PG_FUNCTION_ARGS)
Definition: date.c:1879
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1321
Datum timestamptz_le_date(PG_FUNCTION_ARGS)
Definition: date.c:1044
#define DATE_IS_NOEND(j)
Definition: date.h:42
#define DATEVAL_NOEND
Definition: date.h:37
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
#define PG_RETURN_TIMETZADT_P(x)
Definition: date.h:95
#define PG_RETURN_DATEADT(x)
Definition: date.h:93
#define DATE_IS_NOBEGIN(j)
Definition: date.h:40
#define DATE_NOT_FINITE(j)
Definition: date.h:43
#define DATE_NOEND(j)
Definition: date.h:41
#define PG_GETARG_TIMEADT(n)
Definition: date.h:90
#define PG_RETURN_TIMEADT(x)
Definition: date.h:94
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
#define DATE_NOBEGIN(j)
Definition: date.h:39
#define MAX_TIME_PRECISION
Definition: date.h:45
int64 TimeADT
Definition: date.h:25
#define PG_GETARG_TIMETZADT_P(n)
Definition: date.h:91
#define DATEVAL_NOBEGIN
Definition: date.h:36
#define PG_GETARG_DATEADT(n)
Definition: date.h:89
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:690
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:686
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int DateStyle
Definition: globals.c:125
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
Assert(PointerIsAligned(start, uint64))
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTK_QUARTER
Definition: datetime.h:166
#define DTK_JULIAN
Definition: datetime.h:173
#define DTK_TZ_HOUR
Definition: datetime.h:177
#define DTK_TZ_MINUTE
Definition: datetime.h:178
#define DTK_LATE
Definition: datetime.h:151
#define DTK_DATE
Definition: datetime.h:144
#define DTK_CENTURY
Definition: datetime.h:169
#define DTK_ISODOW
Definition: datetime.h:180
#define DTK_DAY
Definition: datetime.h:163
#define RESERV
Definition: datetime.h:90
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_DATE_M
Definition: datetime.h:191
#define DTK_MILLENNIUM
Definition: datetime.h:170
#define DTK_EARLY
Definition: datetime.h:150
#define DTK_ISOYEAR
Definition: datetime.h:179
#define MAXDATELEN
Definition: datetime.h:200
#define DTK_DOY
Definition: datetime.h:176
#define DTK_TZ
Definition: datetime.h:146
#define TZNAME_FIXED_OFFSET
Definition: datetime.h:299
#define TZNAME_DYNTZ
Definition: datetime.h:300
#define EARLY
Definition: datetime.h:39
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#define LATE
Definition: datetime.h:40
#define DTK_MICROSEC
Definition: datetime.h:172
#define DTK_DOW
Definition: datetime.h:175
#define DTK_YEAR
Definition: datetime.h:167
#define DTK_MILLISEC
Definition: datetime.h:171
#define DTK_MONTH
Definition: datetime.h:165
#define DTK_MINUTE
Definition: datetime.h:161
#define UNITS
Definition: datetime.h:107
long val
Definition: informix.c:689
static bool pg_neg_s32_overflow(int32 a, int32 *result)
Definition: int.h:205
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:235
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
static struct pg_tm tm
Definition: localtime.c:104
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc(Size size)
Definition: mcxt.c:1365
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:64
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:83
static char * buf
Definition: pg_test_fsync.c:72
const char * pg_get_timezone_name(pg_tz *tz)
Definition: localtime.c:1990
#define TZ_STRLEN_MAX
Definition: pgtime.h:54
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
long date
Definition: pgtypes_date.h:9
int64 timestamp
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:413
#define Int64GetDatumFast(X)
Definition: postgres.h:515
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:393
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
uint64_t Datum
Definition: postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
struct SkipSupportData * SkipSupport
Definition: skipsupport.h:50
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
struct StringInfoData * StringInfo
Definition: string.h:15
bool error_occurred
Definition: miscnodes.h:47
int32 day
Definition: timestamp.h:51
int32 month
Definition: timestamp.h:52
TimeOffset time
Definition: timestamp.h:49
Definition: nodes.h:135
SkipSupportIncDec decrement
Definition: skipsupport.h:91
SkipSupportIncDec increment
Definition: skipsupport.h:92
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
Definition: date.h:28
TimeADT time
Definition: date.h:29
int32 zone
Definition: date.h:30
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_sec
Definition: pgtime.h:36
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
Definition: c.h:697
Definition: zic.c:99
int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
Definition: tuplesort.c:3158
#define timestamptz_cmp_internal(dt1, dt2)
Definition: timestamp.h:143
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63
static Datum IntervalPGetDatum(const Interval *X)
Definition: timestamp.h:58
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:67
#define PG_GETARG_INTERVAL_P(n)
Definition: timestamp.h:65
#define PG_GETARG_TIMESTAMPTZ(n)
Definition: timestamp.h:64
#define PG_RETURN_INTERVAL_P(x)
Definition: timestamp.h:69
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition: varatt.h:472
static char * VARDATA_ANY(const void *PTR)
Definition: varatt.h:486
text * cstring_to_text(const char *s)
Definition: varlena.c:181
void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len)
Definition: varlena.c:245
const char * type
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:871