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