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-2019, 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  * If 'have_error' is NULL, then errors are thrown, else '*have_error' is set
558  * and zero is returned.
559  */
560 Timestamp
561 date2timestamp_opt_error(DateADT dateVal, bool *have_error)
562 {
563  Timestamp result;
564 
565  if (DATE_IS_NOBEGIN(dateVal))
566  TIMESTAMP_NOBEGIN(result);
567  else if (DATE_IS_NOEND(dateVal))
568  TIMESTAMP_NOEND(result);
569  else
570  {
571  /*
572  * Date's range is wider than timestamp's, so check for boundaries.
573  * Since dates have the same minimum values as timestamps, only upper
574  * boundary need be checked for overflow.
575  */
576  if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
577  {
578  if (have_error)
579  {
580  *have_error = true;
581  return (Timestamp) 0;
582  }
583  else
584  {
585  ereport(ERROR,
586  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
587  errmsg("date out of range for timestamp")));
588  }
589  }
590 
591  /* date is days since 2000, timestamp is microseconds since same... */
592  result = dateVal * USECS_PER_DAY;
593  }
594 
595  return result;
596 }
597 
598 /*
599  * Single-argument version of date2timestamp_opt_error().
600  */
601 static TimestampTz
603 {
604  return date2timestamp_opt_error(dateVal, NULL);
605 }
606 
607 /*
608  * Promote date to timestamp with time zone.
609  *
610  * If 'have_error' is NULL, then errors are thrown, else '*have_error' is set
611  * and zero is returned.
612  */
614 date2timestamptz_opt_error(DateADT dateVal, bool *have_error)
615 {
616  TimestampTz result;
617  struct pg_tm tt,
618  *tm = &tt;
619  int tz;
620 
621  if (DATE_IS_NOBEGIN(dateVal))
622  TIMESTAMP_NOBEGIN(result);
623  else if (DATE_IS_NOEND(dateVal))
624  TIMESTAMP_NOEND(result);
625  else
626  {
627  /*
628  * Date's range is wider than timestamp's, so check for boundaries.
629  * Since dates have the same minimum values as timestamps, only upper
630  * boundary need be checked for overflow.
631  */
632  if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE))
633  {
634  if (have_error)
635  {
636  *have_error = true;
637  return (TimestampTz) 0;
638  }
639  else
640  {
641  ereport(ERROR,
642  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
643  errmsg("date out of range for timestamp")));
644  }
645  }
646 
647  j2date(dateVal + POSTGRES_EPOCH_JDATE,
648  &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
649  tm->tm_hour = 0;
650  tm->tm_min = 0;
651  tm->tm_sec = 0;
653 
654  result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
655 
656  /*
657  * Since it is possible to go beyond allowed timestamptz range because
658  * of time zone, check for allowed timestamp range after adding tz.
659  */
660  if (!IS_VALID_TIMESTAMP(result))
661  {
662  if (have_error)
663  {
664  *have_error = true;
665  return (TimestampTz) 0;
666  }
667  else
668  {
669  ereport(ERROR,
670  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
671  errmsg("date out of range for timestamp")));
672  }
673  }
674  }
675 
676  return result;
677 }
678 
679 /*
680  * Single-argument version of date2timestamptz_opt_error().
681  */
682 static TimestampTz
684 {
685  return date2timestamptz_opt_error(dateVal, NULL);
686 }
687 
688 /*
689  * date2timestamp_no_overflow
690  *
691  * This is chartered to produce a double value that is numerically
692  * equivalent to the corresponding Timestamp value, if the date is in the
693  * valid range of Timestamps, but in any case not throw an overflow error.
694  * We can do this since the numerical range of double is greater than
695  * that of non-erroneous timestamps. The results are currently only
696  * used for statistical estimation purposes.
697  */
698 double
700 {
701  double result;
702 
703  if (DATE_IS_NOBEGIN(dateVal))
704  result = -DBL_MAX;
705  else if (DATE_IS_NOEND(dateVal))
706  result = DBL_MAX;
707  else
708  {
709  /* date is days since 2000, timestamp is microseconds since same... */
710  result = dateVal * (double) USECS_PER_DAY;
711  }
712 
713  return result;
714 }
715 
716 
717 /*
718  * Crosstype comparison functions for dates
719  */
720 
721 Datum
723 {
724  DateADT dateVal = PG_GETARG_DATEADT(0);
726  Timestamp dt1;
727 
728  dt1 = date2timestamp(dateVal);
729 
730  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
731 }
732 
733 Datum
735 {
736  DateADT dateVal = PG_GETARG_DATEADT(0);
738  Timestamp dt1;
739 
740  dt1 = date2timestamp(dateVal);
741 
742  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
743 }
744 
745 Datum
747 {
748  DateADT dateVal = PG_GETARG_DATEADT(0);
750  Timestamp dt1;
751 
752  dt1 = date2timestamp(dateVal);
753 
754  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
755 }
756 
757 Datum
759 {
760  DateADT dateVal = PG_GETARG_DATEADT(0);
762  Timestamp dt1;
763 
764  dt1 = date2timestamp(dateVal);
765 
766  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
767 }
768 
769 Datum
771 {
772  DateADT dateVal = PG_GETARG_DATEADT(0);
774  Timestamp dt1;
775 
776  dt1 = date2timestamp(dateVal);
777 
778  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
779 }
780 
781 Datum
783 {
784  DateADT dateVal = PG_GETARG_DATEADT(0);
786  Timestamp dt1;
787 
788  dt1 = date2timestamp(dateVal);
789 
790  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
791 }
792 
793 Datum
795 {
796  DateADT dateVal = PG_GETARG_DATEADT(0);
798  Timestamp dt1;
799 
800  dt1 = date2timestamp(dateVal);
801 
803 }
804 
805 Datum
807 {
808  DateADT dateVal = PG_GETARG_DATEADT(0);
810  TimestampTz dt1;
811 
812  dt1 = date2timestamptz(dateVal);
813 
815 }
816 
817 Datum
819 {
820  DateADT dateVal = PG_GETARG_DATEADT(0);
822  TimestampTz dt1;
823 
824  dt1 = date2timestamptz(dateVal);
825 
827 }
828 
829 Datum
831 {
832  DateADT dateVal = PG_GETARG_DATEADT(0);
834  TimestampTz dt1;
835 
836  dt1 = date2timestamptz(dateVal);
837 
839 }
840 
841 Datum
843 {
844  DateADT dateVal = PG_GETARG_DATEADT(0);
846  TimestampTz dt1;
847 
848  dt1 = date2timestamptz(dateVal);
849 
851 }
852 
853 Datum
855 {
856  DateADT dateVal = PG_GETARG_DATEADT(0);
858  TimestampTz dt1;
859 
860  dt1 = date2timestamptz(dateVal);
861 
863 }
864 
865 Datum
867 {
868  DateADT dateVal = PG_GETARG_DATEADT(0);
870  TimestampTz dt1;
871 
872  dt1 = date2timestamptz(dateVal);
873 
875 }
876 
877 Datum
879 {
880  DateADT dateVal = PG_GETARG_DATEADT(0);
882  TimestampTz dt1;
883 
884  dt1 = date2timestamptz(dateVal);
885 
887 }
888 
889 Datum
891 {
893  DateADT dateVal = PG_GETARG_DATEADT(1);
894  Timestamp dt2;
895 
896  dt2 = date2timestamp(dateVal);
897 
898  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
899 }
900 
901 Datum
903 {
905  DateADT dateVal = PG_GETARG_DATEADT(1);
906  Timestamp dt2;
907 
908  dt2 = date2timestamp(dateVal);
909 
910  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
911 }
912 
913 Datum
915 {
917  DateADT dateVal = PG_GETARG_DATEADT(1);
918  Timestamp dt2;
919 
920  dt2 = date2timestamp(dateVal);
921 
922  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
923 }
924 
925 Datum
927 {
929  DateADT dateVal = PG_GETARG_DATEADT(1);
930  Timestamp dt2;
931 
932  dt2 = date2timestamp(dateVal);
933 
934  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
935 }
936 
937 Datum
939 {
941  DateADT dateVal = PG_GETARG_DATEADT(1);
942  Timestamp dt2;
943 
944  dt2 = date2timestamp(dateVal);
945 
946  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
947 }
948 
949 Datum
951 {
953  DateADT dateVal = PG_GETARG_DATEADT(1);
954  Timestamp dt2;
955 
956  dt2 = date2timestamp(dateVal);
957 
958  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
959 }
960 
961 Datum
963 {
965  DateADT dateVal = PG_GETARG_DATEADT(1);
966  Timestamp dt2;
967 
968  dt2 = date2timestamp(dateVal);
969 
971 }
972 
973 Datum
975 {
977  DateADT dateVal = PG_GETARG_DATEADT(1);
978  TimestampTz dt2;
979 
980  dt2 = date2timestamptz(dateVal);
981 
983 }
984 
985 Datum
987 {
989  DateADT dateVal = PG_GETARG_DATEADT(1);
990  TimestampTz dt2;
991 
992  dt2 = date2timestamptz(dateVal);
993 
995 }
996 
997 Datum
999 {
1001  DateADT dateVal = PG_GETARG_DATEADT(1);
1002  TimestampTz dt2;
1003 
1004  dt2 = date2timestamptz(dateVal);
1005 
1007 }
1008 
1009 Datum
1011 {
1013  DateADT dateVal = PG_GETARG_DATEADT(1);
1014  TimestampTz dt2;
1015 
1016  dt2 = date2timestamptz(dateVal);
1017 
1019 }
1020 
1021 Datum
1023 {
1025  DateADT dateVal = PG_GETARG_DATEADT(1);
1026  TimestampTz dt2;
1027 
1028  dt2 = date2timestamptz(dateVal);
1029 
1030  PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);
1031 }
1032 
1033 Datum
1035 {
1037  DateADT dateVal = PG_GETARG_DATEADT(1);
1038  TimestampTz dt2;
1039 
1040  dt2 = date2timestamptz(dateVal);
1041 
1042  PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);
1043 }
1044 
1045 Datum
1047 {
1049  DateADT dateVal = PG_GETARG_DATEADT(1);
1050  TimestampTz dt2;
1051 
1052  dt2 = date2timestamptz(dateVal);
1053 
1055 }
1056 
1057 /*
1058  * in_range support function for date.
1059  *
1060  * We implement this by promoting the dates to timestamp (without time zone)
1061  * and then using the timestamp-and-interval in_range function.
1062  */
1063 Datum
1065 {
1067  DateADT base = PG_GETARG_DATEADT(1);
1068  Interval *offset = PG_GETARG_INTERVAL_P(2);
1069  bool sub = PG_GETARG_BOOL(3);
1070  bool less = PG_GETARG_BOOL(4);
1071  Timestamp valStamp;
1072  Timestamp baseStamp;
1073 
1074  valStamp = date2timestamp(val);
1075  baseStamp = date2timestamp(base);
1076 
1078  TimestampGetDatum(valStamp),
1079  TimestampGetDatum(baseStamp),
1080  IntervalPGetDatum(offset),
1081  BoolGetDatum(sub),
1082  BoolGetDatum(less));
1083 }
1084 
1085 
1086 /* Add an interval to a date, giving a new date.
1087  * Must handle both positive and negative intervals.
1088  *
1089  * We implement this by promoting the date to timestamp (without time zone)
1090  * and then using the timestamp plus interval function.
1091  */
1092 Datum
1094 {
1095  DateADT dateVal = PG_GETARG_DATEADT(0);
1096  Interval *span = PG_GETARG_INTERVAL_P(1);
1097  Timestamp dateStamp;
1098 
1099  dateStamp = date2timestamp(dateVal);
1100 
1102  TimestampGetDatum(dateStamp),
1103  PointerGetDatum(span));
1104 }
1105 
1106 /* Subtract an interval from a date, giving a new date.
1107  * Must handle both positive and negative intervals.
1108  *
1109  * We implement this by promoting the date to timestamp (without time zone)
1110  * and then using the timestamp minus interval function.
1111  */
1112 Datum
1114 {
1115  DateADT dateVal = PG_GETARG_DATEADT(0);
1116  Interval *span = PG_GETARG_INTERVAL_P(1);
1117  Timestamp dateStamp;
1118 
1119  dateStamp = date2timestamp(dateVal);
1120 
1122  TimestampGetDatum(dateStamp),
1123  PointerGetDatum(span));
1124 }
1125 
1126 /* date_timestamp()
1127  * Convert date to timestamp data type.
1128  */
1129 Datum
1131 {
1132  DateADT dateVal = PG_GETARG_DATEADT(0);
1133  Timestamp result;
1134 
1135  result = date2timestamp(dateVal);
1136 
1137  PG_RETURN_TIMESTAMP(result);
1138 }
1139 
1140 /* timestamp_date()
1141  * Convert timestamp to date data type.
1142  */
1143 Datum
1145 {
1147  DateADT result;
1148  struct pg_tm tt,
1149  *tm = &tt;
1150  fsec_t fsec;
1151 
1152  if (TIMESTAMP_IS_NOBEGIN(timestamp))
1153  DATE_NOBEGIN(result);
1154  else if (TIMESTAMP_IS_NOEND(timestamp))
1155  DATE_NOEND(result);
1156  else
1157  {
1158  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1159  ereport(ERROR,
1160  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1161  errmsg("timestamp out of range")));
1162 
1163  result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
1164  }
1165 
1166  PG_RETURN_DATEADT(result);
1167 }
1168 
1169 
1170 /* date_timestamptz()
1171  * Convert date to timestamp with time zone data type.
1172  */
1173 Datum
1175 {
1176  DateADT dateVal = PG_GETARG_DATEADT(0);
1177  TimestampTz result;
1178 
1179  result = date2timestamptz(dateVal);
1180 
1181  PG_RETURN_TIMESTAMP(result);
1182 }
1183 
1184 
1185 /* timestamptz_date()
1186  * Convert timestamp with time zone to date data type.
1187  */
1188 Datum
1190 {
1192  DateADT result;
1193  struct pg_tm tt,
1194  *tm = &tt;
1195  fsec_t fsec;
1196  int tz;
1197 
1198  if (TIMESTAMP_IS_NOBEGIN(timestamp))
1199  DATE_NOBEGIN(result);
1200  else if (TIMESTAMP_IS_NOEND(timestamp))
1201  DATE_NOEND(result);
1202  else
1203  {
1204  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1205  ereport(ERROR,
1206  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1207  errmsg("timestamp out of range")));
1208 
1209  result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
1210  }
1211 
1212  PG_RETURN_DATEADT(result);
1213 }
1214 
1215 
1216 /*****************************************************************************
1217  * Time ADT
1218  *****************************************************************************/
1219 
1220 Datum
1222 {
1223  char *str = PG_GETARG_CSTRING(0);
1224 
1225 #ifdef NOT_USED
1226  Oid typelem = PG_GETARG_OID(1);
1227 #endif
1228  int32 typmod = PG_GETARG_INT32(2);
1229  TimeADT result;
1230  fsec_t fsec;
1231  struct pg_tm tt,
1232  *tm = &tt;
1233  int tz;
1234  int nf;
1235  int dterr;
1236  char workbuf[MAXDATELEN + 1];
1237  char *field[MAXDATEFIELDS];
1238  int dtype;
1239  int ftype[MAXDATEFIELDS];
1240 
1241  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
1242  field, ftype, MAXDATEFIELDS, &nf);
1243  if (dterr == 0)
1244  dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);
1245  if (dterr != 0)
1246  DateTimeParseError(dterr, str, "time");
1247 
1248  tm2time(tm, fsec, &result);
1249  AdjustTimeForTypmod(&result, typmod);
1250 
1251  PG_RETURN_TIMEADT(result);
1252 }
1253 
1254 /* tm2time()
1255  * Convert a tm structure to a time data type.
1256  */
1257 int
1258 tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
1259 {
1260  *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)
1261  * USECS_PER_SEC) + fsec;
1262  return 0;
1263 }
1264 
1265 /* time2tm()
1266  * Convert time data type to POSIX time structure.
1267  *
1268  * For dates within the range of pg_time_t, convert to the local time zone.
1269  * If out of this range, leave as UTC (in practice that could only happen
1270  * if pg_time_t is just 32 bits) - thomas 97/05/27
1271  */
1272 int
1273 time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
1274 {
1275  tm->tm_hour = time / USECS_PER_HOUR;
1276  time -= tm->tm_hour * USECS_PER_HOUR;
1277  tm->tm_min = time / USECS_PER_MINUTE;
1278  time -= tm->tm_min * USECS_PER_MINUTE;
1279  tm->tm_sec = time / USECS_PER_SEC;
1280  time -= tm->tm_sec * USECS_PER_SEC;
1281  *fsec = time;
1282  return 0;
1283 }
1284 
1285 Datum
1287 {
1288  TimeADT time = PG_GETARG_TIMEADT(0);
1289  char *result;
1290  struct pg_tm tt,
1291  *tm = &tt;
1292  fsec_t fsec;
1293  char buf[MAXDATELEN + 1];
1294 
1295  time2tm(time, tm, &fsec);
1296  EncodeTimeOnly(tm, fsec, false, 0, DateStyle, buf);
1297 
1298  result = pstrdup(buf);
1299  PG_RETURN_CSTRING(result);
1300 }
1301 
1302 /*
1303  * time_recv - converts external binary format to time
1304  */
1305 Datum
1307 {
1309 
1310 #ifdef NOT_USED
1311  Oid typelem = PG_GETARG_OID(1);
1312 #endif
1313  int32 typmod = PG_GETARG_INT32(2);
1314  TimeADT result;
1315 
1316  result = pq_getmsgint64(buf);
1317 
1318  if (result < INT64CONST(0) || result > USECS_PER_DAY)
1319  ereport(ERROR,
1320  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1321  errmsg("time out of range")));
1322 
1323  AdjustTimeForTypmod(&result, typmod);
1324 
1325  PG_RETURN_TIMEADT(result);
1326 }
1327 
1328 /*
1329  * time_send - converts time to binary format
1330  */
1331 Datum
1333 {
1334  TimeADT time = PG_GETARG_TIMEADT(0);
1336 
1337  pq_begintypsend(&buf);
1338  pq_sendint64(&buf, time);
1340 }
1341 
1342 Datum
1344 {
1346 
1347  PG_RETURN_INT32(anytime_typmodin(false, ta));
1348 }
1349 
1350 Datum
1352 {
1353  int32 typmod = PG_GETARG_INT32(0);
1354 
1355  PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
1356 }
1357 
1358 /*
1359  * make_time - time constructor
1360  */
1361 Datum
1363 {
1364  int tm_hour = PG_GETARG_INT32(0);
1365  int tm_min = PG_GETARG_INT32(1);
1366  double sec = PG_GETARG_FLOAT8(2);
1367  TimeADT time;
1368 
1369  /* This should match the checks in DecodeTimeOnly */
1370  if (tm_hour < 0 || tm_min < 0 || tm_min > MINS_PER_HOUR - 1 ||
1371  sec < 0 || sec > SECS_PER_MINUTE ||
1372  tm_hour > HOURS_PER_DAY ||
1373  /* test for > 24:00:00 */
1374  (tm_hour == HOURS_PER_DAY && (tm_min > 0 || sec > 0)))
1375  ereport(ERROR,
1376  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
1377  errmsg("time field value out of range: %d:%02d:%02g",
1378  tm_hour, tm_min, sec)));
1379 
1380  /* This should match tm2time */
1381  time = (((tm_hour * MINS_PER_HOUR + tm_min) * SECS_PER_MINUTE)
1382  * USECS_PER_SEC) + rint(sec * USECS_PER_SEC);
1383 
1384  PG_RETURN_TIMEADT(time);
1385 }
1386 
1387 
1388 /* time_support()
1389  *
1390  * Planner support function for the time_scale() and timetz_scale()
1391  * length coercion functions (we need not distinguish them here).
1392  */
1393 Datum
1395 {
1396  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1397  Node *ret = NULL;
1398 
1399  if (IsA(rawreq, SupportRequestSimplify))
1400  {
1402 
1403  ret = TemporalSimplify(MAX_TIME_PRECISION, (Node *) req->fcall);
1404  }
1405 
1406  PG_RETURN_POINTER(ret);
1407 }
1408 
1409 /* time_scale()
1410  * Adjust time type for specified scale factor.
1411  * Used by PostgreSQL type system to stuff columns.
1412  */
1413 Datum
1415 {
1416  TimeADT time = PG_GETARG_TIMEADT(0);
1417  int32 typmod = PG_GETARG_INT32(1);
1418  TimeADT result;
1419 
1420  result = time;
1421  AdjustTimeForTypmod(&result, typmod);
1422 
1423  PG_RETURN_TIMEADT(result);
1424 }
1425 
1426 /* AdjustTimeForTypmod()
1427  * Force the precision of the time value to a specified value.
1428  * Uses *exactly* the same code as in AdjustTimestampForTypmod()
1429  * but we make a separate copy because those types do not
1430  * have a fundamental tie together but rather a coincidence of
1431  * implementation. - thomas
1432  */
1433 void
1435 {
1436  static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
1437  INT64CONST(1000000),
1438  INT64CONST(100000),
1439  INT64CONST(10000),
1440  INT64CONST(1000),
1441  INT64CONST(100),
1442  INT64CONST(10),
1443  INT64CONST(1)
1444  };
1445 
1446  static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
1447  INT64CONST(500000),
1448  INT64CONST(50000),
1449  INT64CONST(5000),
1450  INT64CONST(500),
1451  INT64CONST(50),
1452  INT64CONST(5),
1453  INT64CONST(0)
1454  };
1455 
1456  if (typmod >= 0 && typmod <= MAX_TIME_PRECISION)
1457  {
1458  if (*time >= INT64CONST(0))
1459  *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *
1460  TimeScales[typmod];
1461  else
1462  *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *
1463  TimeScales[typmod]);
1464  }
1465 }
1466 
1467 
1468 Datum
1470 {
1471  TimeADT time1 = PG_GETARG_TIMEADT(0);
1472  TimeADT time2 = PG_GETARG_TIMEADT(1);
1473 
1474  PG_RETURN_BOOL(time1 == time2);
1475 }
1476 
1477 Datum
1479 {
1480  TimeADT time1 = PG_GETARG_TIMEADT(0);
1481  TimeADT time2 = PG_GETARG_TIMEADT(1);
1482 
1483  PG_RETURN_BOOL(time1 != time2);
1484 }
1485 
1486 Datum
1488 {
1489  TimeADT time1 = PG_GETARG_TIMEADT(0);
1490  TimeADT time2 = PG_GETARG_TIMEADT(1);
1491 
1492  PG_RETURN_BOOL(time1 < time2);
1493 }
1494 
1495 Datum
1497 {
1498  TimeADT time1 = PG_GETARG_TIMEADT(0);
1499  TimeADT time2 = PG_GETARG_TIMEADT(1);
1500 
1501  PG_RETURN_BOOL(time1 <= time2);
1502 }
1503 
1504 Datum
1506 {
1507  TimeADT time1 = PG_GETARG_TIMEADT(0);
1508  TimeADT time2 = PG_GETARG_TIMEADT(1);
1509 
1510  PG_RETURN_BOOL(time1 > time2);
1511 }
1512 
1513 Datum
1515 {
1516  TimeADT time1 = PG_GETARG_TIMEADT(0);
1517  TimeADT time2 = PG_GETARG_TIMEADT(1);
1518 
1519  PG_RETURN_BOOL(time1 >= time2);
1520 }
1521 
1522 Datum
1524 {
1525  TimeADT time1 = PG_GETARG_TIMEADT(0);
1526  TimeADT time2 = PG_GETARG_TIMEADT(1);
1527 
1528  if (time1 < time2)
1529  PG_RETURN_INT32(-1);
1530  if (time1 > time2)
1531  PG_RETURN_INT32(1);
1532  PG_RETURN_INT32(0);
1533 }
1534 
1535 Datum
1537 {
1538  return hashint8(fcinfo);
1539 }
1540 
1541 Datum
1543 {
1544  return hashint8extended(fcinfo);
1545 }
1546 
1547 Datum
1549 {
1550  TimeADT time1 = PG_GETARG_TIMEADT(0);
1551  TimeADT time2 = PG_GETARG_TIMEADT(1);
1552 
1553  PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
1554 }
1555 
1556 Datum
1558 {
1559  TimeADT time1 = PG_GETARG_TIMEADT(0);
1560  TimeADT time2 = PG_GETARG_TIMEADT(1);
1561 
1562  PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
1563 }
1564 
1565 /* overlaps_time() --- implements the SQL OVERLAPS operator.
1566  *
1567  * Algorithm is per SQL spec. This is much harder than you'd think
1568  * because the spec requires us to deliver a non-null answer in some cases
1569  * where some of the inputs are null.
1570  */
1571 Datum
1573 {
1574  /*
1575  * The arguments are TimeADT, but we leave them as generic Datums to avoid
1576  * dereferencing nulls (TimeADT is pass-by-reference!)
1577  */
1578  Datum ts1 = PG_GETARG_DATUM(0);
1579  Datum te1 = PG_GETARG_DATUM(1);
1580  Datum ts2 = PG_GETARG_DATUM(2);
1581  Datum te2 = PG_GETARG_DATUM(3);
1582  bool ts1IsNull = PG_ARGISNULL(0);
1583  bool te1IsNull = PG_ARGISNULL(1);
1584  bool ts2IsNull = PG_ARGISNULL(2);
1585  bool te2IsNull = PG_ARGISNULL(3);
1586 
1587 #define TIMEADT_GT(t1,t2) \
1588  (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
1589 #define TIMEADT_LT(t1,t2) \
1590  (DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
1591 
1592  /*
1593  * If both endpoints of interval 1 are null, the result is null (unknown).
1594  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
1595  * take ts1 as the lesser endpoint.
1596  */
1597  if (ts1IsNull)
1598  {
1599  if (te1IsNull)
1600  PG_RETURN_NULL();
1601  /* swap null for non-null */
1602  ts1 = te1;
1603  te1IsNull = true;
1604  }
1605  else if (!te1IsNull)
1606  {
1607  if (TIMEADT_GT(ts1, te1))
1608  {
1609  Datum tt = ts1;
1610 
1611  ts1 = te1;
1612  te1 = tt;
1613  }
1614  }
1615 
1616  /* Likewise for interval 2. */
1617  if (ts2IsNull)
1618  {
1619  if (te2IsNull)
1620  PG_RETURN_NULL();
1621  /* swap null for non-null */
1622  ts2 = te2;
1623  te2IsNull = true;
1624  }
1625  else if (!te2IsNull)
1626  {
1627  if (TIMEADT_GT(ts2, te2))
1628  {
1629  Datum tt = ts2;
1630 
1631  ts2 = te2;
1632  te2 = tt;
1633  }
1634  }
1635 
1636  /*
1637  * At this point neither ts1 nor ts2 is null, so we can consider three
1638  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
1639  */
1640  if (TIMEADT_GT(ts1, ts2))
1641  {
1642  /*
1643  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
1644  * in the presence of nulls it's not quite completely so.
1645  */
1646  if (te2IsNull)
1647  PG_RETURN_NULL();
1648  if (TIMEADT_LT(ts1, te2))
1649  PG_RETURN_BOOL(true);
1650  if (te1IsNull)
1651  PG_RETURN_NULL();
1652 
1653  /*
1654  * If te1 is not null then we had ts1 <= te1 above, and we just found
1655  * ts1 >= te2, hence te1 >= te2.
1656  */
1657  PG_RETURN_BOOL(false);
1658  }
1659  else if (TIMEADT_LT(ts1, ts2))
1660  {
1661  /* This case is ts2 < te1 OR te2 < te1 */
1662  if (te1IsNull)
1663  PG_RETURN_NULL();
1664  if (TIMEADT_LT(ts2, te1))
1665  PG_RETURN_BOOL(true);
1666  if (te2IsNull)
1667  PG_RETURN_NULL();
1668 
1669  /*
1670  * If te2 is not null then we had ts2 <= te2 above, and we just found
1671  * ts2 >= te1, hence te2 >= te1.
1672  */
1673  PG_RETURN_BOOL(false);
1674  }
1675  else
1676  {
1677  /*
1678  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
1679  * rather silly way of saying "true if both are nonnull, else null".
1680  */
1681  if (te1IsNull || te2IsNull)
1682  PG_RETURN_NULL();
1683  PG_RETURN_BOOL(true);
1684  }
1685 
1686 #undef TIMEADT_GT
1687 #undef TIMEADT_LT
1688 }
1689 
1690 /* timestamp_time()
1691  * Convert timestamp to time data type.
1692  */
1693 Datum
1695 {
1697  TimeADT result;
1698  struct pg_tm tt,
1699  *tm = &tt;
1700  fsec_t fsec;
1701 
1702  if (TIMESTAMP_NOT_FINITE(timestamp))
1703  PG_RETURN_NULL();
1704 
1705  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1706  ereport(ERROR,
1707  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1708  errmsg("timestamp out of range")));
1709 
1710  /*
1711  * Could also do this with time = (timestamp / USECS_PER_DAY *
1712  * USECS_PER_DAY) - timestamp;
1713  */
1714  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1715  USECS_PER_SEC) + fsec;
1716 
1717  PG_RETURN_TIMEADT(result);
1718 }
1719 
1720 /* timestamptz_time()
1721  * Convert timestamptz to time data type.
1722  */
1723 Datum
1725 {
1727  TimeADT result;
1728  struct pg_tm tt,
1729  *tm = &tt;
1730  int tz;
1731  fsec_t fsec;
1732 
1733  if (TIMESTAMP_NOT_FINITE(timestamp))
1734  PG_RETURN_NULL();
1735 
1736  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1737  ereport(ERROR,
1738  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1739  errmsg("timestamp out of range")));
1740 
1741  /*
1742  * Could also do this with time = (timestamp / USECS_PER_DAY *
1743  * USECS_PER_DAY) - timestamp;
1744  */
1745  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1746  USECS_PER_SEC) + fsec;
1747 
1748  PG_RETURN_TIMEADT(result);
1749 }
1750 
1751 /* datetime_timestamp()
1752  * Convert date and time to timestamp data type.
1753  */
1754 Datum
1756 {
1758  TimeADT time = PG_GETARG_TIMEADT(1);
1759  Timestamp result;
1760 
1761  result = date2timestamp(date);
1762  if (!TIMESTAMP_NOT_FINITE(result))
1763  {
1764  result += time;
1765  if (!IS_VALID_TIMESTAMP(result))
1766  ereport(ERROR,
1767  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1768  errmsg("timestamp out of range")));
1769  }
1770 
1771  PG_RETURN_TIMESTAMP(result);
1772 }
1773 
1774 /* time_interval()
1775  * Convert time to interval data type.
1776  */
1777 Datum
1779 {
1780  TimeADT time = PG_GETARG_TIMEADT(0);
1781  Interval *result;
1782 
1783  result = (Interval *) palloc(sizeof(Interval));
1784 
1785  result->time = time;
1786  result->day = 0;
1787  result->month = 0;
1788 
1789  PG_RETURN_INTERVAL_P(result);
1790 }
1791 
1792 /* interval_time()
1793  * Convert interval to time data type.
1794  *
1795  * This is defined as producing the fractional-day portion of the interval.
1796  * Therefore, we can just ignore the months field. It is not real clear
1797  * what to do with negative intervals, but we choose to subtract the floor,
1798  * so that, say, '-2 hours' becomes '22:00:00'.
1799  */
1800 Datum
1802 {
1803  Interval *span = PG_GETARG_INTERVAL_P(0);
1804  TimeADT result;
1805  int64 days;
1806 
1807  result = span->time;
1808  if (result >= USECS_PER_DAY)
1809  {
1810  days = result / USECS_PER_DAY;
1811  result -= days * USECS_PER_DAY;
1812  }
1813  else if (result < 0)
1814  {
1815  days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
1816  result += days * USECS_PER_DAY;
1817  }
1818 
1819  PG_RETURN_TIMEADT(result);
1820 }
1821 
1822 /* time_mi_time()
1823  * Subtract two times to produce an interval.
1824  */
1825 Datum
1827 {
1828  TimeADT time1 = PG_GETARG_TIMEADT(0);
1829  TimeADT time2 = PG_GETARG_TIMEADT(1);
1830  Interval *result;
1831 
1832  result = (Interval *) palloc(sizeof(Interval));
1833 
1834  result->month = 0;
1835  result->day = 0;
1836  result->time = time1 - time2;
1837 
1838  PG_RETURN_INTERVAL_P(result);
1839 }
1840 
1841 /* time_pl_interval()
1842  * Add interval to time.
1843  */
1844 Datum
1846 {
1847  TimeADT time = PG_GETARG_TIMEADT(0);
1848  Interval *span = PG_GETARG_INTERVAL_P(1);
1849  TimeADT result;
1850 
1851  result = time + span->time;
1852  result -= result / USECS_PER_DAY * USECS_PER_DAY;
1853  if (result < INT64CONST(0))
1854  result += USECS_PER_DAY;
1855 
1856  PG_RETURN_TIMEADT(result);
1857 }
1858 
1859 /* time_mi_interval()
1860  * Subtract interval from time.
1861  */
1862 Datum
1864 {
1865  TimeADT time = PG_GETARG_TIMEADT(0);
1866  Interval *span = PG_GETARG_INTERVAL_P(1);
1867  TimeADT result;
1868 
1869  result = time - span->time;
1870  result -= result / USECS_PER_DAY * USECS_PER_DAY;
1871  if (result < INT64CONST(0))
1872  result += USECS_PER_DAY;
1873 
1874  PG_RETURN_TIMEADT(result);
1875 }
1876 
1877 /*
1878  * in_range support function for time.
1879  */
1880 Datum
1882 {
1884  TimeADT base = PG_GETARG_TIMEADT(1);
1885  Interval *offset = PG_GETARG_INTERVAL_P(2);
1886  bool sub = PG_GETARG_BOOL(3);
1887  bool less = PG_GETARG_BOOL(4);
1888  TimeADT sum;
1889 
1890  /*
1891  * Like time_pl_interval/time_mi_interval, we disregard the month and day
1892  * fields of the offset. So our test for negative should too.
1893  */
1894  if (offset->time < 0)
1895  ereport(ERROR,
1896  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
1897  errmsg("invalid preceding or following size in window function")));
1898 
1899  /*
1900  * We can't use time_pl_interval/time_mi_interval here, because their
1901  * wraparound behavior would give wrong (or at least undesirable) answers.
1902  * Fortunately the equivalent non-wrapping behavior is trivial, especially
1903  * since we don't worry about integer overflow.
1904  */
1905  if (sub)
1906  sum = base - offset->time;
1907  else
1908  sum = base + offset->time;
1909 
1910  if (less)
1911  PG_RETURN_BOOL(val <= sum);
1912  else
1913  PG_RETURN_BOOL(val >= sum);
1914 }
1915 
1916 
1917 /* time_part()
1918  * Extract specified field from time type.
1919  */
1920 Datum
1922 {
1923  text *units = PG_GETARG_TEXT_PP(0);
1924  TimeADT time = PG_GETARG_TIMEADT(1);
1925  float8 result;
1926  int type,
1927  val;
1928  char *lowunits;
1929 
1930  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
1931  VARSIZE_ANY_EXHDR(units),
1932  false);
1933 
1934  type = DecodeUnits(0, lowunits, &val);
1935  if (type == UNKNOWN_FIELD)
1936  type = DecodeSpecial(0, lowunits, &val);
1937 
1938  if (type == UNITS)
1939  {
1940  fsec_t fsec;
1941  struct pg_tm tt,
1942  *tm = &tt;
1943 
1944  time2tm(time, tm, &fsec);
1945 
1946  switch (val)
1947  {
1948  case DTK_MICROSEC:
1949  result = tm->tm_sec * 1000000.0 + fsec;
1950  break;
1951 
1952  case DTK_MILLISEC:
1953  result = tm->tm_sec * 1000.0 + fsec / 1000.0;
1954  break;
1955 
1956  case DTK_SECOND:
1957  result = tm->tm_sec + fsec / 1000000.0;
1958  break;
1959 
1960  case DTK_MINUTE:
1961  result = tm->tm_min;
1962  break;
1963 
1964  case DTK_HOUR:
1965  result = tm->tm_hour;
1966  break;
1967 
1968  case DTK_TZ:
1969  case DTK_TZ_MINUTE:
1970  case DTK_TZ_HOUR:
1971  case DTK_DAY:
1972  case DTK_MONTH:
1973  case DTK_QUARTER:
1974  case DTK_YEAR:
1975  case DTK_DECADE:
1976  case DTK_CENTURY:
1977  case DTK_MILLENNIUM:
1978  case DTK_ISOYEAR:
1979  default:
1980  ereport(ERROR,
1981  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1982  errmsg("\"time\" units \"%s\" not recognized",
1983  lowunits)));
1984  result = 0;
1985  }
1986  }
1987  else if (type == RESERV && val == DTK_EPOCH)
1988  {
1989  result = time / 1000000.0;
1990  }
1991  else
1992  {
1993  ereport(ERROR,
1994  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1995  errmsg("\"time\" units \"%s\" not recognized",
1996  lowunits)));
1997  result = 0;
1998  }
1999 
2000  PG_RETURN_FLOAT8(result);
2001 }
2002 
2003 
2004 /*****************************************************************************
2005  * Time With Time Zone ADT
2006  *****************************************************************************/
2007 
2008 /* tm2timetz()
2009  * Convert a tm structure to a time data type.
2010  */
2011 int
2012 tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
2013 {
2014  result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
2015  USECS_PER_SEC) + fsec;
2016  result->zone = tz;
2017 
2018  return 0;
2019 }
2020 
2021 Datum
2023 {
2024  char *str = PG_GETARG_CSTRING(0);
2025 
2026 #ifdef NOT_USED
2027  Oid typelem = PG_GETARG_OID(1);
2028 #endif
2029  int32 typmod = PG_GETARG_INT32(2);
2030  TimeTzADT *result;
2031  fsec_t fsec;
2032  struct pg_tm tt,
2033  *tm = &tt;
2034  int tz;
2035  int nf;
2036  int dterr;
2037  char workbuf[MAXDATELEN + 1];
2038  char *field[MAXDATEFIELDS];
2039  int dtype;
2040  int ftype[MAXDATEFIELDS];
2041 
2042  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
2043  field, ftype, MAXDATEFIELDS, &nf);
2044  if (dterr == 0)
2045  dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);
2046  if (dterr != 0)
2047  DateTimeParseError(dterr, str, "time with time zone");
2048 
2049  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2050  tm2timetz(tm, fsec, tz, result);
2051  AdjustTimeForTypmod(&(result->time), typmod);
2052 
2053  PG_RETURN_TIMETZADT_P(result);
2054 }
2055 
2056 Datum
2058 {
2059  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2060  char *result;
2061  struct pg_tm tt,
2062  *tm = &tt;
2063  fsec_t fsec;
2064  int tz;
2065  char buf[MAXDATELEN + 1];
2066 
2067  timetz2tm(time, tm, &fsec, &tz);
2068  EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
2069 
2070  result = pstrdup(buf);
2071  PG_RETURN_CSTRING(result);
2072 }
2073 
2074 /*
2075  * timetz_recv - converts external binary format to timetz
2076  */
2077 Datum
2079 {
2081 
2082 #ifdef NOT_USED
2083  Oid typelem = PG_GETARG_OID(1);
2084 #endif
2085  int32 typmod = PG_GETARG_INT32(2);
2086  TimeTzADT *result;
2087 
2088  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2089 
2090  result->time = pq_getmsgint64(buf);
2091 
2092  if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
2093  ereport(ERROR,
2094  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2095  errmsg("time out of range")));
2096 
2097  result->zone = pq_getmsgint(buf, sizeof(result->zone));
2098 
2099  /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
2100  if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
2101  ereport(ERROR,
2102  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
2103  errmsg("time zone displacement out of range")));
2104 
2105  AdjustTimeForTypmod(&(result->time), typmod);
2106 
2107  PG_RETURN_TIMETZADT_P(result);
2108 }
2109 
2110 /*
2111  * timetz_send - converts timetz to binary format
2112  */
2113 Datum
2115 {
2116  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2118 
2119  pq_begintypsend(&buf);
2120  pq_sendint64(&buf, time->time);
2121  pq_sendint32(&buf, time->zone);
2123 }
2124 
2125 Datum
2127 {
2129 
2130  PG_RETURN_INT32(anytime_typmodin(true, ta));
2131 }
2132 
2133 Datum
2135 {
2136  int32 typmod = PG_GETARG_INT32(0);
2137 
2138  PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
2139 }
2140 
2141 
2142 /* timetz2tm()
2143  * Convert TIME WITH TIME ZONE data type to POSIX time structure.
2144  */
2145 int
2146 timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
2147 {
2148  TimeOffset trem = time->time;
2149 
2150  tm->tm_hour = trem / USECS_PER_HOUR;
2151  trem -= tm->tm_hour * USECS_PER_HOUR;
2152  tm->tm_min = trem / USECS_PER_MINUTE;
2153  trem -= tm->tm_min * USECS_PER_MINUTE;
2154  tm->tm_sec = trem / USECS_PER_SEC;
2155  *fsec = trem - tm->tm_sec * USECS_PER_SEC;
2156 
2157  if (tzp != NULL)
2158  *tzp = time->zone;
2159 
2160  return 0;
2161 }
2162 
2163 /* timetz_scale()
2164  * Adjust time type for specified scale factor.
2165  * Used by PostgreSQL type system to stuff columns.
2166  */
2167 Datum
2169 {
2170  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2171  int32 typmod = PG_GETARG_INT32(1);
2172  TimeTzADT *result;
2173 
2174  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2175 
2176  result->time = time->time;
2177  result->zone = time->zone;
2178 
2179  AdjustTimeForTypmod(&(result->time), typmod);
2180 
2181  PG_RETURN_TIMETZADT_P(result);
2182 }
2183 
2184 
2185 static int
2187 {
2188  TimeOffset t1,
2189  t2;
2190 
2191  /* Primary sort is by true (GMT-equivalent) time */
2192  t1 = time1->time + (time1->zone * USECS_PER_SEC);
2193  t2 = time2->time + (time2->zone * USECS_PER_SEC);
2194 
2195  if (t1 > t2)
2196  return 1;
2197  if (t1 < t2)
2198  return -1;
2199 
2200  /*
2201  * If same GMT time, sort by timezone; we only want to say that two
2202  * timetz's are equal if both the time and zone parts are equal.
2203  */
2204  if (time1->zone > time2->zone)
2205  return 1;
2206  if (time1->zone < time2->zone)
2207  return -1;
2208 
2209  return 0;
2210 }
2211 
2212 Datum
2214 {
2215  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2216  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2217 
2218  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
2219 }
2220 
2221 Datum
2223 {
2224  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2225  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2226 
2227  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
2228 }
2229 
2230 Datum
2232 {
2233  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2234  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2235 
2236  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
2237 }
2238 
2239 Datum
2241 {
2242  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2243  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2244 
2245  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
2246 }
2247 
2248 Datum
2250 {
2251  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2252  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2253 
2254  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
2255 }
2256 
2257 Datum
2259 {
2260  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2261  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2262 
2263  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
2264 }
2265 
2266 Datum
2268 {
2269  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2270  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2271 
2272  PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
2273 }
2274 
2275 Datum
2277 {
2279  uint32 thash;
2280 
2281  /*
2282  * To avoid any problems with padding bytes in the struct, we figure the
2283  * field hashes separately and XOR them.
2284  */
2286  Int64GetDatumFast(key->time)));
2287  thash ^= DatumGetUInt32(hash_uint32(key->zone));
2288  PG_RETURN_UINT32(thash);
2289 }
2290 
2291 Datum
2293 {
2295  Datum seed = PG_GETARG_DATUM(1);
2296  uint64 thash;
2297 
2298  /* Same approach as timetz_hash */
2300  Int64GetDatumFast(key->time),
2301  seed));
2303  DatumGetInt64(seed)));
2304  PG_RETURN_UINT64(thash);
2305 }
2306 
2307 Datum
2309 {
2310  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2311  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2312  TimeTzADT *result;
2313 
2314  if (timetz_cmp_internal(time1, time2) > 0)
2315  result = time1;
2316  else
2317  result = time2;
2318  PG_RETURN_TIMETZADT_P(result);
2319 }
2320 
2321 Datum
2323 {
2324  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2325  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2326  TimeTzADT *result;
2327 
2328  if (timetz_cmp_internal(time1, time2) < 0)
2329  result = time1;
2330  else
2331  result = time2;
2332  PG_RETURN_TIMETZADT_P(result);
2333 }
2334 
2335 /* timetz_pl_interval()
2336  * Add interval to timetz.
2337  */
2338 Datum
2340 {
2341  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2342  Interval *span = PG_GETARG_INTERVAL_P(1);
2343  TimeTzADT *result;
2344 
2345  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2346 
2347  result->time = time->time + span->time;
2348  result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2349  if (result->time < INT64CONST(0))
2350  result->time += USECS_PER_DAY;
2351 
2352  result->zone = time->zone;
2353 
2354  PG_RETURN_TIMETZADT_P(result);
2355 }
2356 
2357 /* timetz_mi_interval()
2358  * Subtract interval from timetz.
2359  */
2360 Datum
2362 {
2363  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2364  Interval *span = PG_GETARG_INTERVAL_P(1);
2365  TimeTzADT *result;
2366 
2367  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2368 
2369  result->time = time->time - span->time;
2370  result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2371  if (result->time < INT64CONST(0))
2372  result->time += USECS_PER_DAY;
2373 
2374  result->zone = time->zone;
2375 
2376  PG_RETURN_TIMETZADT_P(result);
2377 }
2378 
2379 /*
2380  * in_range support function for timetz.
2381  */
2382 Datum
2384 {
2386  TimeTzADT *base = PG_GETARG_TIMETZADT_P(1);
2387  Interval *offset = PG_GETARG_INTERVAL_P(2);
2388  bool sub = PG_GETARG_BOOL(3);
2389  bool less = PG_GETARG_BOOL(4);
2390  TimeTzADT sum;
2391 
2392  /*
2393  * Like timetz_pl_interval/timetz_mi_interval, we disregard the month and
2394  * day fields of the offset. So our test for negative should too.
2395  */
2396  if (offset->time < 0)
2397  ereport(ERROR,
2398  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
2399  errmsg("invalid preceding or following size in window function")));
2400 
2401  /*
2402  * We can't use timetz_pl_interval/timetz_mi_interval here, because their
2403  * wraparound behavior would give wrong (or at least undesirable) answers.
2404  * Fortunately the equivalent non-wrapping behavior is trivial, especially
2405  * since we don't worry about integer overflow.
2406  */
2407  if (sub)
2408  sum.time = base->time - offset->time;
2409  else
2410  sum.time = base->time + offset->time;
2411  sum.zone = base->zone;
2412 
2413  if (less)
2414  PG_RETURN_BOOL(timetz_cmp_internal(val, &sum) <= 0);
2415  else
2416  PG_RETURN_BOOL(timetz_cmp_internal(val, &sum) >= 0);
2417 }
2418 
2419 /* overlaps_timetz() --- implements the SQL OVERLAPS operator.
2420  *
2421  * Algorithm is per SQL spec. This is much harder than you'd think
2422  * because the spec requires us to deliver a non-null answer in some cases
2423  * where some of the inputs are null.
2424  */
2425 Datum
2427 {
2428  /*
2429  * The arguments are TimeTzADT *, but we leave them as generic Datums for
2430  * convenience of notation --- and to avoid dereferencing nulls.
2431  */
2432  Datum ts1 = PG_GETARG_DATUM(0);
2433  Datum te1 = PG_GETARG_DATUM(1);
2434  Datum ts2 = PG_GETARG_DATUM(2);
2435  Datum te2 = PG_GETARG_DATUM(3);
2436  bool ts1IsNull = PG_ARGISNULL(0);
2437  bool te1IsNull = PG_ARGISNULL(1);
2438  bool ts2IsNull = PG_ARGISNULL(2);
2439  bool te2IsNull = PG_ARGISNULL(3);
2440 
2441 #define TIMETZ_GT(t1,t2) \
2442  DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
2443 #define TIMETZ_LT(t1,t2) \
2444  DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
2445 
2446  /*
2447  * If both endpoints of interval 1 are null, the result is null (unknown).
2448  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2449  * take ts1 as the lesser endpoint.
2450  */
2451  if (ts1IsNull)
2452  {
2453  if (te1IsNull)
2454  PG_RETURN_NULL();
2455  /* swap null for non-null */
2456  ts1 = te1;
2457  te1IsNull = true;
2458  }
2459  else if (!te1IsNull)
2460  {
2461  if (TIMETZ_GT(ts1, te1))
2462  {
2463  Datum tt = ts1;
2464 
2465  ts1 = te1;
2466  te1 = tt;
2467  }
2468  }
2469 
2470  /* Likewise for interval 2. */
2471  if (ts2IsNull)
2472  {
2473  if (te2IsNull)
2474  PG_RETURN_NULL();
2475  /* swap null for non-null */
2476  ts2 = te2;
2477  te2IsNull = true;
2478  }
2479  else if (!te2IsNull)
2480  {
2481  if (TIMETZ_GT(ts2, te2))
2482  {
2483  Datum tt = ts2;
2484 
2485  ts2 = te2;
2486  te2 = tt;
2487  }
2488  }
2489 
2490  /*
2491  * At this point neither ts1 nor ts2 is null, so we can consider three
2492  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2493  */
2494  if (TIMETZ_GT(ts1, ts2))
2495  {
2496  /*
2497  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2498  * in the presence of nulls it's not quite completely so.
2499  */
2500  if (te2IsNull)
2501  PG_RETURN_NULL();
2502  if (TIMETZ_LT(ts1, te2))
2503  PG_RETURN_BOOL(true);
2504  if (te1IsNull)
2505  PG_RETURN_NULL();
2506 
2507  /*
2508  * If te1 is not null then we had ts1 <= te1 above, and we just found
2509  * ts1 >= te2, hence te1 >= te2.
2510  */
2511  PG_RETURN_BOOL(false);
2512  }
2513  else if (TIMETZ_LT(ts1, ts2))
2514  {
2515  /* This case is ts2 < te1 OR te2 < te1 */
2516  if (te1IsNull)
2517  PG_RETURN_NULL();
2518  if (TIMETZ_LT(ts2, te1))
2519  PG_RETURN_BOOL(true);
2520  if (te2IsNull)
2521  PG_RETURN_NULL();
2522 
2523  /*
2524  * If te2 is not null then we had ts2 <= te2 above, and we just found
2525  * ts2 >= te1, hence te2 >= te1.
2526  */
2527  PG_RETURN_BOOL(false);
2528  }
2529  else
2530  {
2531  /*
2532  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2533  * rather silly way of saying "true if both are nonnull, else null".
2534  */
2535  if (te1IsNull || te2IsNull)
2536  PG_RETURN_NULL();
2537  PG_RETURN_BOOL(true);
2538  }
2539 
2540 #undef TIMETZ_GT
2541 #undef TIMETZ_LT
2542 }
2543 
2544 
2545 Datum
2547 {
2548  TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
2549  TimeADT result;
2550 
2551  /* swallow the time zone and just return the time */
2552  result = timetz->time;
2553 
2554  PG_RETURN_TIMEADT(result);
2555 }
2556 
2557 
2558 Datum
2560 {
2561  TimeADT time = PG_GETARG_TIMEADT(0);
2562  TimeTzADT *result;
2563  struct pg_tm tt,
2564  *tm = &tt;
2565  fsec_t fsec;
2566  int tz;
2567 
2568  GetCurrentDateTime(tm);
2569  time2tm(time, tm, &fsec);
2571 
2572  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2573 
2574  result->time = time;
2575  result->zone = tz;
2576 
2577  PG_RETURN_TIMETZADT_P(result);
2578 }
2579 
2580 
2581 /* timestamptz_timetz()
2582  * Convert timestamp to timetz data type.
2583  */
2584 Datum
2586 {
2588  TimeTzADT *result;
2589  struct pg_tm tt,
2590  *tm = &tt;
2591  int tz;
2592  fsec_t fsec;
2593 
2594  if (TIMESTAMP_NOT_FINITE(timestamp))
2595  PG_RETURN_NULL();
2596 
2597  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
2598  ereport(ERROR,
2599  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2600  errmsg("timestamp out of range")));
2601 
2602  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2603 
2604  tm2timetz(tm, fsec, tz, result);
2605 
2606  PG_RETURN_TIMETZADT_P(result);
2607 }
2608 
2609 
2610 /* datetimetz_timestamptz()
2611  * Convert date and timetz to timestamp with time zone data type.
2612  * Timestamp is stored in GMT, so add the time zone
2613  * stored with the timetz to the result.
2614  * - thomas 2000-03-10
2615  */
2616 Datum
2618 {
2620  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2621  TimestampTz result;
2622 
2623  if (DATE_IS_NOBEGIN(date))
2624  TIMESTAMP_NOBEGIN(result);
2625  else if (DATE_IS_NOEND(date))
2626  TIMESTAMP_NOEND(result);
2627  else
2628  {
2629  /*
2630  * Date's range is wider than timestamp's, so check for boundaries.
2631  * Since dates have the same minimum values as timestamps, only upper
2632  * boundary need be checked for overflow.
2633  */
2635  ereport(ERROR,
2636  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2637  errmsg("date out of range for timestamp")));
2638  result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
2639 
2640  /*
2641  * Since it is possible to go beyond allowed timestamptz range because
2642  * of time zone, check for allowed timestamp range after adding tz.
2643  */
2644  if (!IS_VALID_TIMESTAMP(result))
2645  ereport(ERROR,
2646  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2647  errmsg("date out of range for timestamp")));
2648  }
2649 
2650  PG_RETURN_TIMESTAMP(result);
2651 }
2652 
2653 
2654 /* timetz_part()
2655  * Extract specified field from time type.
2656  */
2657 Datum
2659 {
2660  text *units = PG_GETARG_TEXT_PP(0);
2661  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2662  float8 result;
2663  int type,
2664  val;
2665  char *lowunits;
2666 
2667  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
2668  VARSIZE_ANY_EXHDR(units),
2669  false);
2670 
2671  type = DecodeUnits(0, lowunits, &val);
2672  if (type == UNKNOWN_FIELD)
2673  type = DecodeSpecial(0, lowunits, &val);
2674 
2675  if (type == UNITS)
2676  {
2677  double dummy;
2678  int tz;
2679  fsec_t fsec;
2680  struct pg_tm tt,
2681  *tm = &tt;
2682 
2683  timetz2tm(time, tm, &fsec, &tz);
2684 
2685  switch (val)
2686  {
2687  case DTK_TZ:
2688  result = -tz;
2689  break;
2690 
2691  case DTK_TZ_MINUTE:
2692  result = -tz;
2693  result /= SECS_PER_MINUTE;
2694  FMODULO(result, dummy, (double) SECS_PER_MINUTE);
2695  break;
2696 
2697  case DTK_TZ_HOUR:
2698  dummy = -tz;
2699  FMODULO(dummy, result, (double) SECS_PER_HOUR);
2700  break;
2701 
2702  case DTK_MICROSEC:
2703  result = tm->tm_sec * 1000000.0 + fsec;
2704  break;
2705 
2706  case DTK_MILLISEC:
2707  result = tm->tm_sec * 1000.0 + fsec / 1000.0;
2708  break;
2709 
2710  case DTK_SECOND:
2711  result = tm->tm_sec + fsec / 1000000.0;
2712  break;
2713 
2714  case DTK_MINUTE:
2715  result = tm->tm_min;
2716  break;
2717 
2718  case DTK_HOUR:
2719  result = tm->tm_hour;
2720  break;
2721 
2722  case DTK_DAY:
2723  case DTK_MONTH:
2724  case DTK_QUARTER:
2725  case DTK_YEAR:
2726  case DTK_DECADE:
2727  case DTK_CENTURY:
2728  case DTK_MILLENNIUM:
2729  default:
2730  ereport(ERROR,
2731  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2732  errmsg("\"time with time zone\" units \"%s\" not recognized",
2733  lowunits)));
2734  result = 0;
2735  }
2736  }
2737  else if (type == RESERV && val == DTK_EPOCH)
2738  {
2739  result = time->time / 1000000.0 + time->zone;
2740  }
2741  else
2742  {
2743  ereport(ERROR,
2744  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2745  errmsg("\"time with time zone\" units \"%s\" not recognized",
2746  lowunits)));
2747  result = 0;
2748  }
2749 
2750  PG_RETURN_FLOAT8(result);
2751 }
2752 
2753 /* timetz_zone()
2754  * Encode time with time zone type with specified time zone.
2755  * Applies DST rules as of the current date.
2756  */
2757 Datum
2759 {
2760  text *zone = PG_GETARG_TEXT_PP(0);
2762  TimeTzADT *result;
2763  int tz;
2764  char tzname[TZ_STRLEN_MAX + 1];
2765  char *lowzone;
2766  int type,
2767  val;
2768  pg_tz *tzp;
2769 
2770  /*
2771  * Look up the requested timezone. First we look in the timezone
2772  * abbreviation table (to handle cases like "EST"), and if that fails, we
2773  * look in the timezone database (to handle cases like
2774  * "America/New_York"). (This matches the order in which timestamp input
2775  * checks the cases; it's important because the timezone database unwisely
2776  * uses a few zone names that are identical to offset abbreviations.)
2777  */
2778  text_to_cstring_buffer(zone, tzname, sizeof(tzname));
2779 
2780  /* DecodeTimezoneAbbrev requires lowercase input */
2781  lowzone = downcase_truncate_identifier(tzname,
2782  strlen(tzname),
2783  false);
2784 
2785  type = DecodeTimezoneAbbrev(0, lowzone, &val, &tzp);
2786 
2787  if (type == TZ || type == DTZ)
2788  {
2789  /* fixed-offset abbreviation */
2790  tz = -val;
2791  }
2792  else if (type == DYNTZ)
2793  {
2794  /* dynamic-offset abbreviation, resolve using current time */
2795  pg_time_t now = (pg_time_t) time(NULL);
2796  struct pg_tm *tm;
2797 
2798  tm = pg_localtime(&now, tzp);
2799  tz = DetermineTimeZoneAbbrevOffset(tm, tzname, tzp);
2800  }
2801  else
2802  {
2803  /* try it as a full zone name */
2804  tzp = pg_tzset(tzname);
2805  if (tzp)
2806  {
2807  /* Get the offset-from-GMT that is valid today for the zone */
2808  pg_time_t now = (pg_time_t) time(NULL);
2809  struct pg_tm *tm;
2810 
2811  tm = pg_localtime(&now, tzp);
2812  tz = -tm->tm_gmtoff;
2813  }
2814  else
2815  {
2816  ereport(ERROR,
2817  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2818  errmsg("time zone \"%s\" not recognized", tzname)));
2819  tz = 0; /* keep compiler quiet */
2820  }
2821  }
2822 
2823  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2824 
2825  result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
2826  while (result->time < INT64CONST(0))
2827  result->time += USECS_PER_DAY;
2828  while (result->time >= USECS_PER_DAY)
2829  result->time -= USECS_PER_DAY;
2830 
2831  result->zone = tz;
2832 
2833  PG_RETURN_TIMETZADT_P(result);
2834 }
2835 
2836 /* timetz_izone()
2837  * Encode time with time zone type with specified time interval as time zone.
2838  */
2839 Datum
2841 {
2843  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2844  TimeTzADT *result;
2845  int tz;
2846 
2847  if (zone->month != 0 || zone->day != 0)
2848  ereport(ERROR,
2849  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2850  errmsg("interval time zone \"%s\" must not include months or days",
2852  PointerGetDatum(zone))))));
2853 
2854  tz = -(zone->time / USECS_PER_SEC);
2855 
2856  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2857 
2858  result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
2859  while (result->time < INT64CONST(0))
2860  result->time += USECS_PER_DAY;
2861  while (result->time >= USECS_PER_DAY)
2862  result->time -= USECS_PER_DAY;
2863 
2864  result->zone = tz;
2865 
2866  PG_RETURN_TIMETZADT_P(result);
2867 }
#define MAXDATELEN
Definition: datetime.h:201
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3858
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
Datum date_cmp_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:878
#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:1343
Datum timetz_cmp(PG_FUNCTION_ARGS)
Definition: date.c:2267
#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:1863
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:2339
#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:2258
#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:348
Datum time_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:1845
#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:902
#define PG_RETURN_TIMETZADT_P(x)
Definition: date.h:67
void DateTimeParseError(int dterr, const char *str, const char *datatype)
Definition: datetime.c:3739
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Datum time_part(PG_FUNCTION_ARGS)
Definition: date.c:1921
int64 pg_time_t
Definition: pgtime.h:23
TimeADT time
Definition: date.h:29
Datum timetz_scale(PG_FUNCTION_ARGS)
Definition: date.c:2168
#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:2222
#define DTK_YEAR
Definition: datetime.h:168
Datum datetime_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1755
#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:2249
int64 timestamp
Datum timestamptz_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:986
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:131
#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:1144
Datum time_le(PG_FUNCTION_ARGS)
Definition: date.c:1496
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
Timestamp date2timestamp_opt_error(DateADT dateVal, bool *have_error)
Definition: date.c:561
#define DTK_QUARTER
Definition: datetime.h:167
Datum date_ne_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:818
Datum date_eq_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:722
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:950
#define PG_RETURN_TIMEADT(x)
Definition: date.h:66
StringInfoData * StringInfo
Definition: stringinfo.h:43
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356
Datum timetz_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:2292
#define FMODULO(t, q, u)
Definition: datetime.h:238
Datum time_eq(PG_FUNCTION_ARGS)
Definition: date.c:1469
Datum timetypmodout(PG_FUNCTION_ARGS)
Definition: date.c:1351
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
Datum time_interval(PG_FUNCTION_ARGS)
Definition: date.c:1778
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:3943
#define DTK_MILLENNIUM
Definition: datetime.h:171
Datum in_range_time_interval(PG_FUNCTION_ARGS)
Definition: date.c:1881
#define USECS_PER_MINUTE
Definition: timestamp.h:93
int errcode(int sqlerrcode)
Definition: elog.c:570
Datum date_lt_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:830
Datum timetz_lt(PG_FUNCTION_ARGS)
Definition: date.c:2231
int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
Definition: date.c:1273
double date2timestamp_no_overflow(DateADT dateVal)
Definition: date.c:699
#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:2361
int DecodeUnits(int field, char *lowtoken, int *val)
Definition: datetime.c:3702
Datum timestamptz_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:1046
Datum timestamp_gt_date(PG_FUNCTION_ARGS)
Definition: date.c:926
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
#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:2186
Datum date_eq_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:806
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:1064
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:1717
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:346
Datum datetimetz_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:2617
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:938
static struct pg_tm tm
Definition: localtime.c:108
Datum time_scale(PG_FUNCTION_ARGS)
Definition: date.c:1414
#define DATE_NOBEGIN(j)
Definition: date.h:39
int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:2012
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:1548
#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:2383
#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:761
#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:491
Datum time_lt(PG_FUNCTION_ARGS)
Definition: date.c:1487
#define DatumGetCString(X)
Definition: postgres.h:566
int DecodeTimezoneAbbrev(int field, char *lowtoken, int *offset, pg_tz **tz)
Definition: datetime.c:2956
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:1523
#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:1362
Datum time_out(PG_FUNCTION_ARGS)
Definition: date.c:1286
Datum timetztypmodin(PG_FUNCTION_ARGS)
Definition: date.c:2126
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:321
Datum timetz_send(PG_FUNCTION_ARGS)
Definition: date.c:2114
Datum time_gt(PG_FUNCTION_ARGS)
Definition: date.c:1505
#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
Datum date_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1130
Datum date_gt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:758
int tm_mday
Definition: pgtime.h:30
static char * buf
Definition: pg_test_fsync.c:68
#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:1441
#define SECS_PER_MINUTE
Definition: timestamp.h:88
Datum timetztypmodout(PG_FUNCTION_ARGS)
Definition: date.c:2134
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:358
#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:1189
#define DTK_ISOYEAR
Definition: datetime.h:180
const char *const days[]
Definition: datetime.c:69
Datum timestamptz_le_date(PG_FUNCTION_ARGS)
Definition: date.c:1022
int32 fsec_t
Definition: timestamp.h:41
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:2240
#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:295
#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:1306
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:625
Datum date_le_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:854
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:783
Datum date_lt_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:746
#define WARNING
Definition: elog.h:40
Datum date_cmp_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:794
#define DTK_LATE
Definition: datetime.h:152
Datum timetz_zone(PG_FUNCTION_ARGS)
Definition: date.c:2758
int64 TimeOffset
Definition: timestamp.h:40
static TimestampTz date2timestamptz(DateADT dateVal)
Definition: date.c:683
#define DTK_MICROSEC
Definition: datetime.h:173
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4467
#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:2146
#define timestamptz_cmp_internal(dt1, dt2)
Definition: timestamp.h:98
Definition: pgtz.h:65
#define Int64GetDatumFast(X)
Definition: postgres.h:775
#define BoolGetDatum(X)
Definition: postgres.h:402
Datum time_ne(PG_FUNCTION_ARGS)
Definition: date.c:1478
Datum time_send(PG_FUNCTION_ARGS)
Definition: date.c:1332
int date2j(int y, int m, int d)
Definition: datetime.c:270
#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:842
#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:1034
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2546
Datum timetz_smaller(PG_FUNCTION_ARGS)
Definition: date.c:2322
Datum timestamptz_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:998
#define PG_ARGISNULL(n)
Definition: fmgr.h:204
Datum timestamp_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:962
Datum timetz_recv(PG_FUNCTION_ARGS)
Definition: date.c:2078
int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result)
Definition: date.c:1258
Datum time_hash_extended(PG_FUNCTION_ARGS)
Definition: date.c:1542
#define PG_GETARG_TIMEADT(n)
Definition: date.h:62
Datum time_support(PG_FUNCTION_ARGS)
Definition: date.c:1394
Datum interval_time(PG_FUNCTION_ARGS)
Definition: date.c:1801
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:352
Datum timetz_eq(PG_FUNCTION_ARGS)
Definition: date.c:2213
#define DTK_EARLY
Definition: datetime.h:151
Datum timetz_hash(PG_FUNCTION_ARGS)
Definition: date.c:2276
#define MAXDATEFIELDS
Definition: datetime.h:203
Datum overlaps_time(PG_FUNCTION_ARGS)
Definition: date.c:1572
#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:3011
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:1557
Datum date_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:866
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2585
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2559
Datum date_ne_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:734
Datum date_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:1174
#define DTZ
Definition: datetime.h:97
#define DTK_EPOCH
Definition: datetime.h:153
Datum date_le_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:770
Datum timetz_part(PG_FUNCTION_ARGS)
Definition: date.c:2658
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:39
Definition: zic.c:98
Datum timetz_in(PG_FUNCTION_ARGS)
Definition: date.c:2022
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:784
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:1826
#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:1010
#define elog(elevel,...)
Definition: elog.h:226
Datum time_in(PG_FUNCTION_ARGS)
Definition: date.c:1221
Datum timestamptz_eq_date(PG_FUNCTION_ARGS)
Definition: date.c:974
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:455
Datum date_ge_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:782
Datum date_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:1113
Datum timestamp_time(PG_FUNCTION_ARGS)
Definition: date.c:1694
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2017
Datum timestamp_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:914
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:272
Definition: c.h:549
#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:602
#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:540
Datum time_ge(PG_FUNCTION_ARGS)
Definition: date.c:1514
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:2426
void AdjustTimeForTypmod(TimeADT *time, int32 typmod)
Definition: date.c:1434
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1602
Datum timetz_larger(PG_FUNCTION_ARGS)
Definition: date.c:2308
long val
Definition: informix.c:684
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:619
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define DTK_DATE
Definition: datetime.h:145
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:2057
#define DATE_NOEND(j)
Definition: date.h:41
Datum time_hash(PG_FUNCTION_ARGS)
Definition: date.c:1536
Datum date_pl_interval(PG_FUNCTION_ARGS)
Definition: date.c:1093
Datum timestamptz_time(PG_FUNCTION_ARGS)
Definition: date.c:1724
#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:890
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2451
Datum timetz_izone(PG_FUNCTION_ARGS)
Definition: date.c:2840
TimestampTz date2timestamptz_opt_error(DateADT dateVal, bool *have_error)
Definition: date.c:614
Datum date_pli(PG_FUNCTION_ARGS)
Definition: date.c:508