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