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