PostgreSQL Source Code  git master
timestamp.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * timestamp.c
4  * Functions for the built-in SQL types "timestamp" and "interval".
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/timestamp.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include <ctype.h>
19 #include <math.h>
20 #include <limits.h>
21 #include <sys/time.h>
22 
23 #include "access/xact.h"
24 #include "catalog/pg_type.h"
25 #include "common/int.h"
26 #include "common/int128.h"
27 #include "funcapi.h"
28 #include "libpq/pqformat.h"
29 #include "miscadmin.h"
30 #include "nodes/nodeFuncs.h"
31 #include "nodes/supportnodes.h"
32 #include "parser/scansup.h"
33 #include "utils/array.h"
34 #include "utils/builtins.h"
35 #include "utils/date.h"
36 #include "utils/datetime.h"
37 #include "utils/float.h"
38 #include "utils/numeric.h"
39 #include "utils/sortsupport.h"
40 
41 /*
42  * gcc's -ffast-math switch breaks routines that expect exact results from
43  * expressions like timeval / SECS_PER_HOUR, where timeval is double.
44  */
45 #ifdef __FAST_MATH__
46 #error -ffast-math is known to break this code
47 #endif
48 
49 #define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
50 
51 /* Set at postmaster start */
53 
54 /* Set at configuration reload */
56 
57 typedef struct
58 {
62  int step_sign;
64 
65 typedef struct
66 {
70  int step_sign;
73 
74 /*
75  * The transition datatype for interval aggregates is declared as internal.
76  * It's a pointer to an IntervalAggState allocated in the aggregate context.
77  */
78 typedef struct IntervalAggState
79 {
80  int64 N; /* count of finite intervals processed */
81  Interval sumX; /* sum of finite intervals processed */
82  /* These counts are *not* included in N! Use IA_TOTAL_COUNT() as needed */
83  int64 pInfcount; /* count of +infinity intervals */
84  int64 nInfcount; /* count of -infinity intervals */
86 
87 #define IA_TOTAL_COUNT(ia) \
88  ((ia)->N + (ia)->pInfcount + (ia)->nInfcount)
89 
90 static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
91 static Timestamp dt2local(Timestamp dt, int timezone);
92 static bool AdjustIntervalForTypmod(Interval *interval, int32 typmod,
93  Node *escontext);
96 
97 static void EncodeSpecialInterval(const Interval *interval, char *str);
98 static void interval_um_internal(const Interval *interval, Interval *result);
99 
100 /* common code for timestamptypmodin and timestamptztypmodin */
101 static int32
103 {
104  int32 *tl;
105  int n;
106 
107  tl = ArrayGetIntegerTypmods(ta, &n);
108 
109  /*
110  * we're not too tense about good error message here because grammar
111  * shouldn't allow wrong number of modifiers for TIMESTAMP
112  */
113  if (n != 1)
114  ereport(ERROR,
115  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
116  errmsg("invalid type modifier")));
117 
118  return anytimestamp_typmod_check(istz, tl[0]);
119 }
120 
121 /* exported so parse_expr.c can use it */
122 int32
124 {
125  if (typmod < 0)
126  ereport(ERROR,
127  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
128  errmsg("TIMESTAMP(%d)%s precision must not be negative",
129  typmod, (istz ? " WITH TIME ZONE" : ""))));
130  if (typmod > MAX_TIMESTAMP_PRECISION)
131  {
133  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
134  errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
135  typmod, (istz ? " WITH TIME ZONE" : ""),
137  typmod = MAX_TIMESTAMP_PRECISION;
138  }
139 
140  return typmod;
141 }
142 
143 /* common code for timestamptypmodout and timestamptztypmodout */
144 static char *
145 anytimestamp_typmodout(bool istz, int32 typmod)
146 {
147  const char *tz = istz ? " with time zone" : " without time zone";
148 
149  if (typmod >= 0)
150  return psprintf("(%d)%s", (int) typmod, tz);
151  else
152  return pstrdup(tz);
153 }
154 
155 
156 /*****************************************************************************
157  * USER I/O ROUTINES *
158  *****************************************************************************/
159 
160 /* timestamp_in()
161  * Convert a string to internal form.
162  */
163 Datum
165 {
166  char *str = PG_GETARG_CSTRING(0);
167 #ifdef NOT_USED
168  Oid typelem = PG_GETARG_OID(1);
169 #endif
170  int32 typmod = PG_GETARG_INT32(2);
171  Node *escontext = fcinfo->context;
172  Timestamp result;
173  fsec_t fsec;
174  struct pg_tm tt,
175  *tm = &tt;
176  int tz;
177  int dtype;
178  int nf;
179  int dterr;
180  char *field[MAXDATEFIELDS];
181  int ftype[MAXDATEFIELDS];
182  char workbuf[MAXDATELEN + MAXDATEFIELDS];
183  DateTimeErrorExtra extra;
184 
185  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
186  field, ftype, MAXDATEFIELDS, &nf);
187  if (dterr == 0)
188  dterr = DecodeDateTime(field, ftype, nf,
189  &dtype, tm, &fsec, &tz, &extra);
190  if (dterr != 0)
191  {
192  DateTimeParseError(dterr, &extra, str, "timestamp", escontext);
193  PG_RETURN_NULL();
194  }
195 
196  switch (dtype)
197  {
198  case DTK_DATE:
199  if (tm2timestamp(tm, fsec, NULL, &result) != 0)
200  ereturn(escontext, (Datum) 0,
201  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
202  errmsg("timestamp out of range: \"%s\"", str)));
203  break;
204 
205  case DTK_EPOCH:
206  result = SetEpochTimestamp();
207  break;
208 
209  case DTK_LATE:
210  TIMESTAMP_NOEND(result);
211  break;
212 
213  case DTK_EARLY:
214  TIMESTAMP_NOBEGIN(result);
215  break;
216 
217  default:
218  elog(ERROR, "unexpected dtype %d while parsing timestamp \"%s\"",
219  dtype, str);
220  TIMESTAMP_NOEND(result);
221  }
222 
223  AdjustTimestampForTypmod(&result, typmod, escontext);
224 
225  PG_RETURN_TIMESTAMP(result);
226 }
227 
228 /* timestamp_out()
229  * Convert a timestamp to external form.
230  */
231 Datum
233 {
235  char *result;
236  struct pg_tm tt,
237  *tm = &tt;
238  fsec_t fsec;
239  char buf[MAXDATELEN + 1];
240 
243  else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
244  EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf);
245  else
246  ereport(ERROR,
247  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
248  errmsg("timestamp out of range")));
249 
250  result = pstrdup(buf);
251  PG_RETURN_CSTRING(result);
252 }
253 
254 /*
255  * timestamp_recv - converts external binary format to timestamp
256  */
257 Datum
259 {
261 
262 #ifdef NOT_USED
263  Oid typelem = PG_GETARG_OID(1);
264 #endif
265  int32 typmod = PG_GETARG_INT32(2);
267  struct pg_tm tt,
268  *tm = &tt;
269  fsec_t fsec;
270 
272 
273  /* range check: see if timestamp_out would like it */
275  /* ok */ ;
276  else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0 ||
278  ereport(ERROR,
279  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
280  errmsg("timestamp out of range")));
281 
282  AdjustTimestampForTypmod(&timestamp, typmod, NULL);
283 
285 }
286 
287 /*
288  * timestamp_send - converts timestamp to binary format
289  */
290 Datum
292 {
295 
299 }
300 
301 Datum
303 {
305 
307 }
308 
309 Datum
311 {
312  int32 typmod = PG_GETARG_INT32(0);
313 
315 }
316 
317 
318 /*
319  * timestamp_support()
320  *
321  * Planner support function for the timestamp_scale() and timestamptz_scale()
322  * length coercion functions (we need not distinguish them here).
323  */
324 Datum
326 {
327  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
328  Node *ret = NULL;
329 
330  if (IsA(rawreq, SupportRequestSimplify))
331  {
333 
335  }
336 
337  PG_RETURN_POINTER(ret);
338 }
339 
340 /* timestamp_scale()
341  * Adjust time type for specified scale factor.
342  * Used by PostgreSQL type system to stuff columns.
343  */
344 Datum
346 {
348  int32 typmod = PG_GETARG_INT32(1);
349  Timestamp result;
350 
351  result = timestamp;
352 
353  AdjustTimestampForTypmod(&result, typmod, NULL);
354 
355  PG_RETURN_TIMESTAMP(result);
356 }
357 
358 /*
359  * AdjustTimestampForTypmod --- round off a timestamp to suit given typmod
360  * Works for either timestamp or timestamptz.
361  *
362  * Returns true on success, false on failure (if escontext points to an
363  * ErrorSaveContext; otherwise errors are thrown).
364  */
365 bool
366 AdjustTimestampForTypmod(Timestamp *time, int32 typmod, Node *escontext)
367 {
368  static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
369  INT64CONST(1000000),
370  INT64CONST(100000),
371  INT64CONST(10000),
372  INT64CONST(1000),
373  INT64CONST(100),
374  INT64CONST(10),
375  INT64CONST(1)
376  };
377 
378  static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
379  INT64CONST(500000),
380  INT64CONST(50000),
381  INT64CONST(5000),
382  INT64CONST(500),
383  INT64CONST(50),
384  INT64CONST(5),
385  INT64CONST(0)
386  };
387 
388  if (!TIMESTAMP_NOT_FINITE(*time)
389  && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
390  {
391  if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
392  ereturn(escontext, false,
393  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
394  errmsg("timestamp(%d) precision must be between %d and %d",
395  typmod, 0, MAX_TIMESTAMP_PRECISION)));
396 
397  if (*time >= INT64CONST(0))
398  {
399  *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
400  TimestampScales[typmod];
401  }
402  else
403  {
404  *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
405  * TimestampScales[typmod]);
406  }
407  }
408 
409  return true;
410 }
411 
412 /* timestamptz_in()
413  * Convert a string to internal form.
414  */
415 Datum
417 {
418  char *str = PG_GETARG_CSTRING(0);
419 #ifdef NOT_USED
420  Oid typelem = PG_GETARG_OID(1);
421 #endif
422  int32 typmod = PG_GETARG_INT32(2);
423  Node *escontext = fcinfo->context;
424  TimestampTz result;
425  fsec_t fsec;
426  struct pg_tm tt,
427  *tm = &tt;
428  int tz;
429  int dtype;
430  int nf;
431  int dterr;
432  char *field[MAXDATEFIELDS];
433  int ftype[MAXDATEFIELDS];
434  char workbuf[MAXDATELEN + MAXDATEFIELDS];
435  DateTimeErrorExtra extra;
436 
437  dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
438  field, ftype, MAXDATEFIELDS, &nf);
439  if (dterr == 0)
440  dterr = DecodeDateTime(field, ftype, nf,
441  &dtype, tm, &fsec, &tz, &extra);
442  if (dterr != 0)
443  {
444  DateTimeParseError(dterr, &extra, str, "timestamp with time zone",
445  escontext);
446  PG_RETURN_NULL();
447  }
448 
449  switch (dtype)
450  {
451  case DTK_DATE:
452  if (tm2timestamp(tm, fsec, &tz, &result) != 0)
453  ereturn(escontext, (Datum) 0,
454  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
455  errmsg("timestamp out of range: \"%s\"", str)));
456  break;
457 
458  case DTK_EPOCH:
459  result = SetEpochTimestamp();
460  break;
461 
462  case DTK_LATE:
463  TIMESTAMP_NOEND(result);
464  break;
465 
466  case DTK_EARLY:
467  TIMESTAMP_NOBEGIN(result);
468  break;
469 
470  default:
471  elog(ERROR, "unexpected dtype %d while parsing timestamptz \"%s\"",
472  dtype, str);
473  TIMESTAMP_NOEND(result);
474  }
475 
476  AdjustTimestampForTypmod(&result, typmod, escontext);
477 
478  PG_RETURN_TIMESTAMPTZ(result);
479 }
480 
481 /*
482  * Try to parse a timezone specification, and return its timezone offset value
483  * if it's acceptable. Otherwise, an error is thrown.
484  *
485  * Note: some code paths update tm->tm_isdst, and some don't; current callers
486  * don't care, so we don't bother being consistent.
487  */
488 static int
490 {
491  char tzname[TZ_STRLEN_MAX + 1];
492  int dterr;
493  int tz;
494 
495  text_to_cstring_buffer(zone, tzname, sizeof(tzname));
496 
497  /*
498  * Look up the requested timezone. First we try to interpret it as a
499  * numeric timezone specification; if DecodeTimezone decides it doesn't
500  * like the format, we try timezone abbreviations and names.
501  *
502  * Note pg_tzset happily parses numeric input that DecodeTimezone would
503  * reject. To avoid having it accept input that would otherwise be seen
504  * as invalid, it's enough to disallow having a digit in the first
505  * position of our input string.
506  */
507  if (isdigit((unsigned char) *tzname))
508  ereport(ERROR,
509  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
510  errmsg("invalid input syntax for type %s: \"%s\"",
511  "numeric time zone", tzname),
512  errhint("Numeric time zones must have \"-\" or \"+\" as first character.")));
513 
514  dterr = DecodeTimezone(tzname, &tz);
515  if (dterr != 0)
516  {
517  int type,
518  val;
519  pg_tz *tzp;
520 
521  if (dterr == DTERR_TZDISP_OVERFLOW)
522  ereport(ERROR,
523  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
524  errmsg("numeric time zone \"%s\" out of range", tzname)));
525  else if (dterr != DTERR_BAD_FORMAT)
526  ereport(ERROR,
527  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
528  errmsg("time zone \"%s\" not recognized", tzname)));
529 
530  type = DecodeTimezoneName(tzname, &val, &tzp);
531 
532  if (type == TZNAME_FIXED_OFFSET)
533  {
534  /* fixed-offset abbreviation */
535  tz = -val;
536  }
537  else if (type == TZNAME_DYNTZ)
538  {
539  /* dynamic-offset abbreviation, resolve using specified time */
540  tz = DetermineTimeZoneAbbrevOffset(tm, tzname, tzp);
541  }
542  else
543  {
544  /* full zone name */
545  tz = DetermineTimeZoneOffset(tm, tzp);
546  }
547  }
548 
549  return tz;
550 }
551 
552 /*
553  * Look up the requested timezone, returning a pg_tz struct.
554  *
555  * This is the same as DecodeTimezoneNameToTz, but starting with a text Datum.
556  */
557 static pg_tz *
559 {
560  char tzname[TZ_STRLEN_MAX + 1];
561 
562  text_to_cstring_buffer(zone, tzname, sizeof(tzname));
563 
564  return DecodeTimezoneNameToTz(tzname);
565 }
566 
567 /*
568  * make_timestamp_internal
569  * workhorse for make_timestamp and make_timestamptz
570  */
571 static Timestamp
572 make_timestamp_internal(int year, int month, int day,
573  int hour, int min, double sec)
574 {
575  struct pg_tm tm;
577  TimeOffset time;
578  int dterr;
579  bool bc = false;
580  Timestamp result;
581 
582  tm.tm_year = year;
583  tm.tm_mon = month;
584  tm.tm_mday = day;
585 
586  /* Handle negative years as BC */
587  if (tm.tm_year < 0)
588  {
589  bc = true;
590  tm.tm_year = -tm.tm_year;
591  }
592 
593  dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm);
594 
595  if (dterr != 0)
596  ereport(ERROR,
597  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
598  errmsg("date field value out of range: %d-%02d-%02d",
599  year, month, day)));
600 
602  ereport(ERROR,
603  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
604  errmsg("date out of range: %d-%02d-%02d",
605  year, month, day)));
606 
608 
609  /* Check for time overflow */
610  if (float_time_overflows(hour, min, sec))
611  ereport(ERROR,
612  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
613  errmsg("time field value out of range: %d:%02d:%02g",
614  hour, min, sec)));
615 
616  /* This should match tm2time */
617  time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
618  * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
619 
620  result = date * USECS_PER_DAY + time;
621  /* check for major overflow */
622  if ((result - time) / USECS_PER_DAY != date)
623  ereport(ERROR,
624  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
625  errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
626  year, month, day,
627  hour, min, sec)));
628 
629  /* check for just-barely overflow (okay except time-of-day wraps) */
630  /* caution: we want to allow 1999-12-31 24:00:00 */
631  if ((result < 0 && date > 0) ||
632  (result > 0 && date < -1))
633  ereport(ERROR,
634  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
635  errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
636  year, month, day,
637  hour, min, sec)));
638 
639  /* final range check catches just-out-of-range timestamps */
640  if (!IS_VALID_TIMESTAMP(result))
641  ereport(ERROR,
642  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
643  errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
644  year, month, day,
645  hour, min, sec)));
646 
647  return result;
648 }
649 
650 /*
651  * make_timestamp() - timestamp constructor
652  */
653 Datum
655 {
656  int32 year = PG_GETARG_INT32(0);
657  int32 month = PG_GETARG_INT32(1);
658  int32 mday = PG_GETARG_INT32(2);
659  int32 hour = PG_GETARG_INT32(3);
660  int32 min = PG_GETARG_INT32(4);
661  float8 sec = PG_GETARG_FLOAT8(5);
662  Timestamp result;
663 
664  result = make_timestamp_internal(year, month, mday,
665  hour, min, sec);
666 
667  PG_RETURN_TIMESTAMP(result);
668 }
669 
670 /*
671  * make_timestamptz() - timestamp with time zone constructor
672  */
673 Datum
675 {
676  int32 year = PG_GETARG_INT32(0);
677  int32 month = PG_GETARG_INT32(1);
678  int32 mday = PG_GETARG_INT32(2);
679  int32 hour = PG_GETARG_INT32(3);
680  int32 min = PG_GETARG_INT32(4);
681  float8 sec = PG_GETARG_FLOAT8(5);
682  Timestamp result;
683 
684  result = make_timestamp_internal(year, month, mday,
685  hour, min, sec);
686 
688 }
689 
690 /*
691  * Construct a timestamp with time zone.
692  * As above, but the time zone is specified as seventh argument.
693  */
694 Datum
696 {
697  int32 year = PG_GETARG_INT32(0);
698  int32 month = PG_GETARG_INT32(1);
699  int32 mday = PG_GETARG_INT32(2);
700  int32 hour = PG_GETARG_INT32(3);
701  int32 min = PG_GETARG_INT32(4);
702  float8 sec = PG_GETARG_FLOAT8(5);
704  TimestampTz result;
706  struct pg_tm tt;
707  int tz;
708  fsec_t fsec;
709 
710  timestamp = make_timestamp_internal(year, month, mday,
711  hour, min, sec);
712 
713  if (timestamp2tm(timestamp, NULL, &tt, &fsec, NULL, NULL) != 0)
714  ereport(ERROR,
715  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
716  errmsg("timestamp out of range")));
717 
718  tz = parse_sane_timezone(&tt, zone);
719 
720  result = dt2local(timestamp, -tz);
721 
722  if (!IS_VALID_TIMESTAMP(result))
723  ereport(ERROR,
724  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
725  errmsg("timestamp out of range")));
726 
727  PG_RETURN_TIMESTAMPTZ(result);
728 }
729 
730 /*
731  * to_timestamp(double precision)
732  * Convert UNIX epoch to timestamptz.
733  */
734 Datum
736 {
737  float8 seconds = PG_GETARG_FLOAT8(0);
738  TimestampTz result;
739 
740  /* Deal with NaN and infinite inputs ... */
741  if (isnan(seconds))
742  ereport(ERROR,
743  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
744  errmsg("timestamp cannot be NaN")));
745 
746  if (isinf(seconds))
747  {
748  if (seconds < 0)
749  TIMESTAMP_NOBEGIN(result);
750  else
751  TIMESTAMP_NOEND(result);
752  }
753  else
754  {
755  /* Out of range? */
756  if (seconds <
758  || seconds >=
760  ereport(ERROR,
761  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
762  errmsg("timestamp out of range: \"%g\"", seconds)));
763 
764  /* Convert UNIX epoch to Postgres epoch */
766 
767  seconds = rint(seconds * USECS_PER_SEC);
768  result = (int64) seconds;
769 
770  /* Recheck in case roundoff produces something just out of range */
771  if (!IS_VALID_TIMESTAMP(result))
772  ereport(ERROR,
773  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
774  errmsg("timestamp out of range: \"%g\"",
775  PG_GETARG_FLOAT8(0))));
776  }
777 
778  PG_RETURN_TIMESTAMP(result);
779 }
780 
781 /* timestamptz_out()
782  * Convert a timestamp to external form.
783  */
784 Datum
786 {
788  char *result;
789  int tz;
790  struct pg_tm tt,
791  *tm = &tt;
792  fsec_t fsec;
793  const char *tzn;
794  char buf[MAXDATELEN + 1];
795 
796  if (TIMESTAMP_NOT_FINITE(dt))
798  else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
799  EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
800  else
801  ereport(ERROR,
802  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
803  errmsg("timestamp out of range")));
804 
805  result = pstrdup(buf);
806  PG_RETURN_CSTRING(result);
807 }
808 
809 /*
810  * timestamptz_recv - converts external binary format to timestamptz
811  */
812 Datum
814 {
816 
817 #ifdef NOT_USED
818  Oid typelem = PG_GETARG_OID(1);
819 #endif
820  int32 typmod = PG_GETARG_INT32(2);
822  int tz;
823  struct pg_tm tt,
824  *tm = &tt;
825  fsec_t fsec;
826 
828 
829  /* range check: see if timestamptz_out would like it */
831  /* ok */ ;
832  else if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0 ||
834  ereport(ERROR,
835  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
836  errmsg("timestamp out of range")));
837 
838  AdjustTimestampForTypmod(&timestamp, typmod, NULL);
839 
841 }
842 
843 /*
844  * timestamptz_send - converts timestamptz to binary format
845  */
846 Datum
848 {
851 
855 }
856 
857 Datum
859 {
861 
863 }
864 
865 Datum
867 {
868  int32 typmod = PG_GETARG_INT32(0);
869 
871 }
872 
873 
874 /* timestamptz_scale()
875  * Adjust time type for specified scale factor.
876  * Used by PostgreSQL type system to stuff columns.
877  */
878 Datum
880 {
882  int32 typmod = PG_GETARG_INT32(1);
883  TimestampTz result;
884 
885  result = timestamp;
886 
887  AdjustTimestampForTypmod(&result, typmod, NULL);
888 
889  PG_RETURN_TIMESTAMPTZ(result);
890 }
891 
892 
893 /* interval_in()
894  * Convert a string to internal form.
895  *
896  * External format(s):
897  * Uses the generic date/time parsing and decoding routines.
898  */
899 Datum
901 {
902  char *str = PG_GETARG_CSTRING(0);
903 #ifdef NOT_USED
904  Oid typelem = PG_GETARG_OID(1);
905 #endif
906  int32 typmod = PG_GETARG_INT32(2);
907  Node *escontext = fcinfo->context;
908  Interval *result;
909  struct pg_itm_in tt,
910  *itm_in = &tt;
911  int dtype;
912  int nf;
913  int range;
914  int dterr;
915  char *field[MAXDATEFIELDS];
916  int ftype[MAXDATEFIELDS];
917  char workbuf[256];
918  DateTimeErrorExtra extra;
919 
920  itm_in->tm_year = 0;
921  itm_in->tm_mon = 0;
922  itm_in->tm_mday = 0;
923  itm_in->tm_usec = 0;
924 
925  if (typmod >= 0)
926  range = INTERVAL_RANGE(typmod);
927  else
929 
930  dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field,
931  ftype, MAXDATEFIELDS, &nf);
932  if (dterr == 0)
933  dterr = DecodeInterval(field, ftype, nf, range,
934  &dtype, itm_in);
935 
936  /* if those functions think it's a bad format, try ISO8601 style */
937  if (dterr == DTERR_BAD_FORMAT)
938  dterr = DecodeISO8601Interval(str,
939  &dtype, itm_in);
940 
941  if (dterr != 0)
942  {
943  if (dterr == DTERR_FIELD_OVERFLOW)
944  dterr = DTERR_INTERVAL_OVERFLOW;
945  DateTimeParseError(dterr, &extra, str, "interval", escontext);
946  PG_RETURN_NULL();
947  }
948 
949  result = (Interval *) palloc(sizeof(Interval));
950 
951  switch (dtype)
952  {
953  case DTK_DELTA:
954  if (itmin2interval(itm_in, result) != 0)
955  ereturn(escontext, (Datum) 0,
956  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
957  errmsg("interval out of range")));
958  break;
959 
960  case DTK_LATE:
961  INTERVAL_NOEND(result);
962  break;
963 
964  case DTK_EARLY:
965  INTERVAL_NOBEGIN(result);
966  break;
967 
968  default:
969  elog(ERROR, "unexpected dtype %d while parsing interval \"%s\"",
970  dtype, str);
971  }
972 
973  AdjustIntervalForTypmod(result, typmod, escontext);
974 
975  PG_RETURN_INTERVAL_P(result);
976 }
977 
978 /* interval_out()
979  * Convert a time span to external form.
980  */
981 Datum
983 {
984  Interval *span = PG_GETARG_INTERVAL_P(0);
985  char *result;
986  struct pg_itm tt,
987  *itm = &tt;
988  char buf[MAXDATELEN + 1];
989 
990  if (INTERVAL_NOT_FINITE(span))
991  EncodeSpecialInterval(span, buf);
992  else
993  {
994  interval2itm(*span, itm);
996  }
997 
998  result = pstrdup(buf);
999  PG_RETURN_CSTRING(result);
1000 }
1001 
1002 /*
1003  * interval_recv - converts external binary format to interval
1004  */
1005 Datum
1007 {
1009 
1010 #ifdef NOT_USED
1011  Oid typelem = PG_GETARG_OID(1);
1012 #endif
1013  int32 typmod = PG_GETARG_INT32(2);
1014  Interval *interval;
1015 
1016  interval = (Interval *) palloc(sizeof(Interval));
1017 
1019  interval->day = pq_getmsgint(buf, sizeof(interval->day));
1020  interval->month = pq_getmsgint(buf, sizeof(interval->month));
1021 
1022  AdjustIntervalForTypmod(interval, typmod, NULL);
1023 
1025 }
1026 
1027 /*
1028  * interval_send - converts interval to binary format
1029  */
1030 Datum
1032 {
1035 
1036  pq_begintypsend(&buf);
1038  pq_sendint32(&buf, interval->day);
1041 }
1042 
1043 /*
1044  * The interval typmod stores a "range" in its high 16 bits and a "precision"
1045  * in its low 16 bits. Both contribute to defining the resolution of the
1046  * type. Range addresses resolution granules larger than one second, and
1047  * precision specifies resolution below one second. This representation can
1048  * express all SQL standard resolutions, but we implement them all in terms of
1049  * truncating rightward from some position. Range is a bitmap of permitted
1050  * fields, but only the temporally-smallest such field is significant to our
1051  * calculations. Precision is a count of sub-second decimal places to retain.
1052  * Setting all bits (INTERVAL_FULL_PRECISION) gives the same truncation
1053  * semantics as choosing MAX_INTERVAL_PRECISION.
1054  */
1055 Datum
1057 {
1059  int32 *tl;
1060  int n;
1061  int32 typmod;
1062 
1063  tl = ArrayGetIntegerTypmods(ta, &n);
1064 
1065  /*
1066  * tl[0] - interval range (fields bitmask) tl[1] - precision (optional)
1067  *
1068  * Note we must validate tl[0] even though it's normally guaranteed
1069  * correct by the grammar --- consider SELECT 'foo'::"interval"(1000).
1070  */
1071  if (n > 0)
1072  {
1073  switch (tl[0])
1074  {
1075  case INTERVAL_MASK(YEAR):
1076  case INTERVAL_MASK(MONTH):
1077  case INTERVAL_MASK(DAY):
1078  case INTERVAL_MASK(HOUR):
1079  case INTERVAL_MASK(MINUTE):
1080  case INTERVAL_MASK(SECOND):
1088  case INTERVAL_FULL_RANGE:
1089  /* all OK */
1090  break;
1091  default:
1092  ereport(ERROR,
1093  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1094  errmsg("invalid INTERVAL type modifier")));
1095  }
1096  }
1097 
1098  if (n == 1)
1099  {
1100  if (tl[0] != INTERVAL_FULL_RANGE)
1101  typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, tl[0]);
1102  else
1103  typmod = -1;
1104  }
1105  else if (n == 2)
1106  {
1107  if (tl[1] < 0)
1108  ereport(ERROR,
1109  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1110  errmsg("INTERVAL(%d) precision must not be negative",
1111  tl[1])));
1112  if (tl[1] > MAX_INTERVAL_PRECISION)
1113  {
1114  ereport(WARNING,
1115  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1116  errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
1117  tl[1], MAX_INTERVAL_PRECISION)));
1118  typmod = INTERVAL_TYPMOD(MAX_INTERVAL_PRECISION, tl[0]);
1119  }
1120  else
1121  typmod = INTERVAL_TYPMOD(tl[1], tl[0]);
1122  }
1123  else
1124  {
1125  ereport(ERROR,
1126  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1127  errmsg("invalid INTERVAL type modifier")));
1128  typmod = 0; /* keep compiler quiet */
1129  }
1130 
1131  PG_RETURN_INT32(typmod);
1132 }
1133 
1134 Datum
1136 {
1137  int32 typmod = PG_GETARG_INT32(0);
1138  char *res = (char *) palloc(64);
1139  int fields;
1140  int precision;
1141  const char *fieldstr;
1142 
1143  if (typmod < 0)
1144  {
1145  *res = '\0';
1147  }
1148 
1149  fields = INTERVAL_RANGE(typmod);
1150  precision = INTERVAL_PRECISION(typmod);
1151 
1152  switch (fields)
1153  {
1154  case INTERVAL_MASK(YEAR):
1155  fieldstr = " year";
1156  break;
1157  case INTERVAL_MASK(MONTH):
1158  fieldstr = " month";
1159  break;
1160  case INTERVAL_MASK(DAY):
1161  fieldstr = " day";
1162  break;
1163  case INTERVAL_MASK(HOUR):
1164  fieldstr = " hour";
1165  break;
1166  case INTERVAL_MASK(MINUTE):
1167  fieldstr = " minute";
1168  break;
1169  case INTERVAL_MASK(SECOND):
1170  fieldstr = " second";
1171  break;
1173  fieldstr = " year to month";
1174  break;
1176  fieldstr = " day to hour";
1177  break;
1179  fieldstr = " day to minute";
1180  break;
1182  fieldstr = " day to second";
1183  break;
1185  fieldstr = " hour to minute";
1186  break;
1188  fieldstr = " hour to second";
1189  break;
1191  fieldstr = " minute to second";
1192  break;
1193  case INTERVAL_FULL_RANGE:
1194  fieldstr = "";
1195  break;
1196  default:
1197  elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
1198  fieldstr = "";
1199  break;
1200  }
1201 
1202  if (precision != INTERVAL_FULL_PRECISION)
1203  snprintf(res, 64, "%s(%d)", fieldstr, precision);
1204  else
1205  snprintf(res, 64, "%s", fieldstr);
1206 
1208 }
1209 
1210 /*
1211  * Given an interval typmod value, return a code for the least-significant
1212  * field that the typmod allows to be nonzero, for instance given
1213  * INTERVAL DAY TO HOUR we want to identify "hour".
1214  *
1215  * The results should be ordered by field significance, which means
1216  * we can't use the dt.h macros YEAR etc, because for some odd reason
1217  * they aren't ordered that way. Instead, arbitrarily represent
1218  * SECOND = 0, MINUTE = 1, HOUR = 2, DAY = 3, MONTH = 4, YEAR = 5.
1219  */
1220 static int
1222 {
1223  if (typmod < 0)
1224  return 0; /* SECOND */
1225 
1226  switch (INTERVAL_RANGE(typmod))
1227  {
1228  case INTERVAL_MASK(YEAR):
1229  return 5; /* YEAR */
1230  case INTERVAL_MASK(MONTH):
1231  return 4; /* MONTH */
1232  case INTERVAL_MASK(DAY):
1233  return 3; /* DAY */
1234  case INTERVAL_MASK(HOUR):
1235  return 2; /* HOUR */
1236  case INTERVAL_MASK(MINUTE):
1237  return 1; /* MINUTE */
1238  case INTERVAL_MASK(SECOND):
1239  return 0; /* SECOND */
1241  return 4; /* MONTH */
1243  return 2; /* HOUR */
1245  return 1; /* MINUTE */
1247  return 0; /* SECOND */
1249  return 1; /* MINUTE */
1251  return 0; /* SECOND */
1253  return 0; /* SECOND */
1254  case INTERVAL_FULL_RANGE:
1255  return 0; /* SECOND */
1256  default:
1257  elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
1258  break;
1259  }
1260  return 0; /* can't get here, but keep compiler quiet */
1261 }
1262 
1263 
1264 /*
1265  * interval_support()
1266  *
1267  * Planner support function for interval_scale().
1268  *
1269  * Flatten superfluous calls to interval_scale(). The interval typmod is
1270  * complex to permit accepting and regurgitating all SQL standard variations.
1271  * For truncation purposes, it boils down to a single, simple granularity.
1272  */
1273 Datum
1275 {
1276  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1277  Node *ret = NULL;
1278 
1279  if (IsA(rawreq, SupportRequestSimplify))
1280  {
1282  FuncExpr *expr = req->fcall;
1283  Node *typmod;
1284 
1285  Assert(list_length(expr->args) >= 2);
1286 
1287  typmod = (Node *) lsecond(expr->args);
1288 
1289  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
1290  {
1291  Node *source = (Node *) linitial(expr->args);
1292  int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
1293  bool noop;
1294 
1295  if (new_typmod < 0)
1296  noop = true;
1297  else
1298  {
1299  int32 old_typmod = exprTypmod(source);
1300  int old_least_field;
1301  int new_least_field;
1302  int old_precis;
1303  int new_precis;
1304 
1305  old_least_field = intervaltypmodleastfield(old_typmod);
1306  new_least_field = intervaltypmodleastfield(new_typmod);
1307  if (old_typmod < 0)
1308  old_precis = INTERVAL_FULL_PRECISION;
1309  else
1310  old_precis = INTERVAL_PRECISION(old_typmod);
1311  new_precis = INTERVAL_PRECISION(new_typmod);
1312 
1313  /*
1314  * Cast is a no-op if least field stays the same or decreases
1315  * while precision stays the same or increases. But
1316  * precision, which is to say, sub-second precision, only
1317  * affects ranges that include SECOND.
1318  */
1319  noop = (new_least_field <= old_least_field) &&
1320  (old_least_field > 0 /* SECOND */ ||
1321  new_precis >= MAX_INTERVAL_PRECISION ||
1322  new_precis >= old_precis);
1323  }
1324  if (noop)
1325  ret = relabel_to_typmod(source, new_typmod);
1326  }
1327  }
1328 
1329  PG_RETURN_POINTER(ret);
1330 }
1331 
1332 /* interval_scale()
1333  * Adjust interval type for specified fields.
1334  * Used by PostgreSQL type system to stuff columns.
1335  */
1336 Datum
1338 {
1340  int32 typmod = PG_GETARG_INT32(1);
1341  Interval *result;
1342 
1343  result = palloc(sizeof(Interval));
1344  *result = *interval;
1345 
1346  AdjustIntervalForTypmod(result, typmod, NULL);
1347 
1348  PG_RETURN_INTERVAL_P(result);
1349 }
1350 
1351 /*
1352  * Adjust interval for specified precision, in both YEAR to SECOND
1353  * range and sub-second precision.
1354  *
1355  * Returns true on success, false on failure (if escontext points to an
1356  * ErrorSaveContext; otherwise errors are thrown).
1357  */
1358 static bool
1360  Node *escontext)
1361 {
1362  static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
1363  INT64CONST(1000000),
1364  INT64CONST(100000),
1365  INT64CONST(10000),
1366  INT64CONST(1000),
1367  INT64CONST(100),
1368  INT64CONST(10),
1369  INT64CONST(1)
1370  };
1371 
1372  static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {
1373  INT64CONST(500000),
1374  INT64CONST(50000),
1375  INT64CONST(5000),
1376  INT64CONST(500),
1377  INT64CONST(50),
1378  INT64CONST(5),
1379  INT64CONST(0)
1380  };
1381 
1382  /* Typmod has no effect on infinite intervals */
1384  return true;
1385 
1386  /*
1387  * Unspecified range and precision? Then not necessary to adjust. Setting
1388  * typmod to -1 is the convention for all data types.
1389  */
1390  if (typmod >= 0)
1391  {
1392  int range = INTERVAL_RANGE(typmod);
1393  int precision = INTERVAL_PRECISION(typmod);
1394 
1395  /*
1396  * Our interpretation of intervals with a limited set of fields is
1397  * that fields to the right of the last one specified are zeroed out,
1398  * but those to the left of it remain valid. Thus for example there
1399  * is no operational difference between INTERVAL YEAR TO MONTH and
1400  * INTERVAL MONTH. In some cases we could meaningfully enforce that
1401  * higher-order fields are zero; for example INTERVAL DAY could reject
1402  * nonzero "month" field. However that seems a bit pointless when we
1403  * can't do it consistently. (We cannot enforce a range limit on the
1404  * highest expected field, since we do not have any equivalent of
1405  * SQL's <interval leading field precision>.) If we ever decide to
1406  * revisit this, interval_support will likely require adjusting.
1407  *
1408  * Note: before PG 8.4 we interpreted a limited set of fields as
1409  * actually causing a "modulo" operation on a given value, potentially
1410  * losing high-order as well as low-order information. But there is
1411  * no support for such behavior in the standard, and it seems fairly
1412  * undesirable on data consistency grounds anyway. Now we only
1413  * perform truncation or rounding of low-order fields.
1414  */
1415  if (range == INTERVAL_FULL_RANGE)
1416  {
1417  /* Do nothing... */
1418  }
1419  else if (range == INTERVAL_MASK(YEAR))
1420  {
1422  interval->day = 0;
1423  interval->time = 0;
1424  }
1425  else if (range == INTERVAL_MASK(MONTH))
1426  {
1427  interval->day = 0;
1428  interval->time = 0;
1429  }
1430  /* YEAR TO MONTH */
1431  else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
1432  {
1433  interval->day = 0;
1434  interval->time = 0;
1435  }
1436  else if (range == INTERVAL_MASK(DAY))
1437  {
1438  interval->time = 0;
1439  }
1440  else if (range == INTERVAL_MASK(HOUR))
1441  {
1444  }
1445  else if (range == INTERVAL_MASK(MINUTE))
1446  {
1449  }
1450  else if (range == INTERVAL_MASK(SECOND))
1451  {
1452  /* fractional-second rounding will be dealt with below */
1453  }
1454  /* DAY TO HOUR */
1455  else if (range == (INTERVAL_MASK(DAY) |
1456  INTERVAL_MASK(HOUR)))
1457  {
1460  }
1461  /* DAY TO MINUTE */
1462  else if (range == (INTERVAL_MASK(DAY) |
1463  INTERVAL_MASK(HOUR) |
1465  {
1468  }
1469  /* DAY TO SECOND */
1470  else if (range == (INTERVAL_MASK(DAY) |
1471  INTERVAL_MASK(HOUR) |
1474  {
1475  /* fractional-second rounding will be dealt with below */
1476  }
1477  /* HOUR TO MINUTE */
1478  else if (range == (INTERVAL_MASK(HOUR) |
1480  {
1483  }
1484  /* HOUR TO SECOND */
1485  else if (range == (INTERVAL_MASK(HOUR) |
1488  {
1489  /* fractional-second rounding will be dealt with below */
1490  }
1491  /* MINUTE TO SECOND */
1492  else if (range == (INTERVAL_MASK(MINUTE) |
1494  {
1495  /* fractional-second rounding will be dealt with below */
1496  }
1497  else
1498  elog(ERROR, "unrecognized interval typmod: %d", typmod);
1499 
1500  /* Need to adjust sub-second precision? */
1501  if (precision != INTERVAL_FULL_PRECISION)
1502  {
1503  if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
1504  ereturn(escontext, false,
1505  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1506  errmsg("interval(%d) precision must be between %d and %d",
1507  precision, 0, MAX_INTERVAL_PRECISION)));
1508 
1509  if (interval->time >= INT64CONST(0))
1510  {
1512  IntervalOffsets[precision],
1513  &interval->time))
1514  ereturn(escontext, false,
1515  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1516  errmsg("interval out of range")));
1517  interval->time -= interval->time % IntervalScales[precision];
1518  }
1519  else
1520  {
1522  IntervalOffsets[precision],
1523  &interval->time))
1524  ereturn(escontext, false,
1525  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1526  errmsg("interval out of range")));
1527  interval->time -= interval->time % IntervalScales[precision];
1528  }
1529  }
1530  }
1531 
1532  return true;
1533 }
1534 
1535 /*
1536  * make_interval - numeric Interval constructor
1537  */
1538 Datum
1540 {
1541  int32 years = PG_GETARG_INT32(0);
1543  int32 weeks = PG_GETARG_INT32(2);
1544  int32 days = PG_GETARG_INT32(3);
1545  int32 hours = PG_GETARG_INT32(4);
1546  int32 mins = PG_GETARG_INT32(5);
1547  double secs = PG_GETARG_FLOAT8(6);
1548  Interval *result;
1549 
1550  /*
1551  * Reject out-of-range inputs. We reject any input values that cause
1552  * integer overflow of the corresponding interval fields.
1553  */
1554  if (isinf(secs) || isnan(secs))
1555  goto out_of_range;
1556 
1557  result = (Interval *) palloc(sizeof(Interval));
1558 
1559  /* years and months -> months */
1560  if (pg_mul_s32_overflow(years, MONTHS_PER_YEAR, &result->month) ||
1561  pg_add_s32_overflow(result->month, months, &result->month))
1562  goto out_of_range;
1563 
1564  /* weeks and days -> days */
1565  if (pg_mul_s32_overflow(weeks, DAYS_PER_WEEK, &result->day) ||
1566  pg_add_s32_overflow(result->day, days, &result->day))
1567  goto out_of_range;
1568 
1569  /* hours and mins -> usecs (cannot overflow 64-bit) */
1570  result->time = hours * USECS_PER_HOUR + mins * USECS_PER_MINUTE;
1571 
1572  /* secs -> usecs */
1573  secs = rint(float8_mul(secs, USECS_PER_SEC));
1574  if (!FLOAT8_FITS_IN_INT64(secs) ||
1575  pg_add_s64_overflow(result->time, (int64) secs, &result->time))
1576  goto out_of_range;
1577 
1578  /* make sure that the result is finite */
1579  if (INTERVAL_NOT_FINITE(result))
1580  goto out_of_range;
1581 
1582  PG_RETURN_INTERVAL_P(result);
1583 
1584 out_of_range:
1585  ereport(ERROR,
1586  errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1587  errmsg("interval out of range"));
1588 
1589  PG_RETURN_NULL(); /* keep compiler quiet */
1590 }
1591 
1592 /* EncodeSpecialTimestamp()
1593  * Convert reserved timestamp data type to string.
1594  */
1595 void
1597 {
1598  if (TIMESTAMP_IS_NOBEGIN(dt))
1599  strcpy(str, EARLY);
1600  else if (TIMESTAMP_IS_NOEND(dt))
1601  strcpy(str, LATE);
1602  else /* shouldn't happen */
1603  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1604 }
1605 
1606 static void
1608 {
1610  strcpy(str, EARLY);
1611  else if (INTERVAL_IS_NOEND(interval))
1612  strcpy(str, LATE);
1613  else /* shouldn't happen */
1614  elog(ERROR, "invalid argument for EncodeSpecialInterval");
1615 }
1616 
1617 Datum
1619 {
1621 }
1622 
1623 Datum
1625 {
1627 }
1628 
1629 Datum
1631 {
1633 }
1634 
1635 Datum
1637 {
1639 }
1640 
1641 Datum
1643 {
1645 }
1646 
1647 /*
1648  * GetCurrentTimestamp -- get the current operating system time
1649  *
1650  * Result is in the form of a TimestampTz value, and is expressed to the
1651  * full precision of the gettimeofday() syscall
1652  */
1655 {
1656  TimestampTz result;
1657  struct timeval tp;
1658 
1659  gettimeofday(&tp, NULL);
1660 
1661  result = (TimestampTz) tp.tv_sec -
1663  result = (result * USECS_PER_SEC) + tp.tv_usec;
1664 
1665  return result;
1666 }
1667 
1668 /*
1669  * GetSQLCurrentTimestamp -- implements CURRENT_TIMESTAMP, CURRENT_TIMESTAMP(n)
1670  */
1673 {
1674  TimestampTz ts;
1675 
1677  if (typmod >= 0)
1678  AdjustTimestampForTypmod(&ts, typmod, NULL);
1679  return ts;
1680 }
1681 
1682 /*
1683  * GetSQLLocalTimestamp -- implements LOCALTIMESTAMP, LOCALTIMESTAMP(n)
1684  */
1685 Timestamp
1687 {
1688  Timestamp ts;
1689 
1691  if (typmod >= 0)
1692  AdjustTimestampForTypmod(&ts, typmod, NULL);
1693  return ts;
1694 }
1695 
1696 /*
1697  * timeofday(*) -- returns the current time as a text.
1698  */
1699 Datum
1701 {
1702  struct timeval tp;
1703  char templ[128];
1704  char buf[128];
1705  pg_time_t tt;
1706 
1707  gettimeofday(&tp, NULL);
1708  tt = (pg_time_t) tp.tv_sec;
1709  pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
1711  snprintf(buf, sizeof(buf), templ, tp.tv_usec);
1712 
1714 }
1715 
1716 /*
1717  * TimestampDifference -- convert the difference between two timestamps
1718  * into integer seconds and microseconds
1719  *
1720  * This is typically used to calculate a wait timeout for select(2),
1721  * which explains the otherwise-odd choice of output format.
1722  *
1723  * Both inputs must be ordinary finite timestamps (in current usage,
1724  * they'll be results from GetCurrentTimestamp()).
1725  *
1726  * We expect start_time <= stop_time. If not, we return zeros,
1727  * since then we're already past the previously determined stop_time.
1728  */
1729 void
1731  long *secs, int *microsecs)
1732 {
1733  TimestampTz diff = stop_time - start_time;
1734 
1735  if (diff <= 0)
1736  {
1737  *secs = 0;
1738  *microsecs = 0;
1739  }
1740  else
1741  {
1742  *secs = (long) (diff / USECS_PER_SEC);
1743  *microsecs = (int) (diff % USECS_PER_SEC);
1744  }
1745 }
1746 
1747 /*
1748  * TimestampDifferenceMilliseconds -- convert the difference between two
1749  * timestamps into integer milliseconds
1750  *
1751  * This is typically used to calculate a wait timeout for WaitLatch()
1752  * or a related function. The choice of "long" as the result type
1753  * is to harmonize with that; furthermore, we clamp the result to at most
1754  * INT_MAX milliseconds, because that's all that WaitLatch() allows.
1755  *
1756  * We expect start_time <= stop_time. If not, we return zero,
1757  * since then we're already past the previously determined stop_time.
1758  *
1759  * Subtracting finite and infinite timestamps works correctly, returning
1760  * zero or INT_MAX as appropriate.
1761  *
1762  * Note we round up any fractional millisecond, since waiting for just
1763  * less than the intended timeout is undesirable.
1764  */
1765 long
1767 {
1768  TimestampTz diff;
1769 
1770  /* Deal with zero or negative elapsed time quickly. */
1771  if (start_time >= stop_time)
1772  return 0;
1773  /* To not fail with timestamp infinities, we must detect overflow. */
1774  if (pg_sub_s64_overflow(stop_time, start_time, &diff))
1775  return (long) INT_MAX;
1776  if (diff >= (INT_MAX * INT64CONST(1000) - 999))
1777  return (long) INT_MAX;
1778  else
1779  return (long) ((diff + 999) / 1000);
1780 }
1781 
1782 /*
1783  * TimestampDifferenceExceeds -- report whether the difference between two
1784  * timestamps is >= a threshold (expressed in milliseconds)
1785  *
1786  * Both inputs must be ordinary finite timestamps (in current usage,
1787  * they'll be results from GetCurrentTimestamp()).
1788  */
1789 bool
1791  TimestampTz stop_time,
1792  int msec)
1793 {
1794  TimestampTz diff = stop_time - start_time;
1795 
1796  return (diff >= msec * INT64CONST(1000));
1797 }
1798 
1799 /*
1800  * Convert a time_t to TimestampTz.
1801  *
1802  * We do not use time_t internally in Postgres, but this is provided for use
1803  * by functions that need to interpret, say, a stat(2) result.
1804  *
1805  * To avoid having the function's ABI vary depending on the width of time_t,
1806  * we declare the argument as pg_time_t, which is cast-compatible with
1807  * time_t but always 64 bits wide (unless the platform has no 64-bit type).
1808  * This detail should be invisible to callers, at least at source code level.
1809  */
1812 {
1813  TimestampTz result;
1814 
1815  result = (TimestampTz) tm -
1817  result *= USECS_PER_SEC;
1818 
1819  return result;
1820 }
1821 
1822 /*
1823  * Convert a TimestampTz to time_t.
1824  *
1825  * This too is just marginally useful, but some places need it.
1826  *
1827  * To avoid having the function's ABI vary depending on the width of time_t,
1828  * we declare the result as pg_time_t, which is cast-compatible with
1829  * time_t but always 64 bits wide (unless the platform has no 64-bit type).
1830  * This detail should be invisible to callers, at least at source code level.
1831  */
1832 pg_time_t
1834 {
1835  pg_time_t result;
1836 
1837  result = (pg_time_t) (t / USECS_PER_SEC +
1839 
1840  return result;
1841 }
1842 
1843 /*
1844  * Produce a C-string representation of a TimestampTz.
1845  *
1846  * This is mostly for use in emitting messages. The primary difference
1847  * from timestamptz_out is that we force the output format to ISO. Note
1848  * also that the result is in a static buffer, not pstrdup'd.
1849  *
1850  * See also pg_strftime.
1851  */
1852 const char *
1854 {
1855  static char buf[MAXDATELEN + 1];
1856  int tz;
1857  struct pg_tm tt,
1858  *tm = &tt;
1859  fsec_t fsec;
1860  const char *tzn;
1861 
1862  if (TIMESTAMP_NOT_FINITE(t))
1864  else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
1865  EncodeDateTime(tm, fsec, true, tz, tzn, USE_ISO_DATES, buf);
1866  else
1867  strlcpy(buf, "(timestamp out of range)", sizeof(buf));
1868 
1869  return buf;
1870 }
1871 
1872 
1873 void
1874 dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
1875 {
1876  TimeOffset time;
1877 
1878  time = jd;
1879 
1880  *hour = time / USECS_PER_HOUR;
1881  time -= (*hour) * USECS_PER_HOUR;
1882  *min = time / USECS_PER_MINUTE;
1883  time -= (*min) * USECS_PER_MINUTE;
1884  *sec = time / USECS_PER_SEC;
1885  *fsec = time - (*sec * USECS_PER_SEC);
1886 } /* dt2time() */
1887 
1888 
1889 /*
1890  * timestamp2tm() - Convert timestamp data type to POSIX time structure.
1891  *
1892  * Note that year is _not_ 1900-based, but is an explicit full value.
1893  * Also, month is one-based, _not_ zero-based.
1894  * Returns:
1895  * 0 on success
1896  * -1 on out of range
1897  *
1898  * If attimezone is NULL, the global timezone setting will be used.
1899  */
1900 int
1901 timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
1902 {
1903  Timestamp date;
1904  Timestamp time;
1905  pg_time_t utime;
1906 
1907  /* Use session timezone if caller asks for default */
1908  if (attimezone == NULL)
1909  attimezone = session_timezone;
1910 
1911  time = dt;
1912  TMODULO(time, date, USECS_PER_DAY);
1913 
1914  if (time < INT64CONST(0))
1915  {
1916  time += USECS_PER_DAY;
1917  date -= 1;
1918  }
1919 
1920  /* add offset to go from J2000 back to standard Julian date */
1922 
1923  /* Julian day routine does not work for negative Julian days */
1924  if (date < 0 || date > (Timestamp) INT_MAX)
1925  return -1;
1926 
1927  j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1928  dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1929 
1930  /* Done if no TZ conversion wanted */
1931  if (tzp == NULL)
1932  {
1933  tm->tm_isdst = -1;
1934  tm->tm_gmtoff = 0;
1935  tm->tm_zone = NULL;
1936  if (tzn != NULL)
1937  *tzn = NULL;
1938  return 0;
1939  }
1940 
1941  /*
1942  * If the time falls within the range of pg_time_t, use pg_localtime() to
1943  * rotate to the local time zone.
1944  *
1945  * First, convert to an integral timestamp, avoiding possibly
1946  * platform-specific roundoff-in-wrong-direction errors, and adjust to
1947  * Unix epoch. Then see if we can convert to pg_time_t without loss. This
1948  * coding avoids hardwiring any assumptions about the width of pg_time_t,
1949  * so it should behave sanely on machines without int64.
1950  */
1951  dt = (dt - *fsec) / USECS_PER_SEC +
1953  utime = (pg_time_t) dt;
1954  if ((Timestamp) utime == dt)
1955  {
1956  struct pg_tm *tx = pg_localtime(&utime, attimezone);
1957 
1958  tm->tm_year = tx->tm_year + 1900;
1959  tm->tm_mon = tx->tm_mon + 1;
1960  tm->tm_mday = tx->tm_mday;
1961  tm->tm_hour = tx->tm_hour;
1962  tm->tm_min = tx->tm_min;
1963  tm->tm_sec = tx->tm_sec;
1964  tm->tm_isdst = tx->tm_isdst;
1965  tm->tm_gmtoff = tx->tm_gmtoff;
1966  tm->tm_zone = tx->tm_zone;
1967  *tzp = -tm->tm_gmtoff;
1968  if (tzn != NULL)
1969  *tzn = tm->tm_zone;
1970  }
1971  else
1972  {
1973  /*
1974  * When out of range of pg_time_t, treat as GMT
1975  */
1976  *tzp = 0;
1977  /* Mark this as *no* time zone available */
1978  tm->tm_isdst = -1;
1979  tm->tm_gmtoff = 0;
1980  tm->tm_zone = NULL;
1981  if (tzn != NULL)
1982  *tzn = NULL;
1983  }
1984 
1985  return 0;
1986 }
1987 
1988 
1989 /* tm2timestamp()
1990  * Convert a tm structure to a timestamp data type.
1991  * Note that year is _not_ 1900-based, but is an explicit full value.
1992  * Also, month is one-based, _not_ zero-based.
1993  *
1994  * Returns -1 on failure (value out of range).
1995  */
1996 int
1997 tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
1998 {
1999  TimeOffset date;
2000  TimeOffset time;
2001 
2002  /* Prevent overflow in Julian-day routines */
2004  {
2005  *result = 0; /* keep compiler quiet */
2006  return -1;
2007  }
2008 
2010  time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
2011 
2012  *result = date * USECS_PER_DAY + time;
2013  /* check for major overflow */
2014  if ((*result - time) / USECS_PER_DAY != date)
2015  {
2016  *result = 0; /* keep compiler quiet */
2017  return -1;
2018  }
2019  /* check for just-barely overflow (okay except time-of-day wraps) */
2020  /* caution: we want to allow 1999-12-31 24:00:00 */
2021  if ((*result < 0 && date > 0) ||
2022  (*result > 0 && date < -1))
2023  {
2024  *result = 0; /* keep compiler quiet */
2025  return -1;
2026  }
2027  if (tzp != NULL)
2028  *result = dt2local(*result, -(*tzp));
2029 
2030  /* final range check catches just-out-of-range timestamps */
2031  if (!IS_VALID_TIMESTAMP(*result))
2032  {
2033  *result = 0; /* keep compiler quiet */
2034  return -1;
2035  }
2036 
2037  return 0;
2038 }
2039 
2040 
2041 /* interval2itm()
2042  * Convert an Interval to a pg_itm structure.
2043  * Note: overflow is not possible, because the pg_itm fields are
2044  * wide enough for all possible conversion results.
2045  */
2046 void
2047 interval2itm(Interval span, struct pg_itm *itm)
2048 {
2049  TimeOffset time;
2050  TimeOffset tfrac;
2051 
2052  itm->tm_year = span.month / MONTHS_PER_YEAR;
2053  itm->tm_mon = span.month % MONTHS_PER_YEAR;
2054  itm->tm_mday = span.day;
2055  time = span.time;
2056 
2057  tfrac = time / USECS_PER_HOUR;
2058  time -= tfrac * USECS_PER_HOUR;
2059  itm->tm_hour = tfrac;
2060  tfrac = time / USECS_PER_MINUTE;
2061  time -= tfrac * USECS_PER_MINUTE;
2062  itm->tm_min = (int) tfrac;
2063  tfrac = time / USECS_PER_SEC;
2064  time -= tfrac * USECS_PER_SEC;
2065  itm->tm_sec = (int) tfrac;
2066  itm->tm_usec = (int) time;
2067 }
2068 
2069 /* itm2interval()
2070  * Convert a pg_itm structure to an Interval.
2071  * Returns 0 if OK, -1 on overflow.
2072  *
2073  * This is for use in computations expected to produce finite results. Any
2074  * inputs that lead to infinite results are treated as overflows.
2075  */
2076 int
2077 itm2interval(struct pg_itm *itm, Interval *span)
2078 {
2079  int64 total_months = (int64) itm->tm_year * MONTHS_PER_YEAR + itm->tm_mon;
2080 
2081  if (total_months > INT_MAX || total_months < INT_MIN)
2082  return -1;
2083  span->month = (int32) total_months;
2084  span->day = itm->tm_mday;
2086  &span->time))
2087  return -1;
2088  /* tm_min, tm_sec are 32 bits, so intermediate products can't overflow */
2089  if (pg_add_s64_overflow(span->time, itm->tm_min * USECS_PER_MINUTE,
2090  &span->time))
2091  return -1;
2092  if (pg_add_s64_overflow(span->time, itm->tm_sec * USECS_PER_SEC,
2093  &span->time))
2094  return -1;
2095  if (pg_add_s64_overflow(span->time, itm->tm_usec,
2096  &span->time))
2097  return -1;
2098  if (INTERVAL_NOT_FINITE(span))
2099  return -1;
2100  return 0;
2101 }
2102 
2103 /* itmin2interval()
2104  * Convert a pg_itm_in structure to an Interval.
2105  * Returns 0 if OK, -1 on overflow.
2106  *
2107  * Note: if the result is infinite, it is not treated as an overflow. This
2108  * avoids any dump/reload hazards from pre-17 databases that do not support
2109  * infinite intervals, but do allow finite intervals with all fields set to
2110  * INT_MIN/INT_MAX (outside the documented range). Such intervals will be
2111  * silently converted to +/-infinity. This may not be ideal, but seems
2112  * preferable to failure, and ought to be pretty unlikely in practice.
2113  */
2114 int
2115 itmin2interval(struct pg_itm_in *itm_in, Interval *span)
2116 {
2117  int64 total_months = (int64) itm_in->tm_year * MONTHS_PER_YEAR + itm_in->tm_mon;
2118 
2119  if (total_months > INT_MAX || total_months < INT_MIN)
2120  return -1;
2121  span->month = (int32) total_months;
2122  span->day = itm_in->tm_mday;
2123  span->time = itm_in->tm_usec;
2124  return 0;
2125 }
2126 
2127 static TimeOffset
2128 time2t(const int hour, const int min, const int sec, const fsec_t fsec)
2129 {
2130  return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
2131 }
2132 
2133 static Timestamp
2134 dt2local(Timestamp dt, int timezone)
2135 {
2136  dt -= (timezone * USECS_PER_SEC);
2137  return dt;
2138 }
2139 
2140 
2141 /*****************************************************************************
2142  * PUBLIC ROUTINES *
2143  *****************************************************************************/
2144 
2145 
2146 Datum
2148 {
2150 
2152 }
2153 
2154 Datum
2156 {
2158 
2160 }
2161 
2162 
2163 /*----------------------------------------------------------
2164  * Relational operators for timestamp.
2165  *---------------------------------------------------------*/
2166 
2167 void
2169 {
2170  struct pg_tm *t0;
2171  pg_time_t epoch = 0;
2172 
2173  t0 = pg_gmtime(&epoch);
2174 
2175  if (t0 == NULL)
2176  elog(ERROR, "could not convert epoch to timestamp: %m");
2177 
2178  tm->tm_year = t0->tm_year;
2179  tm->tm_mon = t0->tm_mon;
2180  tm->tm_mday = t0->tm_mday;
2181  tm->tm_hour = t0->tm_hour;
2182  tm->tm_min = t0->tm_min;
2183  tm->tm_sec = t0->tm_sec;
2184 
2185  tm->tm_year += 1900;
2186  tm->tm_mon++;
2187 }
2188 
2189 Timestamp
2191 {
2192  Timestamp dt;
2193  struct pg_tm tt,
2194  *tm = &tt;
2195 
2196  GetEpochTime(tm);
2197  /* we don't bother to test for failure ... */
2198  tm2timestamp(tm, 0, NULL, &dt);
2199 
2200  return dt;
2201 } /* SetEpochTimestamp() */
2202 
2203 /*
2204  * We are currently sharing some code between timestamp and timestamptz.
2205  * The comparison functions are among them. - thomas 2001-09-25
2206  *
2207  * timestamp_relop - is timestamp1 relop timestamp2
2208  */
2209 int
2211 {
2212  return (dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0);
2213 }
2214 
2215 Datum
2217 {
2218  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2219  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2220 
2221  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
2222 }
2223 
2224 Datum
2226 {
2227  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2228  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2229 
2230  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
2231 }
2232 
2233 Datum
2235 {
2236  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2237  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2238 
2239  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
2240 }
2241 
2242 Datum
2244 {
2245  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2246  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2247 
2248  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
2249 }
2250 
2251 Datum
2253 {
2254  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2255  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2256 
2257  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
2258 }
2259 
2260 Datum
2262 {
2263  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2264  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2265 
2266  PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
2267 }
2268 
2269 Datum
2271 {
2272  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2273  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2274 
2276 }
2277 
2278 #if SIZEOF_DATUM < 8
2279 /* note: this is used for timestamptz also */
2280 static int
2282 {
2285 
2286  return timestamp_cmp_internal(a, b);
2287 }
2288 #endif
2289 
2290 Datum
2292 {
2294 
2295 #if SIZEOF_DATUM >= 8
2296 
2297  /*
2298  * If this build has pass-by-value timestamps, then we can use a standard
2299  * comparator function.
2300  */
2301  ssup->comparator = ssup_datum_signed_cmp;
2302 #else
2303  ssup->comparator = timestamp_fastcmp;
2304 #endif
2305  PG_RETURN_VOID();
2306 }
2307 
2308 Datum
2310 {
2311  return hashint8(fcinfo);
2312 }
2313 
2314 Datum
2316 {
2317  return hashint8extended(fcinfo);
2318 }
2319 
2320 /*
2321  * Cross-type comparison functions for timestamp vs timestamptz
2322  */
2323 
2324 int32
2326 {
2327  TimestampTz dt1;
2328  int overflow;
2329 
2330  dt1 = timestamp2timestamptz_opt_overflow(timestampVal, &overflow);
2331  if (overflow > 0)
2332  {
2333  /* dt1 is larger than any finite timestamp, but less than infinity */
2334  return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1;
2335  }
2336  if (overflow < 0)
2337  {
2338  /* dt1 is less than any finite timestamp, but more than -infinity */
2339  return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1;
2340  }
2341 
2342  return timestamptz_cmp_internal(dt1, dt2);
2343 }
2344 
2345 Datum
2347 {
2348  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2350 
2351  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) == 0);
2352 }
2353 
2354 Datum
2356 {
2357  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2359 
2360  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) != 0);
2361 }
2362 
2363 Datum
2365 {
2366  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2368 
2369  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) < 0);
2370 }
2371 
2372 Datum
2374 {
2375  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2377 
2378  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) > 0);
2379 }
2380 
2381 Datum
2383 {
2384  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2386 
2387  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) <= 0);
2388 }
2389 
2390 Datum
2392 {
2393  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2395 
2396  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt2) >= 0);
2397 }
2398 
2399 Datum
2401 {
2402  Timestamp timestampVal = PG_GETARG_TIMESTAMP(0);
2404 
2406 }
2407 
2408 Datum
2410 {
2412  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2413 
2414  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) == 0);
2415 }
2416 
2417 Datum
2419 {
2421  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2422 
2423  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) != 0);
2424 }
2425 
2426 Datum
2428 {
2430  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2431 
2432  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) > 0);
2433 }
2434 
2435 Datum
2437 {
2439  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2440 
2441  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) < 0);
2442 }
2443 
2444 Datum
2446 {
2448  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2449 
2450  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) >= 0);
2451 }
2452 
2453 Datum
2455 {
2457  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2458 
2459  PG_RETURN_BOOL(timestamp_cmp_timestamptz_internal(timestampVal, dt1) <= 0);
2460 }
2461 
2462 Datum
2464 {
2466  Timestamp timestampVal = PG_GETARG_TIMESTAMP(1);
2467 
2469 }
2470 
2471 
2472 /*
2473  * interval_relop - is interval1 relop interval2
2474  *
2475  * Interval comparison is based on converting interval values to a linear
2476  * representation expressed in the units of the time field (microseconds,
2477  * in the case of integer timestamps) with days assumed to be always 24 hours
2478  * and months assumed to be always 30 days. To avoid overflow, we need a
2479  * wider-than-int64 datatype for the linear representation, so use INT128.
2480  */
2481 
2482 static inline INT128
2484 {
2485  INT128 span;
2486  int64 days;
2487 
2488  /*
2489  * Combine the month and day fields into an integral number of days.
2490  * Because the inputs are int32, int64 arithmetic suffices here.
2491  */
2492  days = interval->month * INT64CONST(30);
2493  days += interval->day;
2494 
2495  /* Widen time field to 128 bits */
2496  span = int64_to_int128(interval->time);
2497 
2498  /* Scale up days to microseconds, forming a 128-bit product */
2500 
2501  return span;
2502 }
2503 
2504 static int
2505 interval_cmp_internal(const Interval *interval1, const Interval *interval2)
2506 {
2507  INT128 span1 = interval_cmp_value(interval1);
2508  INT128 span2 = interval_cmp_value(interval2);
2509 
2510  return int128_compare(span1, span2);
2511 }
2512 
2513 static int
2515 {
2517  INT128 zero = int64_to_int128(0);
2518 
2519  return int128_compare(span, zero);
2520 }
2521 
2522 Datum
2524 {
2525  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2526  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2527 
2528  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);
2529 }
2530 
2531 Datum
2533 {
2534  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2535  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2536 
2537  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);
2538 }
2539 
2540 Datum
2542 {
2543  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2544  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2545 
2546  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);
2547 }
2548 
2549 Datum
2551 {
2552  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2553  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2554 
2555  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);
2556 }
2557 
2558 Datum
2560 {
2561  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2562  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2563 
2564  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
2565 }
2566 
2567 Datum
2569 {
2570  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2571  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2572 
2573  PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
2574 }
2575 
2576 Datum
2578 {
2579  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
2580  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
2581 
2582  PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
2583 }
2584 
2585 /*
2586  * Hashing for intervals
2587  *
2588  * We must produce equal hashvals for values that interval_cmp_internal()
2589  * considers equal. So, compute the net span the same way it does,
2590  * and then hash that.
2591  */
2592 Datum
2594 {
2597  int64 span64;
2598 
2599  /*
2600  * Use only the least significant 64 bits for hashing. The upper 64 bits
2601  * seldom add any useful information, and besides we must do it like this
2602  * for compatibility with hashes calculated before use of INT128 was
2603  * introduced.
2604  */
2605  span64 = int128_to_int64(span);
2606 
2608 }
2609 
2610 Datum
2612 {
2615  int64 span64;
2616 
2617  /* Same approach as interval_hash */
2618  span64 = int128_to_int64(span);
2619 
2621  PG_GETARG_DATUM(1));
2622 }
2623 
2624 /* overlaps_timestamp() --- implements the SQL OVERLAPS operator.
2625  *
2626  * Algorithm is per SQL spec. This is much harder than you'd think
2627  * because the spec requires us to deliver a non-null answer in some cases
2628  * where some of the inputs are null.
2629  */
2630 Datum
2632 {
2633  /*
2634  * The arguments are Timestamps, but we leave them as generic Datums to
2635  * avoid unnecessary conversions between value and reference forms --- not
2636  * to mention possible dereferences of null pointers.
2637  */
2638  Datum ts1 = PG_GETARG_DATUM(0);
2639  Datum te1 = PG_GETARG_DATUM(1);
2640  Datum ts2 = PG_GETARG_DATUM(2);
2641  Datum te2 = PG_GETARG_DATUM(3);
2642  bool ts1IsNull = PG_ARGISNULL(0);
2643  bool te1IsNull = PG_ARGISNULL(1);
2644  bool ts2IsNull = PG_ARGISNULL(2);
2645  bool te2IsNull = PG_ARGISNULL(3);
2646 
2647 #define TIMESTAMP_GT(t1,t2) \
2648  DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))
2649 #define TIMESTAMP_LT(t1,t2) \
2650  DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))
2651 
2652  /*
2653  * If both endpoints of interval 1 are null, the result is null (unknown).
2654  * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
2655  * take ts1 as the lesser endpoint.
2656  */
2657  if (ts1IsNull)
2658  {
2659  if (te1IsNull)
2660  PG_RETURN_NULL();
2661  /* swap null for non-null */
2662  ts1 = te1;
2663  te1IsNull = true;
2664  }
2665  else if (!te1IsNull)
2666  {
2667  if (TIMESTAMP_GT(ts1, te1))
2668  {
2669  Datum tt = ts1;
2670 
2671  ts1 = te1;
2672  te1 = tt;
2673  }
2674  }
2675 
2676  /* Likewise for interval 2. */
2677  if (ts2IsNull)
2678  {
2679  if (te2IsNull)
2680  PG_RETURN_NULL();
2681  /* swap null for non-null */
2682  ts2 = te2;
2683  te2IsNull = true;
2684  }
2685  else if (!te2IsNull)
2686  {
2687  if (TIMESTAMP_GT(ts2, te2))
2688  {
2689  Datum tt = ts2;
2690 
2691  ts2 = te2;
2692  te2 = tt;
2693  }
2694  }
2695 
2696  /*
2697  * At this point neither ts1 nor ts2 is null, so we can consider three
2698  * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
2699  */
2700  if (TIMESTAMP_GT(ts1, ts2))
2701  {
2702  /*
2703  * This case is ts1 < te2 OR te1 < te2, which may look redundant but
2704  * in the presence of nulls it's not quite completely so.
2705  */
2706  if (te2IsNull)
2707  PG_RETURN_NULL();
2708  if (TIMESTAMP_LT(ts1, te2))
2709  PG_RETURN_BOOL(true);
2710  if (te1IsNull)
2711  PG_RETURN_NULL();
2712 
2713  /*
2714  * If te1 is not null then we had ts1 <= te1 above, and we just found
2715  * ts1 >= te2, hence te1 >= te2.
2716  */
2717  PG_RETURN_BOOL(false);
2718  }
2719  else if (TIMESTAMP_LT(ts1, ts2))
2720  {
2721  /* This case is ts2 < te1 OR te2 < te1 */
2722  if (te1IsNull)
2723  PG_RETURN_NULL();
2724  if (TIMESTAMP_LT(ts2, te1))
2725  PG_RETURN_BOOL(true);
2726  if (te2IsNull)
2727  PG_RETURN_NULL();
2728 
2729  /*
2730  * If te2 is not null then we had ts2 <= te2 above, and we just found
2731  * ts2 >= te1, hence te2 >= te1.
2732  */
2733  PG_RETURN_BOOL(false);
2734  }
2735  else
2736  {
2737  /*
2738  * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
2739  * rather silly way of saying "true if both are non-null, else null".
2740  */
2741  if (te1IsNull || te2IsNull)
2742  PG_RETURN_NULL();
2743  PG_RETURN_BOOL(true);
2744  }
2745 
2746 #undef TIMESTAMP_GT
2747 #undef TIMESTAMP_LT
2748 }
2749 
2750 
2751 /*----------------------------------------------------------
2752  * "Arithmetic" operators on date/times.
2753  *---------------------------------------------------------*/
2754 
2755 Datum
2757 {
2758  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2759  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2760  Timestamp result;
2761 
2762  /* use timestamp_cmp_internal to be sure this agrees with comparisons */
2763  if (timestamp_cmp_internal(dt1, dt2) < 0)
2764  result = dt1;
2765  else
2766  result = dt2;
2767  PG_RETURN_TIMESTAMP(result);
2768 }
2769 
2770 Datum
2772 {
2773  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2774  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2775  Timestamp result;
2776 
2777  if (timestamp_cmp_internal(dt1, dt2) > 0)
2778  result = dt1;
2779  else
2780  result = dt2;
2781  PG_RETURN_TIMESTAMP(result);
2782 }
2783 
2784 
2785 Datum
2787 {
2788  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
2789  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
2790  Interval *result;
2791 
2792  result = (Interval *) palloc(sizeof(Interval));
2793 
2794  /*
2795  * Handle infinities.
2796  *
2797  * We treat anything that amounts to "infinity - infinity" as an error,
2798  * since the interval type has nothing equivalent to NaN.
2799  */
2800  if (TIMESTAMP_NOT_FINITE(dt1) || TIMESTAMP_NOT_FINITE(dt2))
2801  {
2802  if (TIMESTAMP_IS_NOBEGIN(dt1))
2803  {
2804  if (TIMESTAMP_IS_NOBEGIN(dt2))
2805  ereport(ERROR,
2806  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2807  errmsg("interval out of range")));
2808  else
2809  INTERVAL_NOBEGIN(result);
2810  }
2811  else if (TIMESTAMP_IS_NOEND(dt1))
2812  {
2813  if (TIMESTAMP_IS_NOEND(dt2))
2814  ereport(ERROR,
2815  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2816  errmsg("interval out of range")));
2817  else
2818  INTERVAL_NOEND(result);
2819  }
2820  else if (TIMESTAMP_IS_NOBEGIN(dt2))
2821  INTERVAL_NOEND(result);
2822  else /* TIMESTAMP_IS_NOEND(dt2) */
2823  INTERVAL_NOBEGIN(result);
2824 
2825  PG_RETURN_INTERVAL_P(result);
2826  }
2827 
2828  if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time)))
2829  ereport(ERROR,
2830  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2831  errmsg("interval out of range")));
2832 
2833  result->month = 0;
2834  result->day = 0;
2835 
2836  /*----------
2837  * This is wrong, but removing it breaks a lot of regression tests.
2838  * For example:
2839  *
2840  * test=> SET timezone = 'EST5EDT';
2841  * test=> SELECT
2842  * test-> ('2005-10-30 13:22:00-05'::timestamptz -
2843  * test(> '2005-10-29 13:22:00-04'::timestamptz);
2844  * ?column?
2845  * ----------------
2846  * 1 day 01:00:00
2847  * (1 row)
2848  *
2849  * so adding that to the first timestamp gets:
2850  *
2851  * test=> SELECT
2852  * test-> ('2005-10-29 13:22:00-04'::timestamptz +
2853  * test(> ('2005-10-30 13:22:00-05'::timestamptz -
2854  * test(> '2005-10-29 13:22:00-04'::timestamptz)) at time zone 'EST';
2855  * timezone
2856  * --------------------
2857  * 2005-10-30 14:22:00
2858  * (1 row)
2859  *----------
2860  */
2862  IntervalPGetDatum(result)));
2863 
2864  PG_RETURN_INTERVAL_P(result);
2865 }
2866 
2867 /*
2868  * interval_justify_interval()
2869  *
2870  * Adjust interval so 'month', 'day', and 'time' portions are within
2871  * customary bounds. Specifically:
2872  *
2873  * 0 <= abs(time) < 24 hours
2874  * 0 <= abs(day) < 30 days
2875  *
2876  * Also, the sign bit on all three fields is made equal, so either
2877  * all three fields are negative or all are positive.
2878  */
2879 Datum
2881 {
2882  Interval *span = PG_GETARG_INTERVAL_P(0);
2883  Interval *result;
2884  TimeOffset wholeday;
2885  int32 wholemonth;
2886 
2887  result = (Interval *) palloc(sizeof(Interval));
2888  result->month = span->month;
2889  result->day = span->day;
2890  result->time = span->time;
2891 
2892  /* do nothing for infinite intervals */
2893  if (INTERVAL_NOT_FINITE(result))
2894  PG_RETURN_INTERVAL_P(result);
2895 
2896  /* pre-justify days if it might prevent overflow */
2897  if ((result->day > 0 && result->time > 0) ||
2898  (result->day < 0 && result->time < 0))
2899  {
2900  wholemonth = result->day / DAYS_PER_MONTH;
2901  result->day -= wholemonth * DAYS_PER_MONTH;
2902  if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2903  ereport(ERROR,
2904  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2905  errmsg("interval out of range")));
2906  }
2907 
2908  /*
2909  * Since TimeOffset is int64, abs(wholeday) can't exceed about 1.07e8. If
2910  * we pre-justified then abs(result->day) is less than DAYS_PER_MONTH, so
2911  * this addition can't overflow. If we didn't pre-justify, then day and
2912  * time are of different signs, so it still can't overflow.
2913  */
2914  TMODULO(result->time, wholeday, USECS_PER_DAY);
2915  result->day += wholeday;
2916 
2917  wholemonth = result->day / DAYS_PER_MONTH;
2918  result->day -= wholemonth * DAYS_PER_MONTH;
2919  if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
2920  ereport(ERROR,
2921  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2922  errmsg("interval out of range")));
2923 
2924  if (result->month > 0 &&
2925  (result->day < 0 || (result->day == 0 && result->time < 0)))
2926  {
2927  result->day += DAYS_PER_MONTH;
2928  result->month--;
2929  }
2930  else if (result->month < 0 &&
2931  (result->day > 0 || (result->day == 0 && result->time > 0)))
2932  {
2933  result->day -= DAYS_PER_MONTH;
2934  result->month++;
2935  }
2936 
2937  if (result->day > 0 && result->time < 0)
2938  {
2939  result->time += USECS_PER_DAY;
2940  result->day--;
2941  }
2942  else if (result->day < 0 && result->time > 0)
2943  {
2944  result->time -= USECS_PER_DAY;
2945  result->day++;
2946  }
2947 
2948  PG_RETURN_INTERVAL_P(result);
2949 }
2950 
2951 /*
2952  * interval_justify_hours()
2953  *
2954  * Adjust interval so 'time' contains less than a whole day, adding
2955  * the excess to 'day'. This is useful for
2956  * situations (such as non-TZ) where '1 day' = '24 hours' is valid,
2957  * e.g. interval subtraction and division.
2958  */
2959 Datum
2961 {
2962  Interval *span = PG_GETARG_INTERVAL_P(0);
2963  Interval *result;
2964  TimeOffset wholeday;
2965 
2966  result = (Interval *) palloc(sizeof(Interval));
2967  result->month = span->month;
2968  result->day = span->day;
2969  result->time = span->time;
2970 
2971  /* do nothing for infinite intervals */
2972  if (INTERVAL_NOT_FINITE(result))
2973  PG_RETURN_INTERVAL_P(result);
2974 
2975  TMODULO(result->time, wholeday, USECS_PER_DAY);
2976  if (pg_add_s32_overflow(result->day, wholeday, &result->day))
2977  ereport(ERROR,
2978  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2979  errmsg("interval out of range")));
2980 
2981  if (result->day > 0 && result->time < 0)
2982  {
2983  result->time += USECS_PER_DAY;
2984  result->day--;
2985  }
2986  else if (result->day < 0 && result->time > 0)
2987  {
2988  result->time -= USECS_PER_DAY;
2989  result->day++;
2990  }
2991 
2992  PG_RETURN_INTERVAL_P(result);
2993 }
2994 
2995 /*
2996  * interval_justify_days()
2997  *
2998  * Adjust interval so 'day' contains less than 30 days, adding
2999  * the excess to 'month'.
3000  */
3001 Datum
3003 {
3004  Interval *span = PG_GETARG_INTERVAL_P(0);
3005  Interval *result;
3006  int32 wholemonth;
3007 
3008  result = (Interval *) palloc(sizeof(Interval));
3009  result->month = span->month;
3010  result->day = span->day;
3011  result->time = span->time;
3012 
3013  /* do nothing for infinite intervals */
3014  if (INTERVAL_NOT_FINITE(result))
3015  PG_RETURN_INTERVAL_P(result);
3016 
3017  wholemonth = result->day / DAYS_PER_MONTH;
3018  result->day -= wholemonth * DAYS_PER_MONTH;
3019  if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
3020  ereport(ERROR,
3021  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3022  errmsg("interval out of range")));
3023 
3024  if (result->month > 0 && result->day < 0)
3025  {
3026  result->day += DAYS_PER_MONTH;
3027  result->month--;
3028  }
3029  else if (result->month < 0 && result->day > 0)
3030  {
3031  result->day -= DAYS_PER_MONTH;
3032  result->month++;
3033  }
3034 
3035  PG_RETURN_INTERVAL_P(result);
3036 }
3037 
3038 /* timestamp_pl_interval()
3039  * Add an interval to a timestamp data type.
3040  * Note that interval has provisions for qualitative year/month and day
3041  * units, so try to do the right thing with them.
3042  * To add a month, increment the month, and use the same day of month.
3043  * Then, if the next month has fewer days, set the day of month
3044  * to the last day of month.
3045  * To add a day, increment the mday, and use the same time of day.
3046  * Lastly, add in the "quantitative time".
3047  */
3048 Datum
3050 {
3052  Interval *span = PG_GETARG_INTERVAL_P(1);
3053  Timestamp result;
3054 
3055  /*
3056  * Handle infinities.
3057  *
3058  * We treat anything that amounts to "infinity - infinity" as an error,
3059  * since the timestamp type has nothing equivalent to NaN.
3060  */
3061  if (INTERVAL_IS_NOBEGIN(span))
3062  {
3064  ereport(ERROR,
3065  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3066  errmsg("timestamp out of range")));
3067  else
3068  TIMESTAMP_NOBEGIN(result);
3069  }
3070  else if (INTERVAL_IS_NOEND(span))
3071  {
3073  ereport(ERROR,
3074  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3075  errmsg("timestamp out of range")));
3076  else
3077  TIMESTAMP_NOEND(result);
3078  }
3079  else if (TIMESTAMP_NOT_FINITE(timestamp))
3080  result = timestamp;
3081  else
3082  {
3083  if (span->month != 0)
3084  {
3085  struct pg_tm tt,
3086  *tm = &tt;
3087  fsec_t fsec;
3088 
3089  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3090  ereport(ERROR,
3091  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3092  errmsg("timestamp out of range")));
3093 
3094  tm->tm_mon += span->month;
3095  if (tm->tm_mon > MONTHS_PER_YEAR)
3096  {
3097  tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3098  tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3099  }
3100  else if (tm->tm_mon < 1)
3101  {
3102  tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3104  }
3105 
3106  /* adjust for end of month boundary problems... */
3107  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3108  tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3109 
3110  if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3111  ereport(ERROR,
3112  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3113  errmsg("timestamp out of range")));
3114  }
3115 
3116  if (span->day != 0)
3117  {
3118  struct pg_tm tt,
3119  *tm = &tt;
3120  fsec_t fsec;
3121  int julian;
3122 
3123  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
3124  ereport(ERROR,
3125  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3126  errmsg("timestamp out of range")));
3127 
3128  /*
3129  * Add days by converting to and from Julian. We need an overflow
3130  * check here since j2date expects a non-negative integer input.
3131  */
3132  julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3133  if (pg_add_s32_overflow(julian, span->day, &julian) ||
3134  julian < 0)
3135  ereport(ERROR,
3136  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3137  errmsg("timestamp out of range")));
3138  j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3139 
3140  if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
3141  ereport(ERROR,
3142  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3143  errmsg("timestamp out of range")));
3144  }
3145 
3146  timestamp += span->time;
3147 
3149  ereport(ERROR,
3150  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3151  errmsg("timestamp out of range")));
3152 
3153  result = timestamp;
3154  }
3155 
3156  PG_RETURN_TIMESTAMP(result);
3157 }
3158 
3159 Datum
3161 {
3163  Interval *span = PG_GETARG_INTERVAL_P(1);
3164  Interval tspan;
3165 
3166  interval_um_internal(span, &tspan);
3167 
3170  PointerGetDatum(&tspan));
3171 }
3172 
3173 
3174 /* timestamptz_pl_interval_internal()
3175  * Add an interval to a timestamptz, in the given (or session) timezone.
3176  *
3177  * Note that interval has provisions for qualitative year/month and day
3178  * units, so try to do the right thing with them.
3179  * To add a month, increment the month, and use the same day of month.
3180  * Then, if the next month has fewer days, set the day of month
3181  * to the last day of month.
3182  * To add a day, increment the mday, and use the same time of day.
3183  * Lastly, add in the "quantitative time".
3184  */
3185 static TimestampTz
3187  Interval *span,
3188  pg_tz *attimezone)
3189 {
3190  TimestampTz result;
3191  int tz;
3192 
3193  /*
3194  * Handle infinities.
3195  *
3196  * We treat anything that amounts to "infinity - infinity" as an error,
3197  * since the timestamptz type has nothing equivalent to NaN.
3198  */
3199  if (INTERVAL_IS_NOBEGIN(span))
3200  {
3202  ereport(ERROR,
3203  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3204  errmsg("timestamp out of range")));
3205  else
3206  TIMESTAMP_NOBEGIN(result);
3207  }
3208  else if (INTERVAL_IS_NOEND(span))
3209  {
3211  ereport(ERROR,
3212  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3213  errmsg("timestamp out of range")));
3214  else
3215  TIMESTAMP_NOEND(result);
3216  }
3217  else if (TIMESTAMP_NOT_FINITE(timestamp))
3218  result = timestamp;
3219  else
3220  {
3221  /* Use session timezone if caller asks for default */
3222  if (attimezone == NULL)
3223  attimezone = session_timezone;
3224 
3225  if (span->month != 0)
3226  {
3227  struct pg_tm tt,
3228  *tm = &tt;
3229  fsec_t fsec;
3230 
3231  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3232  ereport(ERROR,
3233  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3234  errmsg("timestamp out of range")));
3235 
3236  tm->tm_mon += span->month;
3237  if (tm->tm_mon > MONTHS_PER_YEAR)
3238  {
3239  tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
3240  tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
3241  }
3242  else if (tm->tm_mon < 1)
3243  {
3244  tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
3246  }
3247 
3248  /* adjust for end of month boundary problems... */
3249  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
3250  tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
3251 
3252  tz = DetermineTimeZoneOffset(tm, attimezone);
3253 
3254  if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3255  ereport(ERROR,
3256  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3257  errmsg("timestamp out of range")));
3258  }
3259 
3260  if (span->day != 0)
3261  {
3262  struct pg_tm tt,
3263  *tm = &tt;
3264  fsec_t fsec;
3265  int julian;
3266 
3267  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, attimezone) != 0)
3268  ereport(ERROR,
3269  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3270  errmsg("timestamp out of range")));
3271 
3272  /*
3273  * Add days by converting to and from Julian. We need an overflow
3274  * check here since j2date expects a non-negative integer input.
3275  * In practice though, it will give correct answers for small
3276  * negative Julian dates; we should allow -1 to avoid
3277  * timezone-dependent failures, as discussed in timestamp.h.
3278  */
3279  julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3280  if (pg_add_s32_overflow(julian, span->day, &julian) ||
3281  julian < -1)
3282  ereport(ERROR,
3283  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3284  errmsg("timestamp out of range")));
3285  j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3286 
3287  tz = DetermineTimeZoneOffset(tm, attimezone);
3288 
3289  if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
3290  ereport(ERROR,
3291  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3292  errmsg("timestamp out of range")));
3293  }
3294 
3295  timestamp += span->time;
3296 
3298  ereport(ERROR,
3299  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3300  errmsg("timestamp out of range")));
3301 
3302  result = timestamp;
3303  }
3304 
3305  return result;
3306 }
3307 
3308 /* timestamptz_mi_interval_internal()
3309  * As above, but subtract the interval.
3310  */
3311 static TimestampTz
3313  Interval *span,
3314  pg_tz *attimezone)
3315 {
3316  Interval tspan;
3317 
3318  interval_um_internal(span, &tspan);
3319 
3320  return timestamptz_pl_interval_internal(timestamp, &tspan, attimezone);
3321 }
3322 
3323 /* timestamptz_pl_interval()
3324  * Add an interval to a timestamptz, in the session timezone.
3325  */
3326 Datum
3328 {
3330  Interval *span = PG_GETARG_INTERVAL_P(1);
3331 
3333 }
3334 
3335 Datum
3337 {
3339  Interval *span = PG_GETARG_INTERVAL_P(1);
3340 
3342 }
3343 
3344 /* timestamptz_pl_interval_at_zone()
3345  * Add an interval to a timestamptz, in the specified timezone.
3346  */
3347 Datum
3349 {
3351  Interval *span = PG_GETARG_INTERVAL_P(1);
3352  text *zone = PG_GETARG_TEXT_PP(2);
3353  pg_tz *attimezone = lookup_timezone(zone);
3354 
3356 }
3357 
3358 Datum
3360 {
3362  Interval *span = PG_GETARG_INTERVAL_P(1);
3363  text *zone = PG_GETARG_TEXT_PP(2);
3364  pg_tz *attimezone = lookup_timezone(zone);
3365 
3367 }
3368 
3369 /* interval_um_internal()
3370  * Negate an interval.
3371  */
3372 static void
3374 {
3376  INTERVAL_NOEND(result);
3377  else if (INTERVAL_IS_NOEND(interval))
3378  INTERVAL_NOBEGIN(result);
3379  else
3380  {
3381  /* Negate each field, guarding against overflow */
3382  if (pg_sub_s64_overflow(INT64CONST(0), interval->time, &result->time) ||
3383  pg_sub_s32_overflow(0, interval->day, &result->day) ||
3384  pg_sub_s32_overflow(0, interval->month, &result->month) ||
3385  INTERVAL_NOT_FINITE(result))
3386  ereport(ERROR,
3387  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3388  errmsg("interval out of range")));
3389  }
3390 }
3391 
3392 Datum
3394 {
3396  Interval *result;
3397 
3398  result = (Interval *) palloc(sizeof(Interval));
3399  interval_um_internal(interval, result);
3400 
3401  PG_RETURN_INTERVAL_P(result);
3402 }
3403 
3404 
3405 Datum
3407 {
3408  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3409  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3410  Interval *result;
3411 
3412  /* use interval_cmp_internal to be sure this agrees with comparisons */
3413  if (interval_cmp_internal(interval1, interval2) < 0)
3414  result = interval1;
3415  else
3416  result = interval2;
3417  PG_RETURN_INTERVAL_P(result);
3418 }
3419 
3420 Datum
3422 {
3423  Interval *interval1 = PG_GETARG_INTERVAL_P(0);
3424  Interval *interval2 = PG_GETARG_INTERVAL_P(1);
3425  Interval *result;
3426 
3427  if (interval_cmp_internal(interval1, interval2) > 0)
3428  result = interval1;
3429  else
3430  result = interval2;
3431  PG_RETURN_INTERVAL_P(result);
3432 }
3433 
3434 static void
3435 finite_interval_pl(const Interval *span1, const Interval *span2, Interval *result)
3436 {
3437  Assert(!INTERVAL_NOT_FINITE(span1));
3438  Assert(!INTERVAL_NOT_FINITE(span2));
3439 
3440  if (pg_add_s32_overflow(span1->month, span2->month, &result->month) ||
3441  pg_add_s32_overflow(span1->day, span2->day, &result->day) ||
3442  pg_add_s64_overflow(span1->time, span2->time, &result->time) ||
3443  INTERVAL_NOT_FINITE(result))
3444  ereport(ERROR,
3445  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3446  errmsg("interval out of range")));
3447 }
3448 
3449 Datum
3451 {
3452  Interval *span1 = PG_GETARG_INTERVAL_P(0);
3453  Interval *span2 = PG_GETARG_INTERVAL_P(1);
3454  Interval *result;
3455 
3456  result = (Interval *) palloc(sizeof(Interval));
3457 
3458  /*
3459  * Handle infinities.
3460  *
3461  * We treat anything that amounts to "infinity - infinity" as an error,
3462  * since the interval type has nothing equivalent to NaN.
3463  */
3464  if (INTERVAL_IS_NOBEGIN(span1))
3465  {
3466  if (INTERVAL_IS_NOEND(span2))
3467  ereport(ERROR,
3468  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3469  errmsg("interval out of range")));
3470  else
3471  INTERVAL_NOBEGIN(result);
3472  }
3473  else if (INTERVAL_IS_NOEND(span1))
3474  {
3475  if (INTERVAL_IS_NOBEGIN(span2))
3476  ereport(ERROR,
3477  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3478  errmsg("interval out of range")));
3479  else
3480  INTERVAL_NOEND(result);
3481  }
3482  else if (INTERVAL_NOT_FINITE(span2))
3483  memcpy(result, span2, sizeof(Interval));
3484  else
3485  finite_interval_pl(span1, span2, result);
3486 
3487  PG_RETURN_INTERVAL_P(result);
3488 }
3489 
3490 static void
3491 finite_interval_mi(const Interval *span1, const Interval *span2, Interval *result)
3492 {
3493  Assert(!INTERVAL_NOT_FINITE(span1));
3494  Assert(!INTERVAL_NOT_FINITE(span2));
3495 
3496  if (pg_sub_s32_overflow(span1->month, span2->month, &result->month) ||
3497  pg_sub_s32_overflow(span1->day, span2->day, &result->day) ||
3498  pg_sub_s64_overflow(span1->time, span2->time, &result->time) ||
3499  INTERVAL_NOT_FINITE(result))
3500  ereport(ERROR,
3501  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3502  errmsg("interval out of range")));
3503 }
3504 
3505 Datum
3507 {
3508  Interval *span1 = PG_GETARG_INTERVAL_P(0);
3509  Interval *span2 = PG_GETARG_INTERVAL_P(1);
3510  Interval *result;
3511 
3512  result = (Interval *) palloc(sizeof(Interval));
3513 
3514  /*
3515  * Handle infinities.
3516  *
3517  * We treat anything that amounts to "infinity - infinity" as an error,
3518  * since the interval type has nothing equivalent to NaN.
3519  */
3520  if (INTERVAL_IS_NOBEGIN(span1))
3521  {
3522  if (INTERVAL_IS_NOBEGIN(span2))
3523  ereport(ERROR,
3524  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3525  errmsg("interval out of range")));
3526  else
3527  INTERVAL_NOBEGIN(result);
3528  }
3529  else if (INTERVAL_IS_NOEND(span1))
3530  {
3531  if (INTERVAL_IS_NOEND(span2))
3532  ereport(ERROR,
3533  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3534  errmsg("interval out of range")));
3535  else
3536  INTERVAL_NOEND(result);
3537  }
3538  else if (INTERVAL_IS_NOBEGIN(span2))
3539  INTERVAL_NOEND(result);
3540  else if (INTERVAL_IS_NOEND(span2))
3541  INTERVAL_NOBEGIN(result);
3542  else
3543  finite_interval_mi(span1, span2, result);
3544 
3545  PG_RETURN_INTERVAL_P(result);
3546 }
3547 
3548 /*
3549  * There is no interval_abs(): it is unclear what value to return:
3550  * http://archives.postgresql.org/pgsql-general/2009-10/msg01031.php
3551  * http://archives.postgresql.org/pgsql-general/2009-11/msg00041.php
3552  */
3553 
3554 Datum
3556 {
3557  Interval *span = PG_GETARG_INTERVAL_P(0);
3558  float8 factor = PG_GETARG_FLOAT8(1);
3559  double month_remainder_days,
3560  sec_remainder,
3561  result_double;
3562  int32 orig_month = span->month,
3563  orig_day = span->day;
3564  Interval *result;
3565 
3566  result = (Interval *) palloc(sizeof(Interval));
3567 
3568  /*
3569  * Handle NaN and infinities.
3570  *
3571  * We treat "0 * infinity" and "infinity * 0" as errors, since the
3572  * interval type has nothing equivalent to NaN.
3573  */
3574  if (isnan(factor))
3575  goto out_of_range;
3576 
3577  if (INTERVAL_NOT_FINITE(span))
3578  {
3579  if (factor == 0.0)
3580  goto out_of_range;
3581 
3582  if (factor < 0.0)
3583  interval_um_internal(span, result);
3584  else
3585  memcpy(result, span, sizeof(Interval));
3586 
3587  PG_RETURN_INTERVAL_P(result);
3588  }
3589  if (isinf(factor))
3590  {
3591  int isign = interval_sign(span);
3592 
3593  if (isign == 0)
3594  goto out_of_range;
3595 
3596  if (factor * isign < 0)
3597  INTERVAL_NOBEGIN(result);
3598  else
3599  INTERVAL_NOEND(result);
3600 
3601  PG_RETURN_INTERVAL_P(result);
3602  }
3603 
3604  result_double = span->month * factor;
3605  if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3606  goto out_of_range;
3607  result->month = (int32) result_double;
3608 
3609  result_double = span->day * factor;
3610  if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3611  goto out_of_range;
3612  result->day = (int32) result_double;
3613 
3614  /*
3615  * The above correctly handles the whole-number part of the month and day
3616  * products, but we have to do something with any fractional part
3617  * resulting when the factor is non-integral. We cascade the fractions
3618  * down to lower units using the conversion factors DAYS_PER_MONTH and
3619  * SECS_PER_DAY. Note we do NOT cascade up, since we are not forced to do
3620  * so by the representation. The user can choose to cascade up later,
3621  * using justify_hours and/or justify_days.
3622  */
3623 
3624  /*
3625  * Fractional months full days into days.
3626  *
3627  * Floating point calculation are inherently imprecise, so these
3628  * calculations are crafted to produce the most reliable result possible.
3629  * TSROUND() is needed to more accurately produce whole numbers where
3630  * appropriate.
3631  */
3632  month_remainder_days = (orig_month * factor - result->month) * DAYS_PER_MONTH;
3633  month_remainder_days = TSROUND(month_remainder_days);
3634  sec_remainder = (orig_day * factor - result->day +
3635  month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3636  sec_remainder = TSROUND(sec_remainder);
3637 
3638  /*
3639  * Might have 24:00:00 hours due to rounding, or >24 hours because of time
3640  * cascade from months and days. It might still be >24 if the combination
3641  * of cascade and the seconds factor operation itself.
3642  */
3643  if (fabs(sec_remainder) >= SECS_PER_DAY)
3644  {
3645  if (pg_add_s32_overflow(result->day,
3646  (int) (sec_remainder / SECS_PER_DAY),
3647  &result->day))
3648  goto out_of_range;
3649  sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3650  }
3651 
3652  /* cascade units down */
3653  if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3654  &result->day))
3655  goto out_of_range;
3656  result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
3657  if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3658  goto out_of_range;
3659  result->time = (int64) result_double;
3660 
3661  if (INTERVAL_NOT_FINITE(result))
3662  goto out_of_range;
3663 
3664  PG_RETURN_INTERVAL_P(result);
3665 
3666 out_of_range:
3667  ereport(ERROR,
3668  errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3669  errmsg("interval out of range"));
3670 
3671  PG_RETURN_NULL(); /* keep compiler quiet */
3672 }
3673 
3674 Datum
3676 {
3677  /* Args are float8 and Interval *, but leave them as generic Datum */
3678  Datum factor = PG_GETARG_DATUM(0);
3679  Datum span = PG_GETARG_DATUM(1);
3680 
3681  return DirectFunctionCall2(interval_mul, span, factor);
3682 }
3683 
3684 Datum
3686 {
3687  Interval *span = PG_GETARG_INTERVAL_P(0);
3688  float8 factor = PG_GETARG_FLOAT8(1);
3689  double month_remainder_days,
3690  sec_remainder,
3691  result_double;
3692  int32 orig_month = span->month,
3693  orig_day = span->day;
3694  Interval *result;
3695 
3696  result = (Interval *) palloc(sizeof(Interval));
3697 
3698  if (factor == 0.0)
3699  ereport(ERROR,
3700  (errcode(ERRCODE_DIVISION_BY_ZERO),
3701  errmsg("division by zero")));
3702 
3703  /*
3704  * Handle NaN and infinities.
3705  *
3706  * We treat "infinity / infinity" as an error, since the interval type has
3707  * nothing equivalent to NaN. Otherwise, dividing by infinity is handled
3708  * by the regular division code, causing all fields to be set to zero.
3709  */
3710  if (isnan(factor))
3711  goto out_of_range;
3712 
3713  if (INTERVAL_NOT_FINITE(span))
3714  {
3715  if (isinf(factor))
3716  goto out_of_range;
3717 
3718  if (factor < 0.0)
3719  interval_um_internal(span, result);
3720  else
3721  memcpy(result, span, sizeof(Interval));
3722 
3723  PG_RETURN_INTERVAL_P(result);
3724  }
3725 
3726  result_double = span->month / factor;
3727  if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3728  goto out_of_range;
3729  result->month = (int32) result_double;
3730 
3731  result_double = span->day / factor;
3732  if (isnan(result_double) || !FLOAT8_FITS_IN_INT32(result_double))
3733  goto out_of_range;
3734  result->day = (int32) result_double;
3735 
3736  /*
3737  * Fractional months full days into days. See comment in interval_mul().
3738  */
3739  month_remainder_days = (orig_month / factor - result->month) * DAYS_PER_MONTH;
3740  month_remainder_days = TSROUND(month_remainder_days);
3741  sec_remainder = (orig_day / factor - result->day +
3742  month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
3743  sec_remainder = TSROUND(sec_remainder);
3744  if (fabs(sec_remainder) >= SECS_PER_DAY)
3745  {
3746  if (pg_add_s32_overflow(result->day,
3747  (int) (sec_remainder / SECS_PER_DAY),
3748  &result->day))
3749  goto out_of_range;
3750  sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
3751  }
3752 
3753  /* cascade units down */
3754  if (pg_add_s32_overflow(result->day, (int32) month_remainder_days,
3755  &result->day))
3756  goto out_of_range;
3757  result_double = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
3758  if (isnan(result_double) || !FLOAT8_FITS_IN_INT64(result_double))
3759  goto out_of_range;
3760  result->time = (int64) result_double;
3761 
3762  if (INTERVAL_NOT_FINITE(result))
3763  goto out_of_range;
3764 
3765  PG_RETURN_INTERVAL_P(result);
3766 
3767 out_of_range:
3768  ereport(ERROR,
3769  errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3770  errmsg("interval out of range"));
3771 
3772  PG_RETURN_NULL(); /* keep compiler quiet */
3773 }
3774 
3775 
3776 /*
3777  * in_range support functions for timestamps and intervals.
3778  *
3779  * Per SQL spec, we support these with interval as the offset type.
3780  * The spec's restriction that the offset not be negative is a bit hard to
3781  * decipher for intervals, but we choose to interpret it the same as our
3782  * interval comparison operators would.
3783  */
3784 
3785 Datum
3787 {
3790  Interval *offset = PG_GETARG_INTERVAL_P(2);
3791  bool sub = PG_GETARG_BOOL(3);
3792  bool less = PG_GETARG_BOOL(4);
3793  TimestampTz sum;
3794 
3795  if (interval_sign(offset) < 0)
3796  ereport(ERROR,
3797  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3798  errmsg("invalid preceding or following size in window function")));
3799 
3800  /*
3801  * Deal with cases where both base and offset are infinite, and computing
3802  * base +/- offset would cause an error. As for float and numeric types,
3803  * we assume that all values infinitely precede +infinity and infinitely
3804  * follow -infinity. See in_range_float8_float8() for reasoning.
3805  */
3806  if (INTERVAL_IS_NOEND(offset) &&
3807  (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3808  PG_RETURN_BOOL(true);
3809 
3810  /* We don't currently bother to avoid overflow hazards here */
3811  if (sub)
3812  sum = timestamptz_mi_interval_internal(base, offset, NULL);
3813  else
3814  sum = timestamptz_pl_interval_internal(base, offset, NULL);
3815 
3816  if (less)
3817  PG_RETURN_BOOL(val <= sum);
3818  else
3819  PG_RETURN_BOOL(val >= sum);
3820 }
3821 
3822 Datum
3824 {
3826  Timestamp base = PG_GETARG_TIMESTAMP(1);
3827  Interval *offset = PG_GETARG_INTERVAL_P(2);
3828  bool sub = PG_GETARG_BOOL(3);
3829  bool less = PG_GETARG_BOOL(4);
3830  Timestamp sum;
3831 
3832  if (interval_sign(offset) < 0)
3833  ereport(ERROR,
3834  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3835  errmsg("invalid preceding or following size in window function")));
3836 
3837  /*
3838  * Deal with cases where both base and offset are infinite, and computing
3839  * base +/- offset would cause an error. As for float and numeric types,
3840  * we assume that all values infinitely precede +infinity and infinitely
3841  * follow -infinity. See in_range_float8_float8() for reasoning.
3842  */
3843  if (INTERVAL_IS_NOEND(offset) &&
3844  (sub ? TIMESTAMP_IS_NOEND(base) : TIMESTAMP_IS_NOBEGIN(base)))
3845  PG_RETURN_BOOL(true);
3846 
3847  /* We don't currently bother to avoid overflow hazards here */
3848  if (sub)
3850  TimestampGetDatum(base),
3851  IntervalPGetDatum(offset)));
3852  else
3854  TimestampGetDatum(base),
3855  IntervalPGetDatum(offset)));
3856 
3857  if (less)
3858  PG_RETURN_BOOL(val <= sum);
3859  else
3860  PG_RETURN_BOOL(val >= sum);
3861 }
3862 
3863 Datum
3865 {
3867  Interval *base = PG_GETARG_INTERVAL_P(1);
3868  Interval *offset = PG_GETARG_INTERVAL_P(2);
3869  bool sub = PG_GETARG_BOOL(3);
3870  bool less = PG_GETARG_BOOL(4);
3871  Interval *sum;
3872 
3873  if (interval_sign(offset) < 0)
3874  ereport(ERROR,
3875  (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
3876  errmsg("invalid preceding or following size in window function")));
3877 
3878  /*
3879  * Deal with cases where both base and offset are infinite, and computing
3880  * base +/- offset would cause an error. As for float and numeric types,
3881  * we assume that all values infinitely precede +infinity and infinitely
3882  * follow -infinity. See in_range_float8_float8() for reasoning.
3883  */
3884  if (INTERVAL_IS_NOEND(offset) &&
3885  (sub ? INTERVAL_IS_NOEND(base) : INTERVAL_IS_NOBEGIN(base)))
3886  PG_RETURN_BOOL(true);
3887 
3888  /* We don't currently bother to avoid overflow hazards here */
3889  if (sub)
3891  IntervalPGetDatum(base),
3892  IntervalPGetDatum(offset)));
3893  else
3895  IntervalPGetDatum(base),
3896  IntervalPGetDatum(offset)));
3897 
3898  if (less)
3900  else
3902 }
3903 
3904 
3905 /*
3906  * Prepare state data for an interval aggregate function, that needs to compute
3907  * sum and count, in the aggregate's memory context.
3908  *
3909  * The function is used when the state data needs to be allocated in aggregate's
3910  * context. When the state data needs to be allocated in the current memory
3911  * context, we use palloc0 directly e.g. interval_avg_deserialize().
3912  */
3913 static IntervalAggState *
3915 {
3917  MemoryContext agg_context;
3918  MemoryContext old_context;
3919 
3920  if (!AggCheckCallContext(fcinfo, &agg_context))
3921  elog(ERROR, "aggregate function called in non-aggregate context");
3922 
3923  old_context = MemoryContextSwitchTo(agg_context);
3924 
3926 
3927  MemoryContextSwitchTo(old_context);
3928 
3929  return state;
3930 }
3931 
3932 /*
3933  * Accumulate a new input value for interval aggregate functions.
3934  */
3935 static void
3937 {
3938  /* Infinite inputs are counted separately, and do not affect "N" */
3940  {
3941  state->nInfcount++;
3942  return;
3943  }
3944 
3946  {
3947  state->pInfcount++;
3948  return;
3949  }
3950 
3951  finite_interval_pl(&state->sumX, newval, &state->sumX);
3952  state->N++;
3953 }
3954 
3955 /*
3956  * Remove the given interval value from the aggregated state.
3957  */
3958 static void
3960 {
3961  /* Infinite inputs are counted separately, and do not affect "N" */
3963  {
3964  state->nInfcount--;
3965  return;
3966  }
3967 
3969  {
3970  state->pInfcount--;
3971  return;
3972  }
3973 
3974  /* Handle the to-be-discarded finite value. */
3975  state->N--;
3976  if (state->N > 0)
3977  finite_interval_mi(&state->sumX, newval, &state->sumX);
3978  else
3979  {
3980  /* All values discarded, reset the state */
3981  Assert(state->N == 0);
3982  memset(&state->sumX, 0, sizeof(state->sumX));
3983  }
3984 }
3985 
3986 /*
3987  * Transition function for sum() and avg() interval aggregates.
3988  */
3989 Datum
3991 {
3993 
3995 
3996  /* Create the state data on the first call */
3997  if (state == NULL)
3998  state = makeIntervalAggState(fcinfo);
3999 
4000  if (!PG_ARGISNULL(1))
4002 
4004 }
4005 
4006 /*
4007  * Combine function for sum() and avg() interval aggregates.
4008  *
4009  * Combine the given internal aggregate states and place the combination in
4010  * the first argument.
4011  */
4012 Datum
4014 {
4015  IntervalAggState *state1;
4016  IntervalAggState *state2;
4017 
4018  state1 = PG_ARGISNULL(0) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(0);
4019  state2 = PG_ARGISNULL(1) ? NULL : (IntervalAggState *) PG_GETARG_POINTER(1);
4020 
4021  if (state2 == NULL)
4022  PG_RETURN_POINTER(state1);
4023 
4024  if (state1 == NULL)
4025  {
4026  /* manually copy all fields from state2 to state1 */
4027  state1 = makeIntervalAggState(fcinfo);
4028 
4029  state1->N = state2->N;
4030  state1->pInfcount = state2->pInfcount;
4031  state1->nInfcount = state2->nInfcount;
4032 
4033  state1->sumX.day = state2->sumX.day;
4034  state1->sumX.month = state2->sumX.month;
4035  state1->sumX.time = state2->sumX.time;
4036 
4037  PG_RETURN_POINTER(state1);
4038  }
4039 
4040  state1->N += state2->N;
4041  state1->pInfcount += state2->pInfcount;
4042  state1->nInfcount += state2->nInfcount;
4043 
4044  /* Accumulate finite interval values, if any. */
4045  if (state2->N > 0)
4046  finite_interval_pl(&state1->sumX, &state2->sumX, &state1->sumX);
4047 
4048  PG_RETURN_POINTER(state1);
4049 }
4050 
4051 /*
4052  * interval_avg_serialize
4053  * Serialize IntervalAggState for interval aggregates.
4054  */
4055 Datum
4057 {
4060  bytea *result;
4061 
4062  /* Ensure we disallow calling when not in aggregate context */
4063  if (!AggCheckCallContext(fcinfo, NULL))
4064  elog(ERROR, "aggregate function called in non-aggregate context");
4065 
4067 
4068  pq_begintypsend(&buf);
4069 
4070  /* N */
4071  pq_sendint64(&buf, state->N);
4072 
4073  /* sumX */
4074  pq_sendint64(&buf, state->sumX.time);
4075  pq_sendint32(&buf, state->sumX.day);
4076  pq_sendint32(&buf, state->sumX.month);
4077 
4078  /* pInfcount */
4079  pq_sendint64(&buf, state->pInfcount);
4080 
4081  /* nInfcount */
4082  pq_sendint64(&buf, state->nInfcount);
4083 
4084  result = pq_endtypsend(&buf);
4085 
4086  PG_RETURN_BYTEA_P(result);
4087 }
4088 
4089 /*
4090  * interval_avg_deserialize
4091  * Deserialize bytea into IntervalAggState for interval aggregates.
4092  */
4093 Datum
4095 {
4096  bytea *sstate;
4097  IntervalAggState *result;
4099 
4100  if (!AggCheckCallContext(fcinfo, NULL))
4101  elog(ERROR, "aggregate function called in non-aggregate context");
4102 
4103  sstate = PG_GETARG_BYTEA_PP(0);
4104 
4105  /*
4106  * Initialize a StringInfo so that we can "receive" it using the standard
4107  * recv-function infrastructure.
4108  */
4110  VARSIZE_ANY_EXHDR(sstate));
4111 
4112  result = (IntervalAggState *) palloc0(sizeof(IntervalAggState));
4113 
4114  /* N */
4115  result->N = pq_getmsgint64(&buf);
4116 
4117  /* sumX */
4118  result->sumX.time = pq_getmsgint64(&buf);
4119  result->sumX.day = pq_getmsgint(&buf, 4);
4120  result->sumX.month = pq_getmsgint(&buf, 4);
4121 
4122  /* pInfcount */
4123  result->pInfcount = pq_getmsgint64(&buf);
4124 
4125  /* nInfcount */
4126  result->nInfcount = pq_getmsgint64(&buf);
4127 
4128  pq_getmsgend(&buf);
4129 
4130  PG_RETURN_POINTER(result);
4131 }
4132 
4133 /*
4134  * Inverse transition function for sum() and avg() interval aggregates.
4135  */
4136 Datum
4138 {
4140 
4142 
4143  /* Should not get here with no state */
4144  if (state == NULL)
4145  elog(ERROR, "interval_avg_accum_inv called with NULL state");
4146 
4147  if (!PG_ARGISNULL(1))
4149 
4151 }
4152 
4153 /* avg(interval) aggregate final function */
4154 Datum
4156 {
4158 
4160 
4161  /* If there were no non-null inputs, return NULL */
4162  if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4163  PG_RETURN_NULL();
4164 
4165  /*
4166  * Aggregating infinities that all have the same sign produces infinity
4167  * with that sign. Aggregating infinities with different signs results in
4168  * an error.
4169  */
4170  if (state->pInfcount > 0 || state->nInfcount > 0)
4171  {
4172  Interval *result;
4173 
4174  if (state->pInfcount > 0 && state->nInfcount > 0)
4175  ereport(ERROR,
4176  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4177  errmsg("interval out of range.")));
4178 
4179  result = (Interval *) palloc(sizeof(Interval));
4180  if (state->pInfcount > 0)
4181  INTERVAL_NOEND(result);
4182  else
4183  INTERVAL_NOBEGIN(result);
4184 
4185  PG_RETURN_INTERVAL_P(result);
4186  }
4187 
4189  IntervalPGetDatum(&state->sumX),
4190  Float8GetDatum((double) state->N));
4191 }
4192 
4193 /* sum(interval) aggregate final function */
4194 Datum
4196 {
4198  Interval *result;
4199 
4201 
4202  /* If there were no non-null inputs, return NULL */
4203  if (state == NULL || IA_TOTAL_COUNT(state) == 0)
4204  PG_RETURN_NULL();
4205 
4206  /*
4207  * Aggregating infinities that all have the same sign produces infinity
4208  * with that sign. Aggregating infinities with different signs results in
4209  * an error.
4210  */
4211  if (state->pInfcount > 0 && state->nInfcount > 0)
4212  ereport(ERROR,
4213  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4214  errmsg("interval out of range.")));
4215 
4216  result = (Interval *) palloc(sizeof(Interval));
4217 
4218  if (state->pInfcount > 0)
4219  INTERVAL_NOEND(result);
4220  else if (state->nInfcount > 0)
4221  INTERVAL_NOBEGIN(result);
4222  else
4223  memcpy(result, &state->sumX, sizeof(Interval));
4224 
4225  PG_RETURN_INTERVAL_P(result);
4226 }
4227 
4228 /* timestamp_age()
4229  * Calculate time difference while retaining year/month fields.
4230  * Note that this does not result in an accurate absolute time span
4231  * since year and month are out of context once the arithmetic
4232  * is done.
4233  */
4234 Datum
4236 {
4237  Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
4238  Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
4239  Interval *result;
4240  fsec_t fsec1,
4241  fsec2;
4242  struct pg_itm tt,
4243  *tm = &tt;
4244  struct pg_tm tt1,
4245  *tm1 = &tt1;
4246  struct pg_tm tt2,
4247  *tm2 = &tt2;
4248 
4249  result = (Interval *) palloc(sizeof(Interval));
4250 
4251  /*
4252  * Handle infinities.
4253  *
4254  * We treat anything that amounts to "infinity - infinity" as an error,
4255  * since the interval type has nothing equivalent to NaN.
4256  */
4257  if (TIMESTAMP_IS_NOBEGIN(dt1))
4258  {
4259  if (TIMESTAMP_IS_NOBEGIN(dt2))
4260  ereport(ERROR,
4261  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4262  errmsg("interval out of range")));
4263  else
4264  INTERVAL_NOBEGIN(result);
4265  }
4266  else if (TIMESTAMP_IS_NOEND(dt1))
4267  {
4268  if (TIMESTAMP_IS_NOEND(dt2))
4269  ereport(ERROR,
4270  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4271  errmsg("interval out of range")));
4272  else
4273  INTERVAL_NOEND(result);
4274  }
4275  else if (TIMESTAMP_IS_NOBEGIN(dt2))
4276  INTERVAL_NOEND(result);
4277  else if (TIMESTAMP_IS_NOEND(dt2))
4278  INTERVAL_NOBEGIN(result);
4279  else if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
4280  timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
4281  {
4282  /* form the symbolic difference */
4283  tm->tm_usec = fsec1 - fsec2;
4284  tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4285  tm->tm_min = tm1->tm_min - tm2->tm_min;
4286  tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4287  tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4288  tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4289  tm->tm_year = tm1->tm_year - tm2->tm_year;
4290 
4291  /* flip sign if necessary... */
4292  if (dt1 < dt2)
4293  {
4294  tm->tm_usec = -tm->tm_usec;
4295  tm->tm_sec = -tm->tm_sec;
4296  tm->tm_min = -tm->tm_min;
4297  tm->tm_hour = -tm->tm_hour;
4298  tm->tm_mday = -tm->tm_mday;
4299  tm->tm_mon = -tm->tm_mon;
4300  tm->tm_year = -tm->tm_year;
4301  }
4302 
4303  /* propagate any negative fields into the next higher field */
4304  while (tm->tm_usec < 0)
4305  {
4306  tm->tm_usec += USECS_PER_SEC;
4307  tm->tm_sec--;
4308  }
4309 
4310  while (tm->tm_sec < 0)
4311  {
4313  tm->tm_min--;
4314  }
4315 
4316  while (tm->tm_min < 0)
4317  {
4318  tm->tm_min += MINS_PER_HOUR;
4319  tm->tm_hour--;
4320  }
4321 
4322  while (tm->tm_hour < 0)
4323  {
4324  tm->tm_hour += HOURS_PER_DAY;
4325  tm->tm_mday--;
4326  }
4327 
4328  while (tm->tm_mday < 0)
4329  {
4330  if (dt1 < dt2)
4331  {
4332  tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4333  tm->tm_mon--;
4334  }
4335  else
4336  {
4337  tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4338  tm->tm_mon--;
4339  }
4340  }
4341 
4342  while (tm->tm_mon < 0)
4343  {
4345  tm->tm_year--;
4346  }
4347 
4348  /* recover sign if necessary... */
4349  if (dt1 < dt2)
4350  {
4351  tm->tm_usec = -tm->tm_usec;
4352  tm->tm_sec = -tm->tm_sec;
4353  tm->tm_min = -tm->tm_min;
4354  tm->tm_hour = -tm->tm_hour;
4355  tm->tm_mday = -tm->tm_mday;
4356  tm->tm_mon = -tm->tm_mon;
4357  tm->tm_year = -tm->tm_year;
4358  }
4359 
4360  if (itm2interval(tm, result) != 0)
4361  ereport(ERROR,
4362  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4363  errmsg("interval out of range")));
4364  }
4365  else
4366  ereport(ERROR,
4367  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4368  errmsg("timestamp out of range")));
4369 
4370  PG_RETURN_INTERVAL_P(result);
4371 }
4372 
4373 
4374 /* timestamptz_age()
4375  * Calculate time difference while retaining year/month fields.
4376  * Note that this does not result in an accurate absolute time span
4377  * since year and month are out of context once the arithmetic
4378  * is done.
4379  */
4380 Datum
4382 {
4385  Interval *result;
4386  fsec_t fsec1,
4387  fsec2;
4388  struct pg_itm tt,
4389  *tm = &tt;
4390  struct pg_tm tt1,
4391  *tm1 = &tt1;
4392  struct pg_tm tt2,
4393  *tm2 = &tt2;
4394  int tz1;
4395  int tz2;
4396 
4397  result = (Interval *) palloc(sizeof(Interval));
4398 
4399  /*
4400  * Handle infinities.
4401  *
4402  * We treat anything that amounts to "infinity - infinity" as an error,
4403  * since the interval type has nothing equivalent to NaN.
4404  */
4405  if (TIMESTAMP_IS_NOBEGIN(dt1))
4406  {
4407  if (TIMESTAMP_IS_NOBEGIN(dt2))
4408  ereport(ERROR,
4409  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4410  errmsg("interval out of range")));
4411  else
4412  INTERVAL_NOBEGIN(result);
4413  }
4414  else if (TIMESTAMP_IS_NOEND(dt1))
4415  {
4416  if (TIMESTAMP_IS_NOEND(dt2))
4417  ereport(ERROR,
4418  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4419  errmsg("interval out of range")));
4420  else
4421  INTERVAL_NOEND(result);
4422  }
4423  else if (TIMESTAMP_IS_NOBEGIN(dt2))
4424  INTERVAL_NOEND(result);
4425  else if (TIMESTAMP_IS_NOEND(dt2))
4426  INTERVAL_NOBEGIN(result);
4427  else if (timestamp2tm(dt1, &tz1, tm1, &fsec1, NULL, NULL) == 0 &&
4428  timestamp2tm(dt2, &tz2, tm2, &fsec2, NULL, NULL) == 0)
4429  {
4430  /* form the symbolic difference */
4431  tm->tm_usec = fsec1 - fsec2;
4432  tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
4433  tm->tm_min = tm1->tm_min - tm2->tm_min;
4434  tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
4435  tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
4436  tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
4437  tm->tm_year = tm1->tm_year - tm2->tm_year;
4438 
4439  /* flip sign if necessary... */
4440  if (dt1 < dt2)
4441  {
4442  tm->tm_usec = -tm->tm_usec;
4443  tm->tm_sec = -tm->tm_sec;
4444  tm->tm_min = -tm->tm_min;
4445  tm->tm_hour = -tm->tm_hour;
4446  tm->tm_mday = -tm->tm_mday;
4447  tm->tm_mon = -tm->tm_mon;
4448  tm->tm_year = -tm->tm_year;
4449  }
4450 
4451  /* propagate any negative fields into the next higher field */
4452  while (tm->tm_usec < 0)
4453  {
4454  tm->tm_usec += USECS_PER_SEC;
4455  tm->tm_sec--;
4456  }
4457 
4458  while (tm->tm_sec < 0)
4459  {
4461  tm->tm_min--;
4462  }
4463 
4464  while (tm->tm_min < 0)
4465  {
4466  tm->tm_min += MINS_PER_HOUR;
4467  tm->tm_hour--;
4468  }
4469 
4470  while (tm->tm_hour < 0)
4471  {
4472  tm->tm_hour += HOURS_PER_DAY;
4473  tm->tm_mday--;
4474  }
4475 
4476  while (tm->tm_mday < 0)
4477  {
4478  if (dt1 < dt2)
4479  {
4480  tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
4481  tm->tm_mon--;
4482  }
4483  else
4484  {
4485  tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
4486  tm->tm_mon--;
4487  }
4488  }
4489 
4490  while (tm->tm_mon < 0)
4491  {
4493  tm->tm_year--;
4494  }
4495 
4496  /*
4497  * Note: we deliberately ignore any difference between tz1 and tz2.
4498  */
4499 
4500  /* recover sign if necessary... */
4501  if (dt1 < dt2)
4502  {
4503  tm->tm_usec = -tm->tm_usec;
4504  tm->tm_sec = -tm->tm_sec;
4505  tm->tm_min = -tm->tm_min;
4506  tm->tm_hour = -tm->tm_hour;
4507  tm->tm_mday = -tm->tm_mday;
4508  tm->tm_mon = -tm->tm_mon;
4509  tm->tm_year = -tm->tm_year;
4510  }
4511 
4512  if (itm2interval(tm, result) != 0)
4513  ereport(ERROR,
4514  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4515  errmsg("interval out of range")));
4516  }
4517  else
4518  ereport(ERROR,
4519  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4520  errmsg("timestamp out of range")));
4521 
4522  PG_RETURN_INTERVAL_P(result);
4523 }
4524 
4525 
4526 /*----------------------------------------------------------
4527  * Conversion operators.
4528  *---------------------------------------------------------*/
4529 
4530 
4531 /* timestamp_bin()
4532  * Bin timestamp into specified interval.
4533  */
4534 Datum
4536 {
4537  Interval *stride = PG_GETARG_INTERVAL_P(0);
4539  Timestamp origin = PG_GETARG_TIMESTAMP(2);
4540  Timestamp result,
4541  stride_usecs,
4542  tm_diff,
4543  tm_modulo,
4544  tm_delta;
4545 
4548 
4549  if (TIMESTAMP_NOT_FINITE(origin))
4550  ereport(ERROR,
4551  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4552  errmsg("origin out of range")));
4553 
4554  if (INTERVAL_NOT_FINITE(stride))
4555  ereport(ERROR,
4556  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4557  errmsg("timestamps cannot be binned into infinite intervals")));
4558 
4559  if (stride->month != 0)
4560  ereport(ERROR,
4561  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4562  errmsg("timestamps cannot be binned into intervals containing months or years")));
4563 
4564  if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4565  unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4566  ereport(ERROR,
4567  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4568  errmsg("interval out of range")));
4569 
4570  if (stride_usecs <= 0)
4571  ereport(ERROR,
4572  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4573  errmsg("stride must be greater than zero")));
4574 
4575  if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4576  ereport(ERROR,
4577  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4578  errmsg("interval out of range")));
4579 
4580  /* These calculations cannot overflow */
4581  tm_modulo = tm_diff % stride_usecs;
4582  tm_delta = tm_diff - tm_modulo;
4583  result = origin + tm_delta;
4584 
4585  /*
4586  * We want to round towards -infinity, not 0, when tm_diff is negative and
4587  * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4588  * since the result might now be out of the range origin .. timestamp.
4589  */
4590  if (tm_modulo < 0)
4591  {
4592  if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4593  !IS_VALID_TIMESTAMP(result))
4594  ereport(ERROR,
4595  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4596  errmsg("timestamp out of range")));
4597  }
4598 
4599  PG_RETURN_TIMESTAMP(result);
4600 }
4601 
4602 /* timestamp_trunc()
4603  * Truncate timestamp to specified units.
4604  */
4605 Datum
4607 {
4608  text *units = PG_GETARG_TEXT_PP(0);
4610  Timestamp result;
4611  int type,
4612  val;
4613  char *lowunits;
4614  fsec_t fsec;
4615  struct pg_tm tt,
4616  *tm = &tt;
4617 
4620 
4621  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4622  VARSIZE_ANY_EXHDR(units),
4623  false);
4624 
4625  type = DecodeUnits(0, lowunits, &val);
4626 
4627  if (type == UNITS)
4628  {
4629  if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
4630  ereport(ERROR,
4631  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4632  errmsg("timestamp out of range")));
4633 
4634  switch (val)
4635  {
4636  case DTK_WEEK:
4637  {
4638  int woy;
4639 
4640  woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
4641 
4642  /*
4643  * If it is week 52/53 and the month is January, then the
4644  * week must belong to the previous year. Also, some
4645  * December dates belong to the next year.
4646  */
4647  if (woy >= 52 && tm->tm_mon == 1)
4648  --tm->tm_year;
4649  if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4650  ++tm->tm_year;
4651  isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4652  tm->tm_hour = 0;
4653  tm->tm_min = 0;
4654  tm->tm_sec = 0;
4655  fsec = 0;
4656  break;
4657  }
4658  case DTK_MILLENNIUM:
4659  /* see comments in timestamptz_trunc */
4660  if (tm->tm_year > 0)
4661  tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
4662  else
4663  tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
4664  /* FALL THRU */
4665  case DTK_CENTURY:
4666  /* see comments in timestamptz_trunc */
4667  if (tm->tm_year > 0)
4668  tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
4669  else
4670  tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
4671  /* FALL THRU */
4672  case DTK_DECADE:
4673  /* see comments in timestamptz_trunc */
4674  if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
4675  {
4676  if (tm->tm_year > 0)
4677  tm->tm_year = (tm->tm_year / 10) * 10;
4678  else
4679  tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
4680  }
4681  /* FALL THRU */
4682  case DTK_YEAR:
4683  tm->tm_mon = 1;
4684  /* FALL THRU */
4685  case DTK_QUARTER:
4686  tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
4687  /* FALL THRU */
4688  case DTK_MONTH:
4689  tm->tm_mday = 1;
4690  /* FALL THRU */
4691  case DTK_DAY:
4692  tm->tm_hour = 0;
4693  /* FALL THRU */
4694  case DTK_HOUR:
4695  tm->tm_min = 0;
4696  /* FALL THRU */
4697  case DTK_MINUTE:
4698  tm->tm_sec = 0;
4699  /* FALL THRU */
4700  case DTK_SECOND:
4701  fsec = 0;
4702  break;
4703 
4704  case DTK_MILLISEC:
4705  fsec = (fsec / 1000) * 1000;
4706  break;
4707 
4708  case DTK_MICROSEC:
4709  break;
4710 
4711  default:
4712  ereport(ERROR,
4713  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4714  errmsg("unit \"%s\" not supported for type %s",
4715  lowunits, format_type_be(TIMESTAMPOID))));
4716  result = 0;
4717  }
4718 
4719  if (tm2timestamp(tm, fsec, NULL, &result) != 0)
4720  ereport(ERROR,
4721  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4722  errmsg("timestamp out of range")));
4723  }
4724  else
4725  {
4726  ereport(ERROR,
4727  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4728  errmsg("unit \"%s\" not recognized for type %s",
4729  lowunits, format_type_be(TIMESTAMPOID))));
4730  result = 0;
4731  }
4732 
4733  PG_RETURN_TIMESTAMP(result);
4734 }
4735 
4736 /* timestamptz_bin()
4737  * Bin timestamptz into specified interval using specified origin.
4738  */
4739 Datum
4741 {
4742  Interval *stride = PG_GETARG_INTERVAL_P(0);
4744  TimestampTz origin = PG_GETARG_TIMESTAMPTZ(2);
4745  TimestampTz result,
4746  stride_usecs,
4747  tm_diff,
4748  tm_modulo,
4749  tm_delta;
4750 
4753 
4754  if (TIMESTAMP_NOT_FINITE(origin))
4755  ereport(ERROR,
4756  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4757  errmsg("origin out of range")));
4758 
4759  if (INTERVAL_NOT_FINITE(stride))
4760  ereport(ERROR,
4761  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4762  errmsg("timestamps cannot be binned into infinite intervals")));
4763 
4764  if (stride->month != 0)
4765  ereport(ERROR,
4766  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4767  errmsg("timestamps cannot be binned into intervals containing months or years")));
4768 
4769  if (unlikely(pg_mul_s64_overflow(stride->day, USECS_PER_DAY, &stride_usecs)) ||
4770  unlikely(pg_add_s64_overflow(stride_usecs, stride->time, &stride_usecs)))
4771  ereport(ERROR,
4772  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4773  errmsg("interval out of range")));
4774 
4775  if (stride_usecs <= 0)
4776  ereport(ERROR,
4777  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4778  errmsg("stride must be greater than zero")));
4779 
4780  if (unlikely(pg_sub_s64_overflow(timestamp, origin, &tm_diff)))
4781  ereport(ERROR,
4782  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4783  errmsg("interval out of range")));
4784 
4785  /* These calculations cannot overflow */
4786  tm_modulo = tm_diff % stride_usecs;
4787  tm_delta = tm_diff - tm_modulo;
4788  result = origin + tm_delta;
4789 
4790  /*
4791  * We want to round towards -infinity, not 0, when tm_diff is negative and
4792  * not a multiple of stride_usecs. This adjustment *can* cause overflow,
4793  * since the result might now be out of the range origin .. timestamp.
4794  */
4795  if (tm_modulo < 0)
4796  {
4797  if (unlikely(pg_sub_s64_overflow(result, stride_usecs, &result)) ||
4798  !IS_VALID_TIMESTAMP(result))
4799  ereport(ERROR,
4800  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4801  errmsg("timestamp out of range")));
4802  }
4803 
4804  PG_RETURN_TIMESTAMPTZ(result);
4805 }
4806 
4807 /*
4808  * Common code for timestamptz_trunc() and timestamptz_trunc_zone().
4809  *
4810  * tzp identifies the zone to truncate with respect to. We assume
4811  * infinite timestamps have already been rejected.
4812  */
4813 static TimestampTz
4815 {
4816  TimestampTz result;
4817  int tz;
4818  int type,
4819  val;
4820  bool redotz = false;
4821  char *lowunits;
4822  fsec_t fsec;
4823  struct pg_tm tt,
4824  *tm = &tt;
4825 
4826  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
4827  VARSIZE_ANY_EXHDR(units),
4828  false);
4829 
4830  type = DecodeUnits(0, lowunits, &val);
4831 
4832  if (type == UNITS)
4833  {
4834  if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0)
4835  ereport(ERROR,
4836  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4837  errmsg("timestamp out of range")));
4838 
4839  switch (val)
4840  {
4841  case DTK_WEEK:
4842  {
4843  int woy;
4844 
4845  woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
4846 
4847  /*
4848  * If it is week 52/53 and the month is January, then the
4849  * week must belong to the previous year. Also, some
4850  * December dates belong to the next year.
4851  */
4852  if (woy >= 52 && tm->tm_mon == 1)
4853  --tm->tm_year;
4854  if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
4855  ++tm->tm_year;
4856  isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
4857  tm->tm_hour = 0;
4858  tm->tm_min = 0;
4859  tm->tm_sec = 0;
4860  fsec = 0;
4861  redotz = true;
4862  break;
4863  }
4864  /* one may consider DTK_THOUSAND and DTK_HUNDRED... */
4865  case DTK_MILLENNIUM:
4866 
4867  /*
4868  * truncating to the millennium? what is this supposed to
4869  * mean? let us put the first year of the millennium... i.e.
4870  * -1000, 1, 1001, 2001...
4871  */
4872  if (tm->tm_year > 0)
4873  tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
4874  else
4875  tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
4876  /* FALL THRU */
4877  case DTK_CENTURY:
4878  /* truncating to the century? as above: -100, 1, 101... */
4879  if (tm->tm_year > 0)
4880  tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
4881  else
4882  tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
4883  /* FALL THRU */
4884  case DTK_DECADE:
4885 
4886  /*
4887  * truncating to the decade? first year of the decade. must
4888  * not be applied if year was truncated before!
4889  */
4890  if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
4891  {
4892  if (tm->tm_year > 0)
4893  tm->tm_year = (tm->tm_year / 10) * 10;
4894  else
4895  tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
4896  }
4897  /* FALL THRU */
4898  case DTK_YEAR:
4899  tm->tm_mon = 1;
4900  /* FALL THRU */
4901  case DTK_QUARTER:
4902  tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
4903  /* FALL THRU */
4904  case DTK_MONTH:
4905  tm->tm_mday = 1;
4906  /* FALL THRU */
4907  case DTK_DAY:
4908  tm->tm_hour = 0;
4909  redotz = true; /* for all cases >= DAY */
4910  /* FALL THRU */
4911  case DTK_HOUR:
4912  tm->tm_min = 0;
4913  /* FALL THRU */
4914  case DTK_MINUTE:
4915  tm->tm_sec = 0;
4916  /* FALL THRU */
4917  case DTK_SECOND:
4918  fsec = 0;
4919  break;
4920  case DTK_MILLISEC:
4921  fsec = (fsec / 1000) * 1000;
4922  break;
4923  case DTK_MICROSEC:
4924  break;
4925 
4926  default:
4927  ereport(ERROR,
4928  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4929  errmsg("unit \"%s\" not supported for type %s",
4930  lowunits, format_type_be(TIMESTAMPTZOID))));
4931  result = 0;
4932  }
4933 
4934  if (redotz)
4935  tz = DetermineTimeZoneOffset(tm, tzp);
4936 
4937  if (tm2timestamp(tm, fsec, &tz, &result) != 0)
4938  ereport(ERROR,
4939  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4940  errmsg("timestamp out of range")));
4941  }
4942  else
4943  {
4944  ereport(ERROR,
4945  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4946  errmsg("unit \"%s\" not recognized for type %s",
4947  lowunits, format_type_be(TIMESTAMPTZOID))));
4948  result = 0;
4949  }
4950 
4951  return result;
4952 }
4953 
4954 /* timestamptz_trunc()
4955  * Truncate timestamptz to specified units in session timezone.
4956  */
4957 Datum
4959 {
4960  text *units = PG_GETARG_TEXT_PP(0);
4962  TimestampTz result;
4963 
4966 
4968 
4969  PG_RETURN_TIMESTAMPTZ(result);
4970 }
4971 
4972 /* timestamptz_trunc_zone()
4973  * Truncate timestamptz to specified units in specified timezone.
4974  */
4975 Datum
4977 {
4978  text *units = PG_GETARG_TEXT_PP(0);
4980  text *zone = PG_GETARG_TEXT_PP(2);
4981  TimestampTz result;
4982  pg_tz *tzp;
4983 
4984  /*
4985  * timestamptz_zone() doesn't look up the zone for infinite inputs, so we
4986  * don't do so here either.
4987  */
4990 
4991  /*
4992  * Look up the requested timezone.
4993  */
4994  tzp = lookup_timezone(zone);
4995 
4996  result = timestamptz_trunc_internal(units, timestamp, tzp);
4997 
4998  PG_RETURN_TIMESTAMPTZ(result);
4999 }
5000 
5001 /* interval_trunc()
5002  * Extract specified field from interval.
5003  */
5004 Datum
5006 {
5007  text *units = PG_GETARG_TEXT_PP(0);
5009  Interval *result;
5010  int type,
5011  val;
5012  char *lowunits;
5013  struct pg_itm tt,
5014  *tm = &tt;
5015 
5016  result = (Interval *) palloc(sizeof(Interval));
5017 
5019  {
5020  memcpy(result, interval, sizeof(Interval));
5021  PG_RETURN_INTERVAL_P(result);
5022  }
5023 
5024  lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
5025  VARSIZE_ANY_EXHDR(units),
5026  false);
5027 
5028  type = DecodeUnits(0, lowunits, &val);
5029 
5030  if (type == UNITS)
5031  {
5033  switch (val)
5034  {
5035  case DTK_MILLENNIUM:
5036  /* caution: C division may have negative remainder */
5037  tm->tm_year = (tm->tm_year / 1000) * 1000;
5038  /* FALL THRU */
5039  case DTK_CENTURY:
5040  /* caution: C division may have negative remainder */
5041  tm->tm_year = (tm->tm_year / 100) * 100;
5042  /* FALL THRU */
5043  case DTK_DECADE:
5044  /* caution: C division may have negative remainder */
5045  tm->tm_year = (tm->tm_year / 10) * 10;
5046  /* FALL THRU */
5047  case DTK_YEAR:
5048  tm->tm_mon = 0;
5049  /* FALL THRU */
5050  case DTK_QUARTER:
5051  tm->tm_mon = 3 * (tm->tm_mon / 3);
5052  /* FALL THRU */
5053  case DTK_MONTH:
5054  tm->tm_mday = 0;
5055  /* FALL THRU */
5056  case DTK_DAY:
5057  tm->tm_hour = 0;
5058  /* FALL THRU */
5059  case DTK_HOUR:
5060  tm->tm_min = 0;
5061  /* FALL THRU */
5062  case DTK_MINUTE:
5063  tm->tm_sec = 0;
5064  /* FALL THRU */
5065  case DTK_SECOND:
5066  tm->tm_usec = 0;
5067  break;
5068  case DTK_MILLISEC:
5069  tm->tm_usec = (tm->tm_usec / 1000) * 1000;
5070  break;
5071  case DTK_MICROSEC:
5072  break;
5073 
5074  default:
5075  ereport(ERROR,
5076  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5077  errmsg("unit \"%s\" not supported for type %s",
5078  lowunits, format_type_be(INTERVALOID)),
5079  (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0));
5080  }
5081 
5082  if (itm2interval(tm, result) != 0)
5083  ereport(ERROR,
5084  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
5085  errmsg("interval out of range")));
5086  }
5087  else
5088  {
5089  ereport(ERROR,
5090  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5091  errmsg("unit \"%s\" not recognized for type %s",
5092  lowunits, format_type_be(INTERVALOID))));
5093  }
5094 
5095  PG_RETURN_INTERVAL_P(result);
5096 }
5097 
5098 /* isoweek2j()
5099  *
5100  * Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week.
5101  * Julian days are used to convert between ISO week dates and Gregorian dates.
5102  */
5103 int
5104 isoweek2j(int year, int week)
5105 {
5106  int day0,
5107  day4;
5108 
5109  /* fourth day of current year */
5110  day4 = date2j(year, 1, 4);
5111 
5112  /* day0 == offset to first day of week (Monday) */
5113  day0 = j2day(day4 - 1);
5114 
5115  return ((week - 1) * 7) + (day4 - day0);
5116 }
5117 
5118 /* isoweek2date()
5119  * Convert ISO week of year number to date.
5120  * The year field must be specified with the ISO year!
5121  * karel 2000/08/07
5122  */
5123 void
5124 isoweek2date(int woy, int *year, int *mon, int *mday)
5125 {
5126  j2date(isoweek2j(*year, woy), year, mon, mday);
5127 }
5128 
5129 /* isoweekdate2date()
5130  *
5131  * Convert an ISO 8601 week date (ISO year, ISO week) into a Gregorian date.
5132  * Gregorian day of week sent so weekday strings can be supplied.
5133  * Populates year, mon, and mday with the correct Gregorian values.
5134  * year must be passed in as the ISO year.
5135  */
5136 void
5137 isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
5138 {
5139  int jday;
5140 
5141  jday = isoweek2j(*year, isoweek);
5142  /* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
5143  if (wday > 1)
5144  jday += wday - 2;
5145  else
5146  jday += 6;
5147  j2date(jday, year, mon, mday);
5148 }
5149 
5150 /* date2isoweek()
5151  *
5152  * Returns ISO week number of year.
5153  */
5154 int
5155 date2isoweek(int year, int mon, int mday)
5156 {
5157  float8 result;
5158  int day0,
5159  day4,
5160  dayn;
5161 
5162  /* current day */
5163  dayn = date2j(year, mon, mday);
5164 
5165  /* fourth day of current year */
5166  day4 = date2j(year, 1, 4);
5167 
5168  /* day0 == offset to first day of week (Monday) */
5169  day0 = j2day(day4 - 1);
5170 
5171  /*
5172  * We need the first week containing a Thursday, otherwise this day falls
5173  * into the previous year for purposes of counting weeks
5174  */
5175  if (dayn < day4 - day0)
5176  {
5177  day4 = date2j(year - 1, 1, 4);
5178 
5179  /* day0 == offset to first day of week (Monday) */
5180  day0 = j2day(day4 - 1);
5181  }
5182 
5183  result = (dayn - (day4 - day0)) / 7 + 1;
5184 
5185  /*
5186  * Sometimes the last few days in a year will fall into the first week of
5187  * the next year, so check for this.
5188  */
5189  if (result >= 52)
5190  {
5191  day4 = date2j(year + 1, 1, 4);
5192 
5193  /* day0 == offset to first day of week (Monday) */
5194  day0 = j2day(day4 - 1);
5195 
5196  if (dayn >= day4 - day0)
5197  result = (dayn - (day4 - day0)) / 7 + 1;
5198  }
5199 
5200  return (int) result;
5201 }
5202 
5203 
5204 /* date2isoyear()
5205  *
5206  * Returns ISO 8601 year number.
5207  * Note: zero or negative results follow the year-zero-exists convention.
5208  */
5209 int
5210 date2isoyear(int year, int mon, int mday)
5211 {
5212  float8 result;
5213  int day0,
5214  day4,
5215  dayn;
5216 
5217  /* current day */
5218  dayn = date2j(year, mon, mday);
5219 
5220  /* fourth day of current year */
5221  day4 = date2j(year, 1, 4);
5222 
5223  /* day0 == offset to first day of week (Monday) */
5224  day0 = j2day(day4 - 1);
5225 
5226  /*
5227  * We need the first week containing a Thursday, otherwise this day falls
5228  * into the previous year for purposes of counting weeks
5229  */
5230  if (dayn < day4 - day0)
5231  {
5232  day4 = date2j(year - 1, 1, 4);
5233 
5234  /* day0 == offset to first day of week (Monday) */
5235  day0 = j2day(day4 - 1);
5236 
5237  year--;
5238  }
5239 
5240  result = (dayn - (day4 - day0)) / 7 + 1;
5241 
5242  /*
5243  * Sometimes the last few days in a year will fall into the first week of
5244  * the next year, so check for this.
5245  */
5246  if (result >= 52)
5247  {
5248  day4 = date2j(year + 1, 1, 4);
5249 
5250  /* day0 == offset to first day of week (Monday) */
5251  day0 = j2day(day4 - 1);
5252 
5253  if (dayn >= day4 - day0)
5254  year++;
5255  }
5256 
5257  return year;
5258 }
5259 
5260 
5261 /* date2isoyearday()
5262  *
5263  * Returns the ISO 8601 day-of-year, given a Gregorian year, month and day.
5264  * Possible return values are 1 through 371 (364 in non-leap years).
5265  */
5266 int
5267 date2isoyearday(int year, int mon, int mday)
5268 {
5269  return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
5270 }
5271 
5272 /*
5273  * NonFiniteTimestampTzPart
5274  *
5275  * Used by timestamp_part and timestamptz_part when extracting from infinite
5276  * timestamp[tz]. Returns +/-Infinity if that is the appropriate result,
5277  * otherwise returns zero (which should be taken as meaning to return NULL).
5278  *
5279  * Errors thrown here for invalid units should exactly match those that
5280  * would be thrown in the calling functions, else there will be unexpected
5281  * discrepancies between finite- and infinite-input cases.
5282  */
5283 static float8
5284 NonFiniteTimestampTzPart(int type, int unit, char *lowunits,
5285  bool isNegative, bool isTz)
5286 {
5287  if ((type != UNITS) && (type != RESERV))
5288  ereport(ERROR,
5289  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5290  errmsg("unit \"%s\" not recognized for type %s",
5291  lowunits,
5292  format_type_be(isTz ? TIMESTAMPTZOID : TIMESTAMPOID))));
5293 
5294  switch (unit)
5295  {
5296  /* Oscillating units */
5297  case DTK_MICROSEC:
5298  case DTK_MILLISEC:
5299  case DTK_SECOND:
5300  case DTK_MINUTE:
5301  case DTK_HOUR:
5302  case DTK_DAY:
5303  case DTK_MONTH:
5304  case DTK_QUARTER:
5305  case DTK_WEEK:
5306  case DTK_DOW:
5307  case DTK_ISODOW:
5308  case DTK_DOY:
5309  case DTK_TZ:
5310  case DTK_TZ_MINUTE:
5311  case DTK_TZ_HOUR:
5312  return 0.0;
5313 
5314  /* Monotonically-increasing units */
5315  case DTK_YEAR:
5316  case DTK_DECADE:
5317