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