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_sendint(&buf, date, sizeof(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 {
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 {
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);
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
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  TimeADT time1 = PG_GETARG_TIMEADT(0);
1515  TimeADT time2 = PG_GETARG_TIMEADT(1);
1516 
1517  PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);
1518 }
1519 
1520 Datum
1522 {
1523  TimeADT time1 = PG_GETARG_TIMEADT(0);
1524  TimeADT time2 = PG_GETARG_TIMEADT(1);
1525 
1526  PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);
1527 }
1528 
1529 /* overlaps_time() --- implements the SQL OVERLAPS operator.
1530  *
1531  * Algorithm is per SQL spec. This is much harder than you'd think
1532  * because the spec requires us to deliver a non-null answer in some cases
1533  * where some of the inputs are null.
1534  */
1535 Datum
1537 {
1538  /*
1539  * The arguments are TimeADT, but we leave them as generic Datums to avoid
1540  * dereferencing nulls (TimeADT is pass-by-reference!)
1541  */
1542  Datum ts1 = PG_GETARG_DATUM(0);
1543  Datum te1 = PG_GETARG_DATUM(1);
1544  Datum ts2 = PG_GETARG_DATUM(2);
1545  Datum te2 = PG_GETARG_DATUM(3);
1546  bool ts1IsNull = PG_ARGISNULL(0);
1547  bool te1IsNull = PG_ARGISNULL(1);
1548  bool ts2IsNull = PG_ARGISNULL(2);
1549  bool te2IsNull = PG_ARGISNULL(3);
1550 
1551 #define TIMEADT_GT(t1,t2) \
1552  (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))
1553 #define TIMEADT_LT(t1,t2) \
1554  (DatumGetTimeADT(t1) < DatumGetTimeADT(t2))
1555 
1556  /*
1557  * If both endpoints of interval 1 are null, the result is null (unknown).
1558  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
1559  * take ts1 as the lesser endpoint.
1560  */
1561  if (ts1IsNull)
1562  {
1563  if (te1IsNull)
1564  PG_RETURN_NULL();
1565  /* swap null for non-null */
1566  ts1 = te1;
1567  te1IsNull = true;
1568  }
1569  else if (!te1IsNull)
1570  {
1571  if (TIMEADT_GT(ts1, te1))
1572  {
1573  Datum tt = ts1;
1574 
1575  ts1 = te1;
1576  te1 = tt;
1577  }
1578  }
1579 
1580  /* Likewise for interval 2. */
1581  if (ts2IsNull)
1582  {
1583  if (te2IsNull)
1584  PG_RETURN_NULL();
1585  /* swap null for non-null */
1586  ts2 = te2;
1587  te2IsNull = true;
1588  }
1589  else if (!te2IsNull)
1590  {
1591  if (TIMEADT_GT(ts2, te2))
1592  {
1593  Datum tt = ts2;
1594 
1595  ts2 = te2;
1596  te2 = tt;
1597  }
1598  }
1599 
1600  /*
1601  * At this point neither ts1 nor ts2 is null, so we can consider three
1602  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
1603  */
1604  if (TIMEADT_GT(ts1, ts2))
1605  {
1606  /*
1607  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
1608  * in the presence of nulls it's not quite completely so.
1609  */
1610  if (te2IsNull)
1611  PG_RETURN_NULL();
1612  if (TIMEADT_LT(ts1, te2))
1613  PG_RETURN_BOOL(true);
1614  if (te1IsNull)
1615  PG_RETURN_NULL();
1616 
1617  /*
1618  * If te1 is not null then we had ts1 <= te1 above, and we just found
1619  * ts1 >= te2, hence te1 >= te2.
1620  */
1621  PG_RETURN_BOOL(false);
1622  }
1623  else if (TIMEADT_LT(ts1, ts2))
1624  {
1625  /* This case is ts2 < te1 OR te2 < te1 */
1626  if (te1IsNull)
1627  PG_RETURN_NULL();
1628  if (TIMEADT_LT(ts2, te1))
1629  PG_RETURN_BOOL(true);
1630  if (te2IsNull)
1631  PG_RETURN_NULL();
1632 
1633  /*
1634  * If te2 is not null then we had ts2 <= te2 above, and we just found
1635  * ts2 >= te1, hence te2 >= te1.
1636  */
1637  PG_RETURN_BOOL(false);
1638  }
1639  else
1640  {
1641  /*
1642  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
1643  * rather silly way of saying "true if both are nonnull, else null".
1644  */
1645  if (te1IsNull || te2IsNull)
1646  PG_RETURN_NULL();
1647  PG_RETURN_BOOL(true);
1648  }
1649 
1650 #undef TIMEADT_GT
1651 #undef TIMEADT_LT
1652 }
1653 
1654 /* timestamp_time()
1655  * Convert timestamp to time data type.
1656  */
1657 Datum
1659 {
1661  TimeADT result;
1662  struct pg_tm tt,
1663  *tm = &tt;
1664  fsec_t fsec;
1665 
1666  if (TIMESTAMP_NOT_FINITE(timestamp))
1667  PG_RETURN_NULL();
1668 
1669  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
1670  ereport(ERROR,
1671  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1672  errmsg("timestamp out of range")));
1673 
1674  /*
1675  * Could also do this with time = (timestamp / USECS_PER_DAY *
1676  * USECS_PER_DAY) - timestamp;
1677  */
1678  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1679  USECS_PER_SEC) + fsec;
1680 
1681  PG_RETURN_TIMEADT(result);
1682 }
1683 
1684 /* timestamptz_time()
1685  * Convert timestamptz to time data type.
1686  */
1687 Datum
1689 {
1691  TimeADT result;
1692  struct pg_tm tt,
1693  *tm = &tt;
1694  int tz;
1695  fsec_t fsec;
1696 
1697  if (TIMESTAMP_NOT_FINITE(timestamp))
1698  PG_RETURN_NULL();
1699 
1700  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
1701  ereport(ERROR,
1702  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1703  errmsg("timestamp out of range")));
1704 
1705  /*
1706  * Could also do this with time = (timestamp / USECS_PER_DAY *
1707  * USECS_PER_DAY) - timestamp;
1708  */
1709  result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1710  USECS_PER_SEC) + fsec;
1711 
1712  PG_RETURN_TIMEADT(result);
1713 }
1714 
1715 /* datetime_timestamp()
1716  * Convert date and time to timestamp data type.
1717  */
1718 Datum
1720 {
1722  TimeADT time = PG_GETARG_TIMEADT(1);
1723  Timestamp result;
1724 
1725  result = date2timestamp(date);
1726  if (!TIMESTAMP_NOT_FINITE(result))
1727  {
1728  result += time;
1729  if (!IS_VALID_TIMESTAMP(result))
1730  ereport(ERROR,
1731  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1732  errmsg("timestamp out of range")));
1733  }
1734 
1735  PG_RETURN_TIMESTAMP(result);
1736 }
1737 
1738 /* time_interval()
1739  * Convert time to interval data type.
1740  */
1741 Datum
1743 {
1744  TimeADT time = PG_GETARG_TIMEADT(0);
1745  Interval *result;
1746 
1747  result = (Interval *) palloc(sizeof(Interval));
1748 
1749  result->time = time;
1750  result->day = 0;
1751  result->month = 0;
1752 
1753  PG_RETURN_INTERVAL_P(result);
1754 }
1755 
1756 /* interval_time()
1757  * Convert interval to time data type.
1758  *
1759  * This is defined as producing the fractional-day portion of the interval.
1760  * Therefore, we can just ignore the months field. It is not real clear
1761  * what to do with negative intervals, but we choose to subtract the floor,
1762  * so that, say, '-2 hours' becomes '22:00:00'.
1763  */
1764 Datum
1766 {
1767  Interval *span = PG_GETARG_INTERVAL_P(0);
1768  TimeADT result;
1769  int64 days;
1770 
1771  result = span->time;
1772  if (result >= USECS_PER_DAY)
1773  {
1774  days = result / USECS_PER_DAY;
1775  result -= days * USECS_PER_DAY;
1776  }
1777  else if (result < 0)
1778  {
1779  days = (-result + USECS_PER_DAY - 1) / USECS_PER_DAY;
1780  result += days * USECS_PER_DAY;
1781  }
1782 
1783  PG_RETURN_TIMEADT(result);
1784 }
1785 
1786 /* time_mi_time()
1787  * Subtract two times to produce an interval.
1788  */
1789 Datum
1791 {
1792  TimeADT time1 = PG_GETARG_TIMEADT(0);
1793  TimeADT time2 = PG_GETARG_TIMEADT(1);
1794  Interval *result;
1795 
1796  result = (Interval *) palloc(sizeof(Interval));
1797 
1798  result->month = 0;
1799  result->day = 0;
1800  result->time = time1 - time2;
1801 
1802  PG_RETURN_INTERVAL_P(result);
1803 }
1804 
1805 /* time_pl_interval()
1806  * Add interval to time.
1807  */
1808 Datum
1810 {
1811  TimeADT time = PG_GETARG_TIMEADT(0);
1812  Interval *span = PG_GETARG_INTERVAL_P(1);
1813  TimeADT result;
1814 
1815  result = time + span->time;
1816  result -= result / USECS_PER_DAY * USECS_PER_DAY;
1817  if (result < INT64CONST(0))
1818  result += USECS_PER_DAY;
1819 
1820  PG_RETURN_TIMEADT(result);
1821 }
1822 
1823 /* time_mi_interval()
1824  * Subtract interval from time.
1825  */
1826 Datum
1828 {
1829  TimeADT time = PG_GETARG_TIMEADT(0);
1830  Interval *span = PG_GETARG_INTERVAL_P(1);
1831  TimeADT result;
1832 
1833  result = time - span->time;
1834  result -= result / USECS_PER_DAY * USECS_PER_DAY;
1835  if (result < INT64CONST(0))
1836  result += USECS_PER_DAY;
1837 
1838  PG_RETURN_TIMEADT(result);
1839 }
1840 
1841 
1842 /* time_part()
1843  * Extract specified field from time type.
1844  */
1845 Datum
1847 {
1848  text *units = PG_GETARG_TEXT_PP(0);
1849  TimeADT time = PG_GETARG_TIMEADT(1);
1850  float8 result;
1851  int type,
1852  val;
1853  char *lowunits;
1854 
1855  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
1856  VARSIZE_ANY_EXHDR(units),
1857  false);
1858 
1859  type = DecodeUnits(0, lowunits, &val);
1860  if (type == UNKNOWN_FIELD)
1861  type = DecodeSpecial(0, lowunits, &val);
1862 
1863  if (type == UNITS)
1864  {
1865  fsec_t fsec;
1866  struct pg_tm tt,
1867  *tm = &tt;
1868 
1869  time2tm(time, tm, &fsec);
1870 
1871  switch (val)
1872  {
1873  case DTK_MICROSEC:
1874  result = tm->tm_sec * 1000000.0 + fsec;
1875  break;
1876 
1877  case DTK_MILLISEC:
1878  result = tm->tm_sec * 1000.0 + fsec / 1000.0;
1879  break;
1880 
1881  case DTK_SECOND:
1882  result = tm->tm_sec + fsec / 1000000.0;
1883  break;
1884 
1885  case DTK_MINUTE:
1886  result = tm->tm_min;
1887  break;
1888 
1889  case DTK_HOUR:
1890  result = tm->tm_hour;
1891  break;
1892 
1893  case DTK_TZ:
1894  case DTK_TZ_MINUTE:
1895  case DTK_TZ_HOUR:
1896  case DTK_DAY:
1897  case DTK_MONTH:
1898  case DTK_QUARTER:
1899  case DTK_YEAR:
1900  case DTK_DECADE:
1901  case DTK_CENTURY:
1902  case DTK_MILLENNIUM:
1903  case DTK_ISOYEAR:
1904  default:
1905  ereport(ERROR,
1906  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1907  errmsg("\"time\" units \"%s\" not recognized",
1908  lowunits)));
1909  result = 0;
1910  }
1911  }
1912  else if (type == RESERV && val == DTK_EPOCH)
1913  {
1914  result = time / 1000000.0;
1915  }
1916  else
1917  {
1918  ereport(ERROR,
1919  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1920  errmsg("\"time\" units \"%s\" not recognized",
1921  lowunits)));
1922  result = 0;
1923  }
1924 
1925  PG_RETURN_FLOAT8(result);
1926 }
1927 
1928 
1929 /*****************************************************************************
1930  * Time With Time Zone ADT
1931  *****************************************************************************/
1932 
1933 /* tm2timetz()
1934  * Convert a tm structure to a time data type.
1935  */
1936 static int
1937 tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
1938 {
1939  result->time = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) *
1940  USECS_PER_SEC) + fsec;
1941  result->zone = tz;
1942 
1943  return 0;
1944 }
1945 
1946 Datum
1948 {
1949  char *str = PG_GETARG_CSTRING(0);
1950 
1951 #ifdef NOT_USED
1952  Oid typelem = PG_GETARG_OID(1);
1953 #endif
1954  int32 typmod = PG_GETARG_INT32(2);
1955  TimeTzADT *result;
1956  fsec_t fsec;
1957  struct pg_tm tt,
1958  *tm = &tt;
1959  int tz;
1960  int nf;
1961  int dterr;
1962  char workbuf[MAXDATELEN + 1];
1963  char *field[MAXDATEFIELDS];
1964  int dtype;
1965  int ftype[MAXDATEFIELDS];
1966 
1967  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
1968  field, ftype, MAXDATEFIELDS, &nf);
1969  if (dterr == 0)
1970  dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);
1971  if (dterr != 0)
1972  DateTimeParseError(dterr, str, "time with time zone");
1973 
1974  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
1975  tm2timetz(tm, fsec, tz, result);
1976  AdjustTimeForTypmod(&(result->time), typmod);
1977 
1978  PG_RETURN_TIMETZADT_P(result);
1979 }
1980 
1981 Datum
1983 {
1984  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
1985  char *result;
1986  struct pg_tm tt,
1987  *tm = &tt;
1988  fsec_t fsec;
1989  int tz;
1990  char buf[MAXDATELEN + 1];
1991 
1992  timetz2tm(time, tm, &fsec, &tz);
1993  EncodeTimeOnly(tm, fsec, true, tz, DateStyle, buf);
1994 
1995  result = pstrdup(buf);
1996  PG_RETURN_CSTRING(result);
1997 }
1998 
1999 /*
2000  * timetz_recv - converts external binary format to timetz
2001  */
2002 Datum
2004 {
2006 
2007 #ifdef NOT_USED
2008  Oid typelem = PG_GETARG_OID(1);
2009 #endif
2010  int32 typmod = PG_GETARG_INT32(2);
2011  TimeTzADT *result;
2012 
2013  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2014 
2015  result->time = pq_getmsgint64(buf);
2016 
2017  if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
2018  ereport(ERROR,
2019  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2020  errmsg("time out of range")));
2021 
2022  result->zone = pq_getmsgint(buf, sizeof(result->zone));
2023 
2024  /* Check for sane GMT displacement; see notes in datatype/timestamp.h */
2025  if (result->zone <= -TZDISP_LIMIT || result->zone >= TZDISP_LIMIT)
2026  ereport(ERROR,
2027  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
2028  errmsg("time zone displacement out of range")));
2029 
2030  AdjustTimeForTypmod(&(result->time), typmod);
2031 
2032  PG_RETURN_TIMETZADT_P(result);
2033 }
2034 
2035 /*
2036  * timetz_send - converts timetz to binary format
2037  */
2038 Datum
2040 {
2041  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2043 
2044  pq_begintypsend(&buf);
2045  pq_sendint64(&buf, time->time);
2046  pq_sendint(&buf, time->zone, sizeof(time->zone));
2048 }
2049 
2050 Datum
2052 {
2054 
2055  PG_RETURN_INT32(anytime_typmodin(true, ta));
2056 }
2057 
2058 Datum
2060 {
2061  int32 typmod = PG_GETARG_INT32(0);
2062 
2063  PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
2064 }
2065 
2066 
2067 /* timetz2tm()
2068  * Convert TIME WITH TIME ZONE data type to POSIX time structure.
2069  */
2070 static int
2071 timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp)
2072 {
2073  TimeOffset trem = time->time;
2074 
2075  tm->tm_hour = trem / USECS_PER_HOUR;
2076  trem -= tm->tm_hour * USECS_PER_HOUR;
2077  tm->tm_min = trem / USECS_PER_MINUTE;
2078  trem -= tm->tm_min * USECS_PER_MINUTE;
2079  tm->tm_sec = trem / USECS_PER_SEC;
2080  *fsec = trem - tm->tm_sec * USECS_PER_SEC;
2081 
2082  if (tzp != NULL)
2083  *tzp = time->zone;
2084 
2085  return 0;
2086 }
2087 
2088 /* timetz_scale()
2089  * Adjust time type for specified scale factor.
2090  * Used by PostgreSQL type system to stuff columns.
2091  */
2092 Datum
2094 {
2095  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2096  int32 typmod = PG_GETARG_INT32(1);
2097  TimeTzADT *result;
2098 
2099  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2100 
2101  result->time = time->time;
2102  result->zone = time->zone;
2103 
2104  AdjustTimeForTypmod(&(result->time), typmod);
2105 
2106  PG_RETURN_TIMETZADT_P(result);
2107 }
2108 
2109 
2110 static int
2112 {
2113  TimeOffset t1,
2114  t2;
2115 
2116  /* Primary sort is by true (GMT-equivalent) time */
2117  t1 = time1->time + (time1->zone * USECS_PER_SEC);
2118  t2 = time2->time + (time2->zone * USECS_PER_SEC);
2119 
2120  if (t1 > t2)
2121  return 1;
2122  if (t1 < t2)
2123  return -1;
2124 
2125  /*
2126  * If same GMT time, sort by timezone; we only want to say that two
2127  * timetz's are equal if both the time and zone parts are equal.
2128  */
2129  if (time1->zone > time2->zone)
2130  return 1;
2131  if (time1->zone < time2->zone)
2132  return -1;
2133 
2134  return 0;
2135 }
2136 
2137 Datum
2139 {
2140  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2141  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2142 
2143  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
2144 }
2145 
2146 Datum
2148 {
2149  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2150  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2151 
2152  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
2153 }
2154 
2155 Datum
2157 {
2158  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2159  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2160 
2161  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
2162 }
2163 
2164 Datum
2166 {
2167  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2168  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2169 
2170  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
2171 }
2172 
2173 Datum
2175 {
2176  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2177  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2178 
2179  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
2180 }
2181 
2182 Datum
2184 {
2185  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2186  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2187 
2188  PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
2189 }
2190 
2191 Datum
2193 {
2194  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2195  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2196 
2197  PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
2198 }
2199 
2200 Datum
2202 {
2203  TimeTzADT *key = PG_GETARG_TIMETZADT_P(0);
2204  uint32 thash;
2205 
2206  /*
2207  * To avoid any problems with padding bytes in the struct, we figure the
2208  * field hashes separately and XOR them.
2209  */
2211  Int64GetDatumFast(key->time)));
2212  thash ^= DatumGetUInt32(hash_uint32(key->zone));
2213  PG_RETURN_UINT32(thash);
2214 }
2215 
2216 Datum
2218 {
2219  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2220  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2221  TimeTzADT *result;
2222 
2223  if (timetz_cmp_internal(time1, time2) > 0)
2224  result = time1;
2225  else
2226  result = time2;
2227  PG_RETURN_TIMETZADT_P(result);
2228 }
2229 
2230 Datum
2232 {
2233  TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
2234  TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
2235  TimeTzADT *result;
2236 
2237  if (timetz_cmp_internal(time1, time2) < 0)
2238  result = time1;
2239  else
2240  result = time2;
2241  PG_RETURN_TIMETZADT_P(result);
2242 }
2243 
2244 /* timetz_pl_interval()
2245  * Add interval to timetz.
2246  */
2247 Datum
2249 {
2250  TimeTzADT *time = PG_GETARG_TIMETZADT_P(0);
2251  Interval *span = PG_GETARG_INTERVAL_P(1);
2252  TimeTzADT *result;
2253 
2254  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2255 
2256  result->time = time->time + span->time;
2257  result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;
2258  if (result->time < INT64CONST(0))
2259  result->time += USECS_PER_DAY;
2260 
2261  result->zone = time->zone;
2262 
2263  PG_RETURN_TIMETZADT_P(result);
2264 }
2265 
2266 /* timetz_mi_interval()
2267  * Subtract interval from 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 /* overlaps_timetz() --- implements the SQL OVERLAPS operator.
2289  *
2290  * Algorithm is per SQL spec. This is much harder than you'd think
2291  * because the spec requires us to deliver a non-null answer in some cases
2292  * where some of the inputs are null.
2293  */
2294 Datum
2296 {
2297  /*
2298  * The arguments are TimeTzADT *, but we leave them as generic Datums for
2299  * convenience of notation --- and to avoid dereferencing nulls.
2300  */
2301  Datum ts1 = PG_GETARG_DATUM(0);
2302  Datum te1 = PG_GETARG_DATUM(1);
2303  Datum ts2 = PG_GETARG_DATUM(2);
2304  Datum te2 = PG_GETARG_DATUM(3);
2305  bool ts1IsNull = PG_ARGISNULL(0);
2306  bool te1IsNull = PG_ARGISNULL(1);
2307  bool ts2IsNull = PG_ARGISNULL(2);
2308  bool te2IsNull = PG_ARGISNULL(3);
2309 
2310 #define TIMETZ_GT(t1,t2) \
2311  DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))
2312 #define TIMETZ_LT(t1,t2) \
2313  DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))
2314 
2315  /*
2316  * If both endpoints of interval 1 are null, the result is null (unknown).
2317  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2318  * take ts1 as the lesser endpoint.
2319  */
2320  if (ts1IsNull)
2321  {
2322  if (te1IsNull)
2323  PG_RETURN_NULL();
2324  /* swap null for non-null */
2325  ts1 = te1;
2326  te1IsNull = true;
2327  }
2328  else if (!te1IsNull)
2329  {
2330  if (TIMETZ_GT(ts1, te1))
2331  {
2332  Datum tt = ts1;
2333 
2334  ts1 = te1;
2335  te1 = tt;
2336  }
2337  }
2338 
2339  /* Likewise for interval 2. */
2340  if (ts2IsNull)
2341  {
2342  if (te2IsNull)
2343  PG_RETURN_NULL();
2344  /* swap null for non-null */
2345  ts2 = te2;
2346  te2IsNull = true;
2347  }
2348  else if (!te2IsNull)
2349  {
2350  if (TIMETZ_GT(ts2, te2))
2351  {
2352  Datum tt = ts2;
2353 
2354  ts2 = te2;
2355  te2 = tt;
2356  }
2357  }
2358 
2359  /*
2360  * At this point neither ts1 nor ts2 is null, so we can consider three
2361  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2362  */
2363  if (TIMETZ_GT(ts1, ts2))
2364  {
2365  /*
2366  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2367  * in the presence of nulls it's not quite completely so.
2368  */
2369  if (te2IsNull)
2370  PG_RETURN_NULL();
2371  if (TIMETZ_LT(ts1, te2))
2372  PG_RETURN_BOOL(true);
2373  if (te1IsNull)
2374  PG_RETURN_NULL();
2375 
2376  /*
2377  * If te1 is not null then we had ts1 <= te1 above, and we just found
2378  * ts1 >= te2, hence te1 >= te2.
2379  */
2380  PG_RETURN_BOOL(false);
2381  }
2382  else if (TIMETZ_LT(ts1, ts2))
2383  {
2384  /* This case is ts2 < te1 OR te2 < te1 */
2385  if (te1IsNull)
2386  PG_RETURN_NULL();
2387  if (TIMETZ_LT(ts2, te1))
2388  PG_RETURN_BOOL(true);
2389  if (te2IsNull)
2390  PG_RETURN_NULL();
2391 
2392  /*
2393  * If te2 is not null then we had ts2 <= te2 above, and we just found
2394  * ts2 >= te1, hence te2 >= te1.
2395  */
2396  PG_RETURN_BOOL(false);
2397  }
2398  else
2399  {
2400  /*
2401  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2402  * rather silly way of saying "true if both are nonnull, else null".
2403  */
2404  if (te1IsNull || te2IsNull)
2405  PG_RETURN_NULL();
2406  PG_RETURN_BOOL(true);
2407  }
2408 
2409 #undef TIMETZ_GT
2410 #undef TIMETZ_LT
2411 }
2412 
2413 
2414 Datum
2416 {
2417  TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0);
2418  TimeADT result;
2419 
2420  /* swallow the time zone and just return the time */
2421  result = timetz->time;
2422 
2423  PG_RETURN_TIMEADT(result);
2424 }
2425 
2426 
2427 Datum
2429 {
2430  TimeADT time = PG_GETARG_TIMEADT(0);
2431  TimeTzADT *result;
2432  struct pg_tm tt,
2433  *tm = &tt;
2434  fsec_t fsec;
2435  int tz;
2436 
2437  GetCurrentDateTime(tm);
2438  time2tm(time, tm, &fsec);
2440 
2441  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2442 
2443  result->time = time;
2444  result->zone = tz;
2445 
2446  PG_RETURN_TIMETZADT_P(result);
2447 }
2448 
2449 
2450 /* timestamptz_timetz()
2451  * Convert timestamp to timetz data type.
2452  */
2453 Datum
2455 {
2457  TimeTzADT *result;
2458  struct pg_tm tt,
2459  *tm = &tt;
2460  int tz;
2461  fsec_t fsec;
2462 
2463  if (TIMESTAMP_NOT_FINITE(timestamp))
2464  PG_RETURN_NULL();
2465 
2466  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
2467  ereport(ERROR,
2468  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2469  errmsg("timestamp out of range")));
2470 
2471  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2472 
2473  tm2timetz(tm, fsec, tz, result);
2474 
2475  PG_RETURN_TIMETZADT_P(result);
2476 }
2477 
2478 
2479 /* datetimetz_timestamptz()
2480  * Convert date and timetz to timestamp with time zone data type.
2481  * Timestamp is stored in GMT, so add the time zone
2482  * stored with the timetz to the result.
2483  * - thomas 2000-03-10
2484  */
2485 Datum
2487 {
2489  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2491 
2492  if (DATE_IS_NOBEGIN(date))
2493  TIMESTAMP_NOBEGIN(result);
2494  else if (DATE_IS_NOEND(date))
2495  TIMESTAMP_NOEND(result);
2496  else
2497  {
2498  /*
2499  * Date's range is wider than timestamp's, so check for boundaries.
2500  * Since dates have the same minimum values as timestamps, only upper
2501  * boundary need be checked for overflow.
2502  */
2504  ereport(ERROR,
2505  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2506  errmsg("date out of range for timestamp")));
2507  result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;
2508 
2509  /*
2510  * Since it is possible to go beyond allowed timestamptz range because
2511  * of time zone, check for allowed timestamp range after adding tz.
2512  */
2513  if (!IS_VALID_TIMESTAMP(result))
2514  ereport(ERROR,
2515  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2516  errmsg("date out of range for timestamp")));
2517  }
2518 
2519  PG_RETURN_TIMESTAMP(result);
2520 }
2521 
2522 
2523 /* timetz_part()
2524  * Extract specified field from time type.
2525  */
2526 Datum
2528 {
2529  text *units = PG_GETARG_TEXT_PP(0);
2530  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2531  float8 result;
2532  int type,
2533  val;
2534  char *lowunits;
2535 
2536  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
2537  VARSIZE_ANY_EXHDR(units),
2538  false);
2539 
2540  type = DecodeUnits(0, lowunits, &val);
2541  if (type == UNKNOWN_FIELD)
2542  type = DecodeSpecial(0, lowunits, &val);
2543 
2544  if (type == UNITS)
2545  {
2546  double dummy;
2547  int tz;
2548  fsec_t fsec;
2549  struct pg_tm tt,
2550  *tm = &tt;
2551 
2552  timetz2tm(time, tm, &fsec, &tz);
2553 
2554  switch (val)
2555  {
2556  case DTK_TZ:
2557  result = -tz;
2558  break;
2559 
2560  case DTK_TZ_MINUTE:
2561  result = -tz;
2562  result /= SECS_PER_MINUTE;
2563  FMODULO(result, dummy, (double) SECS_PER_MINUTE);
2564  break;
2565 
2566  case DTK_TZ_HOUR:
2567  dummy = -tz;
2568  FMODULO(dummy, result, (double) SECS_PER_HOUR);
2569  break;
2570 
2571  case DTK_MICROSEC:
2572  result = tm->tm_sec * 1000000.0 + fsec;
2573  break;
2574 
2575  case DTK_MILLISEC:
2576  result = tm->tm_sec * 1000.0 + fsec / 1000.0;
2577  break;
2578 
2579  case DTK_SECOND:
2580  result = tm->tm_sec + fsec / 1000000.0;
2581  break;
2582 
2583  case DTK_MINUTE:
2584  result = tm->tm_min;
2585  break;
2586 
2587  case DTK_HOUR:
2588  result = tm->tm_hour;
2589  break;
2590 
2591  case DTK_DAY:
2592  case DTK_MONTH:
2593  case DTK_QUARTER:
2594  case DTK_YEAR:
2595  case DTK_DECADE:
2596  case DTK_CENTURY:
2597  case DTK_MILLENNIUM:
2598  default:
2599  ereport(ERROR,
2600  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2601  errmsg("\"time with time zone\" units \"%s\" not recognized",
2602  lowunits)));
2603  result = 0;
2604  }
2605  }
2606  else if (type == RESERV && val == DTK_EPOCH)
2607  {
2608  result = time->time / 1000000.0 + time->zone;
2609  }
2610  else
2611  {
2612  ereport(ERROR,
2613  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2614  errmsg("\"time with time zone\" units \"%s\" not recognized",
2615  lowunits)));
2616  result = 0;
2617  }
2618 
2619  PG_RETURN_FLOAT8(result);
2620 }
2621 
2622 /* timetz_zone()
2623  * Encode time with time zone type with specified time zone.
2624  * Applies DST rules as of the current date.
2625  */
2626 Datum
2628 {
2629  text *zone = PG_GETARG_TEXT_PP(0);
2631  TimeTzADT *result;
2632  int tz;
2633  char tzname[TZ_STRLEN_MAX + 1];
2634  char *lowzone;
2635  int type,
2636  val;
2637  pg_tz *tzp;
2638 
2639  /*
2640  * Look up the requested timezone. First we look in the timezone
2641  * abbreviation table (to handle cases like "EST"), and if that fails, we
2642  * look in the timezone database (to handle cases like
2643  * "America/New_York"). (This matches the order in which timestamp input
2644  * checks the cases; it's important because the timezone database unwisely
2645  * uses a few zone names that are identical to offset abbreviations.)
2646  */
2647  text_to_cstring_buffer(zone, tzname, sizeof(tzname));
2648 
2649  /* DecodeTimezoneAbbrev requires lowercase input */
2650  lowzone = downcase_truncate_identifier(tzname,
2651  strlen(tzname),
2652  false);
2653 
2654  type = DecodeTimezoneAbbrev(0, lowzone, &val, &tzp);
2655 
2656  if (type == TZ || type == DTZ)
2657  {
2658  /* fixed-offset abbreviation */
2659  tz = -val;
2660  }
2661  else if (type == DYNTZ)
2662  {
2663  /* dynamic-offset abbreviation, resolve using current time */
2664  pg_time_t now = (pg_time_t) time(NULL);
2665  struct pg_tm *tm;
2666 
2667  tm = pg_localtime(&now, tzp);
2668  tz = DetermineTimeZoneAbbrevOffset(tm, tzname, tzp);
2669  }
2670  else
2671  {
2672  /* try it as a full zone name */
2673  tzp = pg_tzset(tzname);
2674  if (tzp)
2675  {
2676  /* Get the offset-from-GMT that is valid today for the zone */
2677  pg_time_t now = (pg_time_t) time(NULL);
2678  struct pg_tm *tm;
2679 
2680  tm = pg_localtime(&now, tzp);
2681  tz = -tm->tm_gmtoff;
2682  }
2683  else
2684  {
2685  ereport(ERROR,
2686  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2687  errmsg("time zone \"%s\" not recognized", tzname)));
2688  tz = 0; /* keep compiler quiet */
2689  }
2690  }
2691 
2692  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2693 
2694  result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
2695  while (result->time < INT64CONST(0))
2696  result->time += USECS_PER_DAY;
2697  while (result->time >= USECS_PER_DAY)
2698  result->time -= USECS_PER_DAY;
2699 
2700  result->zone = tz;
2701 
2702  PG_RETURN_TIMETZADT_P(result);
2703 }
2704 
2705 /* timetz_izone()
2706  * Encode time with time zone type with specified time interval as time zone.
2707  */
2708 Datum
2710 {
2712  TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
2713  TimeTzADT *result;
2714  int tz;
2715 
2716  if (zone->month != 0 || zone->day != 0)
2717  ereport(ERROR,
2718  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2719  errmsg("interval time zone \"%s\" must not include months or days",
2721  PointerGetDatum(zone))))));
2722 
2723  tz = -(zone->time / USECS_PER_SEC);
2724 
2725  result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
2726 
2727  result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
2728  while (result->time < INT64CONST(0))
2729  result->time += USECS_PER_DAY;
2730  while (result->time >= USECS_PER_DAY)
2731  result->time -= USECS_PER_DAY;
2732 
2733  result->zone = tz;
2734 
2735  PG_RETURN_TIMETZADT_P(result);
2736 }
#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:2192
#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:1827
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:2248
#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:2183
#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:1809
#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:1846
int64 pg_time_t
Definition: pgtime.h:23
TimeADT time
Definition: date.h:28
Datum timetz_scale(PG_FUNCTION_ARGS)
Definition: date.c:2093
#define PG_RETURN_INTERVAL_P(x)
Definition: timestamp.h:41
int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
Definition: timestamp.c:2022
#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:2147
#define DTK_YEAR
Definition: datetime.h:170
Datum datetime_timestamp(PG_FUNCTION_ARGS)
Definition: date.c:1719
#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:62
Datum timetz_gt(PG_FUNCTION_ARGS)
Definition: date.c:2174
int64 timestamp
Datum timestamptz_ne_date(PG_FUNCTION_ARGS)
Definition: date.c:945
int64 TimestampTz
Definition: timestamp.h:39
#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:359
Datum timestamp_date(PG_FUNCTION_ARGS)
Definition: date.c:1075
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:1077
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:1757
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:46
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
#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:2071
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:1742
Definition: nodes.h:506
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
#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:2156
double date2timestamp_no_overflow(DateADT dateVal)
Definition: date.c:658
#define TZ
Definition: datetime.h:96
return result
Definition: formatting.c:1618
#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:957
Datum timetz_mi_interval(PG_FUNCTION_ARGS)
Definition: date.c:2270
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:584
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:329
long int tm_gmtoff
Definition: pgtime.h:36
static int timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
Definition: date.c:2111
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 DTK_CURRENT
Definition: datetime.h:152
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
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:256
Datum datetimetz_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:2486
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:103
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:218
#define DTK_MONTH
Definition: datetime.h:168
#define DTK_MILLISEC
Definition: datetime.h:174
Datum timestamp_mi_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2825
Datum time_larger(PG_FUNCTION_ARGS)
Definition: date.c:1512
#define IS_VALID_DATE(d)
Definition: timestamp.h:190
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
Datum timestamp_pl_interval(PG_FUNCTION_ARGS)
Definition: timestamp.c:2746
#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:381
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:2051
TimeTzADT * GetSQLCurrentTime(int32 typmod)
Definition: date.c:336
Datum timetz_send(PG_FUNCTION_ARGS)
Definition: date.c:2039
Datum time_gt(PG_FUNCTION_ARGS)
Definition: date.c:1475
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:65
#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:2059
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:268
#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:2165
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:708
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:2627
int64 TimeOffset
Definition: timestamp.h:40
Datum hash_uint32(uint32 k)
Definition: hashfunc.c:512
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
Datum timestamptz_ge_date(PG_FUNCTION_ARGS)
Definition: date.c:993
Datum timetz_time(PG_FUNCTION_ARGS)
Definition: date.c:2415
Datum timetz_smaller(PG_FUNCTION_ARGS)
Definition: date.c:2231
Datum timestamptz_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:957
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define NULL
Definition: c.h:229
Datum timestamp_cmp_date(PG_FUNCTION_ARGS)
Definition: date.c:921
Datum timetz_recv(PG_FUNCTION_ARGS)
Definition: date.c:2003
Node * TemporalTransform(int32 max_precis, Node *node)
Definition: datetime.c:4486
#define INT64CONST(x)
Definition: c.h:310
#define PG_GETARG_TIMEADT(n)
Definition: date.h:61
Datum interval_time(PG_FUNCTION_ARGS)
Definition: date.c:1765
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
Datum timetz_eq(PG_FUNCTION_ARGS)
Definition: date.c:2138
#define DTK_EARLY
Definition: datetime.h:153
Datum timetz_hash(PG_FUNCTION_ARGS)
Definition: date.c:2201
#define MAXDATEFIELDS
Definition: datetime.h:205
Datum overlaps_time(PG_FUNCTION_ARGS)
Definition: date.c:1536
#define DTK_DAY
Definition: datetime.h:166
Datum make_date(PG_FUNCTION_ARGS)
Definition: date.c:250
int DateStyle
Definition: globals.c:106
#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:1254
Datum time_smaller(PG_FUNCTION_ARGS)
Definition: date.c:1521
Datum date_ge_timestamptz(PG_FUNCTION_ARGS)
Definition: date.c:825
Datum timestamptz_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2454
Datum time_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2428
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:2527
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:39
Definition: zic.c:90
static int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result)
Definition: date.c:1937
Datum timetz_in(PG_FUNCTION_ARGS)
Definition: date.c:1947
int tm_year
Definition: pgtime.h:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
#define TIMEADT_GT(t1, t2)
Datum time_mi_time(PG_FUNCTION_ARGS)
Definition: date.c:1790
#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:486
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:1658
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:1983
Datum timestamp_lt_date(PG_FUNCTION_ARGS)
Definition: date.c:873
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
Definition: c.h:439
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
pg_tz * session_timezone
Definition: pgtz.c:27
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:448
#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
void pq_sendint64(StringInfo buf, int64 i)
Definition: pqformat.c:271
#define EARLY
Definition: datetime.h:40
int tm_min
Definition: pgtime.h:28
Datum overlaps_timetz(PG_FUNCTION_ARGS)
Definition: date.c:2295
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:2217
long val
Definition: informix.c:689
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1533
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:586
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define DTK_DATE
Definition: datetime.h:145
Datum timetz_out(PG_FUNCTION_ARGS)
Definition: date.c:1982
#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:1688
#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:2709
Datum date_pli(PG_FUNCTION_ARGS)
Definition: date.c:523