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