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