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