PostgreSQL Source Code  git master
datetime.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * datetime.c
4  * Support functions for date/time types.
5  *
6  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/datetime.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <ctype.h>
18 #include <limits.h>
19 #include <math.h>
20 
21 #include "access/htup_details.h"
22 #include "access/xact.h"
23 #include "catalog/pg_type.h"
24 #include "common/int.h"
25 #include "common/string.h"
26 #include "funcapi.h"
27 #include "miscadmin.h"
28 #include "nodes/nodeFuncs.h"
29 #include "parser/scansup.h"
30 #include "utils/builtins.h"
31 #include "utils/date.h"
32 #include "utils/datetime.h"
33 #include "utils/guc.h"
34 #include "utils/memutils.h"
35 #include "utils/tzparser.h"
36 
37 static int DecodeNumber(int flen, char *str, bool haveTextMonth,
38  int fmask, int *tmask,
39  struct pg_tm *tm, fsec_t *fsec, bool *is2digits);
40 static int DecodeNumberField(int len, char *str,
41  int fmask, int *tmask,
42  struct pg_tm *tm, fsec_t *fsec, bool *is2digits);
43 static int DecodeTimeCommon(char *str, int fmask, int range,
44  int *tmask, struct pg_itm *itm);
45 static int DecodeTime(char *str, int fmask, int range,
46  int *tmask, struct pg_tm *tm, fsec_t *fsec);
47 static int DecodeTimeForInterval(char *str, int fmask, int range,
48  int *tmask, struct pg_itm_in *itm_in);
49 static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
50 static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
51  struct pg_tm *tm);
52 static char *AppendSeconds(char *cp, int sec, fsec_t fsec,
53  int precision, bool fillzeros);
54 static bool int64_multiply_add(int64 val, int64 multiplier, int64 *sum);
55 static bool AdjustFractMicroseconds(double frac, int64 scale,
56  struct pg_itm_in *itm_in);
57 static bool AdjustFractDays(double frac, int scale,
58  struct pg_itm_in *itm_in);
59 static bool AdjustFractYears(double frac, int scale,
60  struct pg_itm_in *itm_in);
61 static bool AdjustMicroseconds(int64 val, double fval, int64 scale,
62  struct pg_itm_in *itm_in);
63 static bool AdjustDays(int64 val, int scale,
64  struct pg_itm_in *itm_in);
65 static bool AdjustMonths(int64 val, struct pg_itm_in *itm_in);
66 static bool AdjustYears(int64 val, int scale,
67  struct pg_itm_in *itm_in);
68 static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp,
69  pg_time_t *tp);
71  const char *abbr, pg_tz *tzp,
72  int *offset, int *isdst);
74  DateTimeErrorExtra *extra);
75 
76 
77 const int day_tab[2][13] =
78 {
79  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
80  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}
81 };
82 
83 const char *const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
84 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
85 
86 const char *const days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
87 "Thursday", "Friday", "Saturday", NULL};
88 
89 
90 /*****************************************************************************
91  * PRIVATE ROUTINES *
92  *****************************************************************************/
93 
94 /*
95  * datetktbl holds date/time keywords.
96  *
97  * Note that this table must be strictly alphabetically ordered to allow an
98  * O(ln(N)) search algorithm to be used.
99  *
100  * The token field must be NUL-terminated; we truncate entries to TOKMAXLEN
101  * characters to fit.
102  *
103  * The static table contains no TZ, DTZ, or DYNTZ entries; rather those
104  * are loaded from configuration files and stored in zoneabbrevtbl, whose
105  * abbrevs[] field has the same format as the static datetktbl.
106  */
107 static const datetkn datetktbl[] = {
108  /* token, type, value */
109  {"+infinity", RESERV, DTK_LATE}, /* same as "infinity" */
110  {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
111  {DA_D, ADBC, AD}, /* "ad" for years > 0 */
112  {"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
113  {"am", AMPM, AM},
114  {"apr", MONTH, 4},
115  {"april", MONTH, 4},
116  {"at", IGNORE_DTF, 0}, /* "at" (throwaway) */
117  {"aug", MONTH, 8},
118  {"august", MONTH, 8},
119  {DB_C, ADBC, BC}, /* "bc" for years <= 0 */
120  {"d", UNITS, DTK_DAY}, /* "day of month" for ISO input */
121  {"dec", MONTH, 12},
122  {"december", MONTH, 12},
123  {"dow", UNITS, DTK_DOW}, /* day of week */
124  {"doy", UNITS, DTK_DOY}, /* day of year */
125  {"dst", DTZMOD, SECS_PER_HOUR},
126  {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
127  {"feb", MONTH, 2},
128  {"february", MONTH, 2},
129  {"fri", DOW, 5},
130  {"friday", DOW, 5},
131  {"h", UNITS, DTK_HOUR}, /* "hour" */
132  {LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */
133  {"isodow", UNITS, DTK_ISODOW}, /* ISO day of week, Sunday == 7 */
134  {"isoyear", UNITS, DTK_ISOYEAR}, /* year in terms of the ISO week date */
135  {"j", UNITS, DTK_JULIAN},
136  {"jan", MONTH, 1},
137  {"january", MONTH, 1},
138  {"jd", UNITS, DTK_JULIAN},
139  {"jul", MONTH, 7},
140  {"julian", UNITS, DTK_JULIAN},
141  {"july", MONTH, 7},
142  {"jun", MONTH, 6},
143  {"june", MONTH, 6},
144  {"m", UNITS, DTK_MONTH}, /* "month" for ISO input */
145  {"mar", MONTH, 3},
146  {"march", MONTH, 3},
147  {"may", MONTH, 5},
148  {"mm", UNITS, DTK_MINUTE}, /* "minute" for ISO input */
149  {"mon", DOW, 1},
150  {"monday", DOW, 1},
151  {"nov", MONTH, 11},
152  {"november", MONTH, 11},
153  {NOW, RESERV, DTK_NOW}, /* current transaction time */
154  {"oct", MONTH, 10},
155  {"october", MONTH, 10},
156  {"on", IGNORE_DTF, 0}, /* "on" (throwaway) */
157  {"pm", AMPM, PM},
158  {"s", UNITS, DTK_SECOND}, /* "seconds" for ISO input */
159  {"sat", DOW, 6},
160  {"saturday", DOW, 6},
161  {"sep", MONTH, 9},
162  {"sept", MONTH, 9},
163  {"september", MONTH, 9},
164  {"sun", DOW, 0},
165  {"sunday", DOW, 0},
166  {"t", ISOTIME, DTK_TIME}, /* Filler for ISO time fields */
167  {"thu", DOW, 4},
168  {"thur", DOW, 4},
169  {"thurs", DOW, 4},
170  {"thursday", DOW, 4},
171  {TODAY, RESERV, DTK_TODAY}, /* midnight */
172  {TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */
173  {"tue", DOW, 2},
174  {"tues", DOW, 2},
175  {"tuesday", DOW, 2},
176  {"wed", DOW, 3},
177  {"wednesday", DOW, 3},
178  {"weds", DOW, 3},
179  {"y", UNITS, DTK_YEAR}, /* "year" for ISO input */
180  {YESTERDAY, RESERV, DTK_YESTERDAY} /* yesterday midnight */
181 };
182 
183 static const int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
184 
185 /*
186  * deltatktbl: same format as datetktbl, but holds keywords used to represent
187  * time units (eg, for intervals, and for EXTRACT).
188  */
189 static const datetkn deltatktbl[] = {
190  /* token, type, value */
191  {"@", IGNORE_DTF, 0}, /* postgres relative prefix */
192  {DAGO, AGO, 0}, /* "ago" indicates negative time offset */
193  {"c", UNITS, DTK_CENTURY}, /* "century" relative */
194  {"cent", UNITS, DTK_CENTURY}, /* "century" relative */
195  {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative */
196  {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
197  {"d", UNITS, DTK_DAY}, /* "day" relative */
198  {DDAY, UNITS, DTK_DAY}, /* "day" relative */
199  {"days", UNITS, DTK_DAY}, /* "days" relative */
200  {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
201  {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative */
202  {"decades", UNITS, DTK_DECADE}, /* "decades" relative */
203  {"decs", UNITS, DTK_DECADE}, /* "decades" relative */
204  {"h", UNITS, DTK_HOUR}, /* "hour" relative */
205  {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative */
206  {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
207  {"hr", UNITS, DTK_HOUR}, /* "hour" relative */
208  {"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
209  {"m", UNITS, DTK_MINUTE}, /* "minute" relative */
210  {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
211  {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
212  {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
213  {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
214  {"millisecon", UNITS, DTK_MILLISEC}, /* relative */
215  {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
216  {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
217  {"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
218  {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative */
219  {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
220  {"mon", UNITS, DTK_MONTH}, /* "months" relative */
221  {"mons", UNITS, DTK_MONTH}, /* "months" relative */
222  {DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
223  {"months", UNITS, DTK_MONTH},
224  {"ms", UNITS, DTK_MILLISEC},
225  {"msec", UNITS, DTK_MILLISEC},
227  {"mseconds", UNITS, DTK_MILLISEC},
228  {"msecs", UNITS, DTK_MILLISEC},
229  {"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative */
230  {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
231  {"s", UNITS, DTK_SECOND},
232  {"sec", UNITS, DTK_SECOND},
234  {"seconds", UNITS, DTK_SECOND},
235  {"secs", UNITS, DTK_SECOND},
236  {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
237  {"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
238  {"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
239  {"us", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
240  {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
241  {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative */
242  {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
243  {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
244  {"w", UNITS, DTK_WEEK}, /* "week" relative */
245  {DWEEK, UNITS, DTK_WEEK}, /* "week" relative */
246  {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
247  {"y", UNITS, DTK_YEAR}, /* "year" relative */
248  {DYEAR, UNITS, DTK_YEAR}, /* "year" relative */
249  {"years", UNITS, DTK_YEAR}, /* "years" relative */
250  {"yr", UNITS, DTK_YEAR}, /* "year" relative */
251  {"yrs", UNITS, DTK_YEAR} /* "years" relative */
252 };
253 
254 static const int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
255 
257 
258 /* Caches of recent lookup results in the above tables */
259 
260 static const datetkn *datecache[MAXDATEFIELDS] = {NULL};
261 
262 static const datetkn *deltacache[MAXDATEFIELDS] = {NULL};
263 
264 static const datetkn *abbrevcache[MAXDATEFIELDS] = {NULL};
265 
266 
267 /*
268  * Calendar time to Julian date conversions.
269  * Julian date is commonly used in astronomical applications,
270  * since it is numerically accurate and computationally simple.
271  * The algorithms here will accurately convert between Julian day
272  * and calendar date for all non-negative Julian days
273  * (i.e. from Nov 24, -4713 on).
274  *
275  * Rewritten to eliminate overflow problems. This now allows the
276  * routines to work correctly for all Julian day counts from
277  * 0 to 2147483647 (Nov 24, -4713 to Jun 3, 5874898) assuming
278  * a 32-bit integer. Longer types should also work to the limits
279  * of their precision.
280  *
281  * Actually, date2j() will work sanely, in the sense of producing
282  * valid negative Julian dates, significantly before Nov 24, -4713.
283  * We rely on it to do so back to Nov 1, -4713; see IS_VALID_JULIAN()
284  * and associated commentary in timestamp.h.
285  */
286 
287 int
288 date2j(int year, int month, int day)
289 {
290  int julian;
291  int century;
292 
293  if (month > 2)
294  {
295  month += 1;
296  year += 4800;
297  }
298  else
299  {
300  month += 13;
301  year += 4799;
302  }
303 
304  century = year / 100;
305  julian = year * 365 - 32167;
306  julian += year / 4 - century + century / 4;
307  julian += 7834 * month / 256 + day;
308 
309  return julian;
310 } /* date2j() */
311 
312 void
313 j2date(int jd, int *year, int *month, int *day)
314 {
315  unsigned int julian;
316  unsigned int quad;
317  unsigned int extra;
318  int y;
319 
320  julian = jd;
321  julian += 32044;
322  quad = julian / 146097;
323  extra = (julian - quad * 146097) * 4 + 3;
324  julian += 60 + quad * 3 + extra / 146097;
325  quad = julian / 1461;
326  julian -= quad * 1461;
327  y = julian * 4 / 1461;
328  julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
329  + 123;
330  y += quad * 4;
331  *year = y - 4800;
332  quad = julian * 2141 / 65536;
333  *day = julian - 7834 * quad / 256;
334  *month = (quad + 10) % MONTHS_PER_YEAR + 1;
335 } /* j2date() */
336 
337 
338 /*
339  * j2day - convert Julian date to day-of-week (0..6 == Sun..Sat)
340  *
341  * Note: various places use the locution j2day(date - 1) to produce a
342  * result according to the convention 0..6 = Mon..Sun. This is a bit of
343  * a crock, but will work as long as the computation here is just a modulo.
344  */
345 int
347 {
348  date += 1;
349  date %= 7;
350  /* Cope if division truncates towards zero, as it probably does */
351  if (date < 0)
352  date += 7;
353 
354  return date;
355 } /* j2day() */
356 
357 
358 /*
359  * GetCurrentDateTime()
360  *
361  * Get the transaction start time ("now()") broken down as a struct pg_tm,
362  * converted according to the session timezone setting.
363  *
364  * This is just a convenience wrapper for GetCurrentTimeUsec, to cover the
365  * case where caller doesn't need either fractional seconds or tz offset.
366  */
367 void
369 {
370  fsec_t fsec;
371 
372  GetCurrentTimeUsec(tm, &fsec, NULL);
373 }
374 
375 /*
376  * GetCurrentTimeUsec()
377  *
378  * Get the transaction start time ("now()") broken down as a struct pg_tm,
379  * including fractional seconds and timezone offset. The time is converted
380  * according to the session timezone setting.
381  *
382  * Callers may pass tzp = NULL if they don't need the offset, but this does
383  * not affect the conversion behavior (unlike timestamp2tm()).
384  *
385  * Internally, we cache the result, since this could be called many times
386  * in a transaction, within which now() doesn't change.
387  */
388 void
389 GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
390 {
392 
393  /*
394  * The cache key must include both current time and current timezone. By
395  * representing the timezone by just a pointer, we're assuming that
396  * distinct timezone settings could never have the same pointer value.
397  * This is true by virtue of the hashtable used inside pg_tzset();
398  * however, it might need another look if we ever allow entries in that
399  * hash to be recycled.
400  */
401  static TimestampTz cache_ts = 0;
402  static pg_tz *cache_timezone = NULL;
403  static struct pg_tm cache_tm;
404  static fsec_t cache_fsec;
405  static int cache_tz;
406 
407  if (cur_ts != cache_ts || session_timezone != cache_timezone)
408  {
409  /*
410  * Make sure cache is marked invalid in case of error after partial
411  * update within timestamp2tm.
412  */
413  cache_timezone = NULL;
414 
415  /*
416  * Perform the computation, storing results into cache. We do not
417  * really expect any error here, since current time surely ought to be
418  * within range, but check just for sanity's sake.
419  */
420  if (timestamp2tm(cur_ts, &cache_tz, &cache_tm, &cache_fsec,
421  NULL, session_timezone) != 0)
422  ereport(ERROR,
423  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
424  errmsg("timestamp out of range")));
425 
426  /* OK, so mark the cache valid. */
427  cache_ts = cur_ts;
428  cache_timezone = session_timezone;
429  }
430 
431  *tm = cache_tm;
432  *fsec = cache_fsec;
433  if (tzp != NULL)
434  *tzp = cache_tz;
435 }
436 
437 
438 /*
439  * Append seconds and fractional seconds (if any) at *cp.
440  *
441  * precision is the max number of fraction digits, fillzeros says to
442  * pad to two integral-seconds digits.
443  *
444  * Returns a pointer to the new end of string. No NUL terminator is put
445  * there; callers are responsible for NUL terminating str themselves.
446  *
447  * Note that any sign is stripped from the input sec and fsec values.
448  */
449 static char *
450 AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
451 {
452  Assert(precision >= 0);
453 
454  if (fillzeros)
455  cp = pg_ultostr_zeropad(cp, abs(sec), 2);
456  else
457  cp = pg_ultostr(cp, abs(sec));
458 
459  /* fsec_t is just an int32 */
460  if (fsec != 0)
461  {
462  int32 value = abs(fsec);
463  char *end = &cp[precision + 1];
464  bool gotnonzero = false;
465 
466  *cp++ = '.';
467 
468  /*
469  * Append the fractional seconds part. Note that we don't want any
470  * trailing zeros here, so since we're building the number in reverse
471  * we'll skip appending zeros until we've output a non-zero digit.
472  */
473  while (precision--)
474  {
475  int32 oldval = value;
476  int32 remainder;
477 
478  value /= 10;
479  remainder = oldval - value * 10;
480 
481  /* check if we got a non-zero */
482  if (remainder)
483  gotnonzero = true;
484 
485  if (gotnonzero)
486  cp[precision] = '0' + remainder;
487  else
488  end = &cp[precision];
489  }
490 
491  /*
492  * If we still have a non-zero value then precision must have not been
493  * enough to print the number. We punt the problem to pg_ultostr(),
494  * which will generate a correct answer in the minimum valid width.
495  */
496  if (value)
497  return pg_ultostr(cp, abs(fsec));
498 
499  return end;
500  }
501  else
502  return cp;
503 }
504 
505 
506 /*
507  * Variant of above that's specialized to timestamp case.
508  *
509  * Returns a pointer to the new end of string. No NUL terminator is put
510  * there; callers are responsible for NUL terminating str themselves.
511  */
512 static char *
513 AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
514 {
515  return AppendSeconds(cp, tm->tm_sec, fsec, MAX_TIMESTAMP_PRECISION, true);
516 }
517 
518 
519 /*
520  * Add val * multiplier to *sum.
521  * Returns true if successful, false on overflow.
522  */
523 static bool
524 int64_multiply_add(int64 val, int64 multiplier, int64 *sum)
525 {
526  int64 product;
527 
528  if (pg_mul_s64_overflow(val, multiplier, &product) ||
529  pg_add_s64_overflow(*sum, product, sum))
530  return false;
531  return true;
532 }
533 
534 /*
535  * Multiply frac by scale (to produce microseconds) and add to itm_in->tm_usec.
536  * Returns true if successful, false if itm_in overflows.
537  */
538 static bool
539 AdjustFractMicroseconds(double frac, int64 scale,
540  struct pg_itm_in *itm_in)
541 {
542  int64 usec;
543 
544  /* Fast path for common case */
545  if (frac == 0)
546  return true;
547 
548  /*
549  * We assume the input frac has abs value less than 1, so overflow of frac
550  * or usec is not an issue for interesting values of scale.
551  */
552  frac *= scale;
553  usec = (int64) frac;
554 
555  /* Round off any fractional microsecond */
556  frac -= usec;
557  if (frac > 0.5)
558  usec++;
559  else if (frac < -0.5)
560  usec--;
561 
562  return !pg_add_s64_overflow(itm_in->tm_usec, usec, &itm_in->tm_usec);
563 }
564 
565 /*
566  * Multiply frac by scale (to produce days). Add the integral part of the
567  * result to itm_in->tm_mday, the fractional part to itm_in->tm_usec.
568  * Returns true if successful, false if itm_in overflows.
569  */
570 static bool
571 AdjustFractDays(double frac, int scale,
572  struct pg_itm_in *itm_in)
573 {
574  int extra_days;
575 
576  /* Fast path for common case */
577  if (frac == 0)
578  return true;
579 
580  /*
581  * We assume the input frac has abs value less than 1, so overflow of frac
582  * or extra_days is not an issue.
583  */
584  frac *= scale;
585  extra_days = (int) frac;
586 
587  /* ... but this could overflow, if tm_mday is already nonzero */
588  if (pg_add_s32_overflow(itm_in->tm_mday, extra_days, &itm_in->tm_mday))
589  return false;
590 
591  /* Handle any fractional day */
592  frac -= extra_days;
593  return AdjustFractMicroseconds(frac, USECS_PER_DAY, itm_in);
594 }
595 
596 /*
597  * Multiply frac by scale (to produce years), then further scale up to months.
598  * Add the integral part of the result to itm_in->tm_mon, discarding any
599  * fractional part.
600  * Returns true if successful, false if itm_in overflows.
601  */
602 static bool
603 AdjustFractYears(double frac, int scale,
604  struct pg_itm_in *itm_in)
605 {
606  /*
607  * As above, we assume abs(frac) < 1, so this can't overflow for any
608  * interesting value of scale.
609  */
610  int extra_months = (int) rint(frac * scale * MONTHS_PER_YEAR);
611 
612  return !pg_add_s32_overflow(itm_in->tm_mon, extra_months, &itm_in->tm_mon);
613 }
614 
615 /*
616  * Add (val + fval) * scale to itm_in->tm_usec.
617  * Returns true if successful, false if itm_in overflows.
618  */
619 static bool
620 AdjustMicroseconds(int64 val, double fval, int64 scale,
621  struct pg_itm_in *itm_in)
622 {
623  /* Handle the integer part */
624  if (!int64_multiply_add(val, scale, &itm_in->tm_usec))
625  return false;
626  /* Handle the float part */
627  return AdjustFractMicroseconds(fval, scale, itm_in);
628 }
629 
630 /*
631  * Multiply val by scale (to produce days) and add to itm_in->tm_mday.
632  * Returns true if successful, false if itm_in overflows.
633  */
634 static bool
635 AdjustDays(int64 val, int scale, struct pg_itm_in *itm_in)
636 {
637  int days;
638 
639  if (val < INT_MIN || val > INT_MAX)
640  return false;
641  return !pg_mul_s32_overflow((int32) val, scale, &days) &&
642  !pg_add_s32_overflow(itm_in->tm_mday, days, &itm_in->tm_mday);
643 }
644 
645 /*
646  * Add val to itm_in->tm_mon (no need for scale here, as val is always
647  * in months already).
648  * Returns true if successful, false if itm_in overflows.
649  */
650 static bool
651 AdjustMonths(int64 val, struct pg_itm_in *itm_in)
652 {
653  if (val < INT_MIN || val > INT_MAX)
654  return false;
655  return !pg_add_s32_overflow(itm_in->tm_mon, (int32) val, &itm_in->tm_mon);
656 }
657 
658 /*
659  * Multiply val by scale (to produce years) and add to itm_in->tm_year.
660  * Returns true if successful, false if itm_in overflows.
661  */
662 static bool
663 AdjustYears(int64 val, int scale,
664  struct pg_itm_in *itm_in)
665 {
666  int years;
667 
668  if (val < INT_MIN || val > INT_MAX)
669  return false;
670  return !pg_mul_s32_overflow((int32) val, scale, &years) &&
671  !pg_add_s32_overflow(itm_in->tm_year, years, &itm_in->tm_year);
672 }
673 
674 
675 /*
676  * Parse the fractional part of a number (decimal point and optional digits,
677  * followed by end of string). Returns the fractional value into *frac.
678  *
679  * Returns 0 if successful, DTERR code if bogus input detected.
680  */
681 static int
682 ParseFraction(char *cp, double *frac)
683 {
684  /* Caller should always pass the start of the fraction part */
685  Assert(*cp == '.');
686 
687  /*
688  * We want to allow just "." with no digits, but some versions of strtod
689  * will report EINVAL for that, so special-case it.
690  */
691  if (cp[1] == '\0')
692  {
693  *frac = 0;
694  }
695  else
696  {
697  errno = 0;
698  *frac = strtod(cp, &cp);
699  /* check for parse failure */
700  if (*cp != '\0' || errno != 0)
701  return DTERR_BAD_FORMAT;
702  }
703  return 0;
704 }
705 
706 /*
707  * Fetch a fractional-second value with suitable error checking.
708  * Same as ParseFraction except we convert the result to integer microseconds.
709  */
710 static int
712 {
713  double frac;
714  int dterr;
715 
716  dterr = ParseFraction(cp, &frac);
717  if (dterr)
718  return dterr;
719  *fsec = rint(frac * 1000000);
720  return 0;
721 }
722 
723 
724 /* ParseDateTime()
725  * Break string into tokens based on a date/time context.
726  * Returns 0 if successful, DTERR code if bogus input detected.
727  *
728  * timestr - the input string
729  * workbuf - workspace for field string storage. This must be
730  * larger than the largest legal input for this datetime type --
731  * some additional space will be needed to NUL terminate fields.
732  * buflen - the size of workbuf
733  * field[] - pointers to field strings are returned in this array
734  * ftype[] - field type indicators are returned in this array
735  * maxfields - dimensions of the above two arrays
736  * *numfields - set to the actual number of fields detected
737  *
738  * The fields extracted from the input are stored as separate,
739  * null-terminated strings in the workspace at workbuf. Any text is
740  * converted to lower case.
741  *
742  * Several field types are assigned:
743  * DTK_NUMBER - digits and (possibly) a decimal point
744  * DTK_DATE - digits and two delimiters, or digits and text
745  * DTK_TIME - digits, colon delimiters, and possibly a decimal point
746  * DTK_STRING - text (no digits or punctuation)
747  * DTK_SPECIAL - leading "+" or "-" followed by text
748  * DTK_TZ - leading "+" or "-" followed by digits (also eats ':', '.', '-')
749  *
750  * Note that some field types can hold unexpected items:
751  * DTK_NUMBER can hold date fields (yy.ddd)
752  * DTK_STRING can hold months (January) and time zones (PST)
753  * DTK_DATE can hold time zone names (America/New_York, GMT-8)
754  */
755 int
756 ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
757  char **field, int *ftype, int maxfields, int *numfields)
758 {
759  int nf = 0;
760  const char *cp = timestr;
761  char *bufp = workbuf;
762  const char *bufend = workbuf + buflen;
763 
764  /*
765  * Set the character pointed-to by "bufptr" to "newchar", and increment
766  * "bufptr". "end" gives the end of the buffer -- we return an error if
767  * there is no space left to append a character to the buffer. Note that
768  * "bufptr" is evaluated twice.
769  */
770 #define APPEND_CHAR(bufptr, end, newchar) \
771  do \
772  { \
773  if (((bufptr) + 1) >= (end)) \
774  return DTERR_BAD_FORMAT; \
775  *(bufptr)++ = newchar; \
776  } while (0)
777 
778  /* outer loop through fields */
779  while (*cp != '\0')
780  {
781  /* Ignore spaces between fields */
782  if (isspace((unsigned char) *cp))
783  {
784  cp++;
785  continue;
786  }
787 
788  /* Record start of current field */
789  if (nf >= maxfields)
790  return DTERR_BAD_FORMAT;
791  field[nf] = bufp;
792 
793  /* leading digit? then date or time */
794  if (isdigit((unsigned char) *cp))
795  {
796  APPEND_CHAR(bufp, bufend, *cp++);
797  while (isdigit((unsigned char) *cp))
798  APPEND_CHAR(bufp, bufend, *cp++);
799 
800  /* time field? */
801  if (*cp == ':')
802  {
803  ftype[nf] = DTK_TIME;
804  APPEND_CHAR(bufp, bufend, *cp++);
805  while (isdigit((unsigned char) *cp) ||
806  (*cp == ':') || (*cp == '.'))
807  APPEND_CHAR(bufp, bufend, *cp++);
808  }
809  /* date field? allow embedded text month */
810  else if (*cp == '-' || *cp == '/' || *cp == '.')
811  {
812  /* save delimiting character to use later */
813  char delim = *cp;
814 
815  APPEND_CHAR(bufp, bufend, *cp++);
816  /* second field is all digits? then no embedded text month */
817  if (isdigit((unsigned char) *cp))
818  {
819  ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);
820  while (isdigit((unsigned char) *cp))
821  APPEND_CHAR(bufp, bufend, *cp++);
822 
823  /*
824  * insist that the delimiters match to get a three-field
825  * date.
826  */
827  if (*cp == delim)
828  {
829  ftype[nf] = DTK_DATE;
830  APPEND_CHAR(bufp, bufend, *cp++);
831  while (isdigit((unsigned char) *cp) || *cp == delim)
832  APPEND_CHAR(bufp, bufend, *cp++);
833  }
834  }
835  else
836  {
837  ftype[nf] = DTK_DATE;
838  while (isalnum((unsigned char) *cp) || *cp == delim)
839  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
840  }
841  }
842 
843  /*
844  * otherwise, number only and will determine year, month, day, or
845  * concatenated fields later...
846  */
847  else
848  ftype[nf] = DTK_NUMBER;
849  }
850  /* Leading decimal point? Then fractional seconds... */
851  else if (*cp == '.')
852  {
853  APPEND_CHAR(bufp, bufend, *cp++);
854  while (isdigit((unsigned char) *cp))
855  APPEND_CHAR(bufp, bufend, *cp++);
856 
857  ftype[nf] = DTK_NUMBER;
858  }
859 
860  /*
861  * text? then date string, month, day of week, special, or timezone
862  */
863  else if (isalpha((unsigned char) *cp))
864  {
865  bool is_date;
866 
867  ftype[nf] = DTK_STRING;
868  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
869  while (isalpha((unsigned char) *cp))
870  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
871 
872  /*
873  * Dates can have embedded '-', '/', or '.' separators. It could
874  * also be a timezone name containing embedded '/', '+', '-', '_',
875  * or ':' (but '_' or ':' can't be the first punctuation). If the
876  * next character is a digit or '+', we need to check whether what
877  * we have so far is a recognized non-timezone keyword --- if so,
878  * don't believe that this is the start of a timezone.
879  */
880  is_date = false;
881  if (*cp == '-' || *cp == '/' || *cp == '.')
882  is_date = true;
883  else if (*cp == '+' || isdigit((unsigned char) *cp))
884  {
885  *bufp = '\0'; /* null-terminate current field value */
886  /* we need search only the core token table, not TZ names */
887  if (datebsearch(field[nf], datetktbl, szdatetktbl) == NULL)
888  is_date = true;
889  }
890  if (is_date)
891  {
892  ftype[nf] = DTK_DATE;
893  do
894  {
895  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
896  } while (*cp == '+' || *cp == '-' ||
897  *cp == '/' || *cp == '_' ||
898  *cp == '.' || *cp == ':' ||
899  isalnum((unsigned char) *cp));
900  }
901  }
902  /* sign? then special or numeric timezone */
903  else if (*cp == '+' || *cp == '-')
904  {
905  APPEND_CHAR(bufp, bufend, *cp++);
906  /* soak up leading whitespace */
907  while (isspace((unsigned char) *cp))
908  cp++;
909  /* numeric timezone? */
910  /* note that "DTK_TZ" could also be a signed float or yyyy-mm */
911  if (isdigit((unsigned char) *cp))
912  {
913  ftype[nf] = DTK_TZ;
914  APPEND_CHAR(bufp, bufend, *cp++);
915  while (isdigit((unsigned char) *cp) ||
916  *cp == ':' || *cp == '.' || *cp == '-')
917  APPEND_CHAR(bufp, bufend, *cp++);
918  }
919  /* special? */
920  else if (isalpha((unsigned char) *cp))
921  {
922  ftype[nf] = DTK_SPECIAL;
923  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
924  while (isalpha((unsigned char) *cp))
925  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
926  }
927  /* otherwise something wrong... */
928  else
929  return DTERR_BAD_FORMAT;
930  }
931  /* ignore other punctuation but use as delimiter */
932  else if (ispunct((unsigned char) *cp))
933  {
934  cp++;
935  continue;
936  }
937  /* otherwise, something is not right... */
938  else
939  return DTERR_BAD_FORMAT;
940 
941  /* force in a delimiter after each field */
942  *bufp++ = '\0';
943  nf++;
944  }
945 
946  *numfields = nf;
947 
948  return 0;
949 }
950 
951 
952 /* DecodeDateTime()
953  * Interpret previously parsed fields for general date and time.
954  * Return 0 if full date, 1 if only time, and negative DTERR code if problems.
955  * (Currently, all callers treat 1 as an error return too.)
956  *
957  * Inputs are field[] and ftype[] arrays, of length nf.
958  * Other arguments are outputs.
959  *
960  * External format(s):
961  * "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>"
962  * "Fri Feb-7-1997 15:23:27"
963  * "Feb-7-1997 15:23:27"
964  * "2-7-1997 15:23:27"
965  * "1997-2-7 15:23:27"
966  * "1997.038 15:23:27" (day of year 1-366)
967  * Also supports input in compact time:
968  * "970207 152327"
969  * "97038 152327"
970  * "20011225T040506.789-07"
971  *
972  * Use the system-provided functions to get the current time zone
973  * if not specified in the input string.
974  *
975  * If the date is outside the range of pg_time_t (in practice that could only
976  * happen if pg_time_t is just 32 bits), then assume UTC time zone - thomas
977  * 1997-05-27
978  */
979 int
980 DecodeDateTime(char **field, int *ftype, int nf,
981  int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,
982  DateTimeErrorExtra *extra)
983 {
984  int fmask = 0,
985  tmask,
986  type;
987  int ptype = 0; /* "prefix type" for ISO and Julian formats */
988  int i;
989  int val;
990  int dterr;
991  int mer = HR24;
992  bool haveTextMonth = false;
993  bool isjulian = false;
994  bool is2digits = false;
995  bool bc = false;
996  pg_tz *namedTz = NULL;
997  pg_tz *abbrevTz = NULL;
998  pg_tz *valtz;
999  char *abbrev = NULL;
1000  struct pg_tm cur_tm;
1001 
1002  /*
1003  * We'll insist on at least all of the date fields, but initialize the
1004  * remaining fields in case they are not set later...
1005  */
1006  *dtype = DTK_DATE;
1007  tm->tm_hour = 0;
1008  tm->tm_min = 0;
1009  tm->tm_sec = 0;
1010  *fsec = 0;
1011  /* don't know daylight savings time status apriori */
1012  tm->tm_isdst = -1;
1013  if (tzp != NULL)
1014  *tzp = 0;
1015 
1016  for (i = 0; i < nf; i++)
1017  {
1018  switch (ftype[i])
1019  {
1020  case DTK_DATE:
1021 
1022  /*
1023  * Integral julian day with attached time zone? All other
1024  * forms with JD will be separated into distinct fields, so we
1025  * handle just this case here.
1026  */
1027  if (ptype == DTK_JULIAN)
1028  {
1029  char *cp;
1030  int jday;
1031 
1032  if (tzp == NULL)
1033  return DTERR_BAD_FORMAT;
1034 
1035  errno = 0;
1036  jday = strtoint(field[i], &cp, 10);
1037  if (errno == ERANGE || jday < 0)
1038  return DTERR_FIELD_OVERFLOW;
1039 
1040  j2date(jday, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1041  isjulian = true;
1042 
1043  /* Get the time zone from the end of the string */
1044  dterr = DecodeTimezone(cp, tzp);
1045  if (dterr)
1046  return dterr;
1047 
1048  tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
1049  ptype = 0;
1050  break;
1051  }
1052 
1053  /*
1054  * Already have a date? Then this might be a time zone name
1055  * with embedded punctuation (e.g. "America/New_York") or a
1056  * run-together time with trailing time zone (e.g. hhmmss-zz).
1057  * - thomas 2001-12-25
1058  *
1059  * We consider it a time zone if we already have month & day.
1060  * This is to allow the form "mmm dd hhmmss tz year", which
1061  * we've historically accepted.
1062  */
1063  else if (ptype != 0 ||
1064  ((fmask & (DTK_M(MONTH) | DTK_M(DAY))) ==
1065  (DTK_M(MONTH) | DTK_M(DAY))))
1066  {
1067  /* No time zone accepted? Then quit... */
1068  if (tzp == NULL)
1069  return DTERR_BAD_FORMAT;
1070 
1071  if (isdigit((unsigned char) *field[i]) || ptype != 0)
1072  {
1073  char *cp;
1074 
1075  /*
1076  * Allow a preceding "t" field, but no other units.
1077  */
1078  if (ptype != 0)
1079  {
1080  /* Sanity check; should not fail this test */
1081  if (ptype != DTK_TIME)
1082  return DTERR_BAD_FORMAT;
1083  ptype = 0;
1084  }
1085 
1086  /*
1087  * Starts with a digit but we already have a time
1088  * field? Then we are in trouble with a date and time
1089  * already...
1090  */
1091  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1092  return DTERR_BAD_FORMAT;
1093 
1094  if ((cp = strchr(field[i], '-')) == NULL)
1095  return DTERR_BAD_FORMAT;
1096 
1097  /* Get the time zone from the end of the string */
1098  dterr = DecodeTimezone(cp, tzp);
1099  if (dterr)
1100  return dterr;
1101  *cp = '\0';
1102 
1103  /*
1104  * Then read the rest of the field as a concatenated
1105  * time
1106  */
1107  dterr = DecodeNumberField(strlen(field[i]), field[i],
1108  fmask,
1109  &tmask, tm,
1110  fsec, &is2digits);
1111  if (dterr < 0)
1112  return dterr;
1113 
1114  /*
1115  * modify tmask after returning from
1116  * DecodeNumberField()
1117  */
1118  tmask |= DTK_M(TZ);
1119  }
1120  else
1121  {
1122  namedTz = pg_tzset(field[i]);
1123  if (!namedTz)
1124  {
1125  extra->dtee_timezone = field[i];
1126  return DTERR_BAD_TIMEZONE;
1127  }
1128  /* we'll apply the zone setting below */
1129  tmask = DTK_M(TZ);
1130  }
1131  }
1132  else
1133  {
1134  dterr = DecodeDate(field[i], fmask,
1135  &tmask, &is2digits, tm);
1136  if (dterr)
1137  return dterr;
1138  }
1139  break;
1140 
1141  case DTK_TIME:
1142 
1143  /*
1144  * This might be an ISO time following a "t" field.
1145  */
1146  if (ptype != 0)
1147  {
1148  /* Sanity check; should not fail this test */
1149  if (ptype != DTK_TIME)
1150  return DTERR_BAD_FORMAT;
1151  ptype = 0;
1152  }
1153  dterr = DecodeTime(field[i], fmask, INTERVAL_FULL_RANGE,
1154  &tmask, tm, fsec);
1155  if (dterr)
1156  return dterr;
1157 
1158  /* check for time overflow */
1160  *fsec))
1161  return DTERR_FIELD_OVERFLOW;
1162  break;
1163 
1164  case DTK_TZ:
1165  {
1166  int tz;
1167 
1168  if (tzp == NULL)
1169  return DTERR_BAD_FORMAT;
1170 
1171  dterr = DecodeTimezone(field[i], &tz);
1172  if (dterr)
1173  return dterr;
1174  *tzp = tz;
1175  tmask = DTK_M(TZ);
1176  }
1177  break;
1178 
1179  case DTK_NUMBER:
1180 
1181  /*
1182  * Deal with cases where previous field labeled this one
1183  */
1184  if (ptype != 0)
1185  {
1186  char *cp;
1187  int value;
1188 
1189  errno = 0;
1190  value = strtoint(field[i], &cp, 10);
1191  if (errno == ERANGE)
1192  return DTERR_FIELD_OVERFLOW;
1193  if (*cp != '.' && *cp != '\0')
1194  return DTERR_BAD_FORMAT;
1195 
1196  switch (ptype)
1197  {
1198  case DTK_JULIAN:
1199  /* previous field was a label for "julian date" */
1200  if (value < 0)
1201  return DTERR_FIELD_OVERFLOW;
1202  tmask = DTK_DATE_M;
1203  j2date(value, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1204  isjulian = true;
1205 
1206  /* fractional Julian Day? */
1207  if (*cp == '.')
1208  {
1209  double time;
1210 
1211  dterr = ParseFraction(cp, &time);
1212  if (dterr)
1213  return dterr;
1214  time *= USECS_PER_DAY;
1215  dt2time(time,
1216  &tm->tm_hour, &tm->tm_min,
1217  &tm->tm_sec, fsec);
1218  tmask |= DTK_TIME_M;
1219  }
1220  break;
1221 
1222  case DTK_TIME:
1223  /* previous field was "t" for ISO time */
1224  dterr = DecodeNumberField(strlen(field[i]), field[i],
1225  (fmask | DTK_DATE_M),
1226  &tmask, tm,
1227  fsec, &is2digits);
1228  if (dterr < 0)
1229  return dterr;
1230  if (tmask != DTK_TIME_M)
1231  return DTERR_BAD_FORMAT;
1232  break;
1233 
1234  default:
1235  return DTERR_BAD_FORMAT;
1236  break;
1237  }
1238 
1239  ptype = 0;
1240  *dtype = DTK_DATE;
1241  }
1242  else
1243  {
1244  char *cp;
1245  int flen;
1246 
1247  flen = strlen(field[i]);
1248  cp = strchr(field[i], '.');
1249 
1250  /* Embedded decimal and no date yet? */
1251  if (cp != NULL && !(fmask & DTK_DATE_M))
1252  {
1253  dterr = DecodeDate(field[i], fmask,
1254  &tmask, &is2digits, tm);
1255  if (dterr)
1256  return dterr;
1257  }
1258  /* embedded decimal and several digits before? */
1259  else if (cp != NULL && flen - strlen(cp) > 2)
1260  {
1261  /*
1262  * Interpret as a concatenated date or time Set the
1263  * type field to allow decoding other fields later.
1264  * Example: 20011223 or 040506
1265  */
1266  dterr = DecodeNumberField(flen, field[i], fmask,
1267  &tmask, tm,
1268  fsec, &is2digits);
1269  if (dterr < 0)
1270  return dterr;
1271  }
1272 
1273  /*
1274  * Is this a YMD or HMS specification, or a year number?
1275  * YMD and HMS are required to be six digits or more, so
1276  * if it is 5 digits, it is a year. If it is six or more
1277  * digits, we assume it is YMD or HMS unless no date and
1278  * no time values have been specified. This forces 6+
1279  * digit years to be at the end of the string, or to use
1280  * the ISO date specification.
1281  */
1282  else if (flen >= 6 && (!(fmask & DTK_DATE_M) ||
1283  !(fmask & DTK_TIME_M)))
1284  {
1285  dterr = DecodeNumberField(flen, field[i], fmask,
1286  &tmask, tm,
1287  fsec, &is2digits);
1288  if (dterr < 0)
1289  return dterr;
1290  }
1291  /* otherwise it is a single date/time field... */
1292  else
1293  {
1294  dterr = DecodeNumber(flen, field[i],
1295  haveTextMonth, fmask,
1296  &tmask, tm,
1297  fsec, &is2digits);
1298  if (dterr)
1299  return dterr;
1300  }
1301  }
1302  break;
1303 
1304  case DTK_STRING:
1305  case DTK_SPECIAL:
1306  /* timezone abbrevs take precedence over built-in tokens */
1307  dterr = DecodeTimezoneAbbrev(i, field[i],
1308  &type, &val, &valtz, extra);
1309  if (dterr)
1310  return dterr;
1311  if (type == UNKNOWN_FIELD)
1312  type = DecodeSpecial(i, field[i], &val);
1313  if (type == IGNORE_DTF)
1314  continue;
1315 
1316  tmask = DTK_M(type);
1317  switch (type)
1318  {
1319  case RESERV:
1320  switch (val)
1321  {
1322  case DTK_NOW:
1323  tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
1324  *dtype = DTK_DATE;
1325  GetCurrentTimeUsec(tm, fsec, tzp);
1326  break;
1327 
1328  case DTK_YESTERDAY:
1329  tmask = DTK_DATE_M;
1330  *dtype = DTK_DATE;
1331  GetCurrentDateTime(&cur_tm);
1332  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) - 1,
1333  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1334  break;
1335 
1336  case DTK_TODAY:
1337  tmask = DTK_DATE_M;
1338  *dtype = DTK_DATE;
1339  GetCurrentDateTime(&cur_tm);
1340  tm->tm_year = cur_tm.tm_year;
1341  tm->tm_mon = cur_tm.tm_mon;
1342  tm->tm_mday = cur_tm.tm_mday;
1343  break;
1344 
1345  case DTK_TOMORROW:
1346  tmask = DTK_DATE_M;
1347  *dtype = DTK_DATE;
1348  GetCurrentDateTime(&cur_tm);
1349  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) + 1,
1350  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1351  break;
1352 
1353  case DTK_ZULU:
1354  tmask = (DTK_TIME_M | DTK_M(TZ));
1355  *dtype = DTK_DATE;
1356  tm->tm_hour = 0;
1357  tm->tm_min = 0;
1358  tm->tm_sec = 0;
1359  if (tzp != NULL)
1360  *tzp = 0;
1361  break;
1362 
1363  case DTK_EPOCH:
1364  case DTK_LATE:
1365  case DTK_EARLY:
1366  tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
1367  *dtype = val;
1368  /* caller ignores tm for these dtype codes */
1369  break;
1370 
1371  default:
1372  elog(ERROR, "unrecognized RESERV datetime token: %d",
1373  val);
1374  }
1375 
1376  break;
1377 
1378  case MONTH:
1379 
1380  /*
1381  * already have a (numeric) month? then see if we can
1382  * substitute...
1383  */
1384  if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
1385  !(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 &&
1386  tm->tm_mon <= 31)
1387  {
1388  tm->tm_mday = tm->tm_mon;
1389  tmask = DTK_M(DAY);
1390  }
1391  haveTextMonth = true;
1392  tm->tm_mon = val;
1393  break;
1394 
1395  case DTZMOD:
1396 
1397  /*
1398  * daylight savings time modifier (solves "MET DST"
1399  * syntax)
1400  */
1401  tmask |= DTK_M(DTZ);
1402  tm->tm_isdst = 1;
1403  if (tzp == NULL)
1404  return DTERR_BAD_FORMAT;
1405  *tzp -= val;
1406  break;
1407 
1408  case DTZ:
1409 
1410  /*
1411  * set mask for TZ here _or_ check for DTZ later when
1412  * getting default timezone
1413  */
1414  tmask |= DTK_M(TZ);
1415  tm->tm_isdst = 1;
1416  if (tzp == NULL)
1417  return DTERR_BAD_FORMAT;
1418  *tzp = -val;
1419  break;
1420 
1421  case TZ:
1422  tm->tm_isdst = 0;
1423  if (tzp == NULL)
1424  return DTERR_BAD_FORMAT;
1425  *tzp = -val;
1426  break;
1427 
1428  case DYNTZ:
1429  tmask |= DTK_M(TZ);
1430  if (tzp == NULL)
1431  return DTERR_BAD_FORMAT;
1432  /* we'll determine the actual offset later */
1433  abbrevTz = valtz;
1434  abbrev = field[i];
1435  break;
1436 
1437  case AMPM:
1438  mer = val;
1439  break;
1440 
1441  case ADBC:
1442  bc = (val == BC);
1443  break;
1444 
1445  case DOW:
1446  tm->tm_wday = val;
1447  break;
1448 
1449  case UNITS:
1450  tmask = 0;
1451  /* reject consecutive unhandled units */
1452  if (ptype != 0)
1453  return DTERR_BAD_FORMAT;
1454  ptype = val;
1455  break;
1456 
1457  case ISOTIME:
1458 
1459  /*
1460  * This is a filler field "t" indicating that the next
1461  * field is time. Try to verify that this is sensible.
1462  */
1463  tmask = 0;
1464 
1465  /* No preceding date? Then quit... */
1466  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1467  return DTERR_BAD_FORMAT;
1468 
1469  /* reject consecutive unhandled units */
1470  if (ptype != 0)
1471  return DTERR_BAD_FORMAT;
1472  ptype = val;
1473  break;
1474 
1475  case UNKNOWN_FIELD:
1476 
1477  /*
1478  * Before giving up and declaring error, check to see
1479  * if it is an all-alpha timezone name.
1480  */
1481  namedTz = pg_tzset(field[i]);
1482  if (!namedTz)
1483  return DTERR_BAD_FORMAT;
1484  /* we'll apply the zone setting below */
1485  tmask = DTK_M(TZ);
1486  break;
1487 
1488  default:
1489  return DTERR_BAD_FORMAT;
1490  }
1491  break;
1492 
1493  default:
1494  return DTERR_BAD_FORMAT;
1495  }
1496 
1497  if (tmask & fmask)
1498  return DTERR_BAD_FORMAT;
1499  fmask |= tmask;
1500  } /* end loop over fields */
1501 
1502  /* reject if prefix type appeared and was never handled */
1503  if (ptype != 0)
1504  return DTERR_BAD_FORMAT;
1505 
1506  /* do additional checking for normal date specs (but not "infinity" etc) */
1507  if (*dtype == DTK_DATE)
1508  {
1509  /* do final checking/adjustment of Y/M/D fields */
1510  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
1511  if (dterr)
1512  return dterr;
1513 
1514  /* handle AM/PM */
1515  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
1516  return DTERR_FIELD_OVERFLOW;
1517  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
1518  tm->tm_hour = 0;
1519  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
1520  tm->tm_hour += HOURS_PER_DAY / 2;
1521 
1522  /* check for incomplete input */
1523  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1524  {
1525  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1526  return 1;
1527  return DTERR_BAD_FORMAT;
1528  }
1529 
1530  /*
1531  * If we had a full timezone spec, compute the offset (we could not do
1532  * it before, because we need the date to resolve DST status).
1533  */
1534  if (namedTz != NULL)
1535  {
1536  /* daylight savings time modifier disallowed with full TZ */
1537  if (fmask & DTK_M(DTZMOD))
1538  return DTERR_BAD_FORMAT;
1539 
1540  *tzp = DetermineTimeZoneOffset(tm, namedTz);
1541  }
1542 
1543  /*
1544  * Likewise, if we had a dynamic timezone abbreviation, resolve it
1545  * now.
1546  */
1547  if (abbrevTz != NULL)
1548  {
1549  /* daylight savings time modifier disallowed with dynamic TZ */
1550  if (fmask & DTK_M(DTZMOD))
1551  return DTERR_BAD_FORMAT;
1552 
1553  *tzp = DetermineTimeZoneAbbrevOffset(tm, abbrev, abbrevTz);
1554  }
1555 
1556  /* timezone not specified? then use session timezone */
1557  if (tzp != NULL && !(fmask & DTK_M(TZ)))
1558  {
1559  /*
1560  * daylight savings time modifier but no standard timezone? then
1561  * error
1562  */
1563  if (fmask & DTK_M(DTZMOD))
1564  return DTERR_BAD_FORMAT;
1565 
1567  }
1568  }
1569 
1570  return 0;
1571 }
1572 
1573 
1574 /* DetermineTimeZoneOffset()
1575  *
1576  * Given a struct pg_tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min,
1577  * and tm_sec fields are set, and a zic-style time zone definition, determine
1578  * the applicable GMT offset and daylight-savings status at that time.
1579  * Set the struct pg_tm's tm_isdst field accordingly, and return the GMT
1580  * offset as the function result.
1581  *
1582  * Note: if the date is out of the range we can deal with, we return zero
1583  * as the GMT offset and set tm_isdst = 0. We don't throw an error here,
1584  * though probably some higher-level code will.
1585  */
1586 int
1588 {
1589  pg_time_t t;
1590 
1591  return DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1592 }
1593 
1594 
1595 /* DetermineTimeZoneOffsetInternal()
1596  *
1597  * As above, but also return the actual UTC time imputed to the date/time
1598  * into *tp.
1599  *
1600  * In event of an out-of-range date, we punt by returning zero into *tp.
1601  * This is okay for the immediate callers but is a good reason for not
1602  * exposing this worker function globally.
1603  *
1604  * Note: it might seem that we should use mktime() for this, but bitter
1605  * experience teaches otherwise. This code is much faster than most versions
1606  * of mktime(), anyway.
1607  */
1608 static int
1610 {
1611  int date,
1612  sec;
1613  pg_time_t day,
1614  mytime,
1615  prevtime,
1616  boundary,
1617  beforetime,
1618  aftertime;
1619  long int before_gmtoff,
1620  after_gmtoff;
1621  int before_isdst,
1622  after_isdst;
1623  int res;
1624 
1625  /*
1626  * First, generate the pg_time_t value corresponding to the given
1627  * y/m/d/h/m/s taken as GMT time. If this overflows, punt and decide the
1628  * timezone is GMT. (For a valid Julian date, integer overflow should be
1629  * impossible with 64-bit pg_time_t, but let's check for safety.)
1630  */
1632  goto overflow;
1634 
1635  day = ((pg_time_t) date) * SECS_PER_DAY;
1636  if (day / SECS_PER_DAY != date)
1637  goto overflow;
1639  mytime = day + sec;
1640  /* since sec >= 0, overflow could only be from +day to -mytime */
1641  if (mytime < 0 && day > 0)
1642  goto overflow;
1643 
1644  /*
1645  * Find the DST time boundary just before or following the target time. We
1646  * assume that all zones have GMT offsets less than 24 hours, and that DST
1647  * boundaries can't be closer together than 48 hours, so backing up 24
1648  * hours and finding the "next" boundary will work.
1649  */
1650  prevtime = mytime - SECS_PER_DAY;
1651  if (mytime < 0 && prevtime > 0)
1652  goto overflow;
1653 
1654  res = pg_next_dst_boundary(&prevtime,
1655  &before_gmtoff, &before_isdst,
1656  &boundary,
1657  &after_gmtoff, &after_isdst,
1658  tzp);
1659  if (res < 0)
1660  goto overflow; /* failure? */
1661 
1662  if (res == 0)
1663  {
1664  /* Non-DST zone, life is simple */
1665  tm->tm_isdst = before_isdst;
1666  *tp = mytime - before_gmtoff;
1667  return -(int) before_gmtoff;
1668  }
1669 
1670  /*
1671  * Form the candidate pg_time_t values with local-time adjustment
1672  */
1673  beforetime = mytime - before_gmtoff;
1674  if ((before_gmtoff > 0 &&
1675  mytime < 0 && beforetime > 0) ||
1676  (before_gmtoff <= 0 &&
1677  mytime > 0 && beforetime < 0))
1678  goto overflow;
1679  aftertime = mytime - after_gmtoff;
1680  if ((after_gmtoff > 0 &&
1681  mytime < 0 && aftertime > 0) ||
1682  (after_gmtoff <= 0 &&
1683  mytime > 0 && aftertime < 0))
1684  goto overflow;
1685 
1686  /*
1687  * If both before or both after the boundary time, we know what to do. The
1688  * boundary time itself is considered to be after the transition, which
1689  * means we can accept aftertime == boundary in the second case.
1690  */
1691  if (beforetime < boundary && aftertime < boundary)
1692  {
1693  tm->tm_isdst = before_isdst;
1694  *tp = beforetime;
1695  return -(int) before_gmtoff;
1696  }
1697  if (beforetime > boundary && aftertime >= boundary)
1698  {
1699  tm->tm_isdst = after_isdst;
1700  *tp = aftertime;
1701  return -(int) after_gmtoff;
1702  }
1703 
1704  /*
1705  * It's an invalid or ambiguous time due to timezone transition. In a
1706  * spring-forward transition, prefer the "before" interpretation; in a
1707  * fall-back transition, prefer "after". (We used to define and implement
1708  * this test as "prefer the standard-time interpretation", but that rule
1709  * does not help to resolve the behavior when both times are reported as
1710  * standard time; which does happen, eg Europe/Moscow in Oct 2014. Also,
1711  * in some zones such as Europe/Dublin, there is widespread confusion
1712  * about which time offset is "standard" time, so it's fortunate that our
1713  * behavior doesn't depend on that.)
1714  */
1715  if (beforetime > aftertime)
1716  {
1717  tm->tm_isdst = before_isdst;
1718  *tp = beforetime;
1719  return -(int) before_gmtoff;
1720  }
1721  tm->tm_isdst = after_isdst;
1722  *tp = aftertime;
1723  return -(int) after_gmtoff;
1724 
1725 overflow:
1726  /* Given date is out of range, so assume UTC */
1727  tm->tm_isdst = 0;
1728  *tp = 0;
1729  return 0;
1730 }
1731 
1732 
1733 /* DetermineTimeZoneAbbrevOffset()
1734  *
1735  * Determine the GMT offset and DST flag to be attributed to a dynamic
1736  * time zone abbreviation, that is one whose meaning has changed over time.
1737  * *tm contains the local time at which the meaning should be determined,
1738  * and tm->tm_isdst receives the DST flag.
1739  *
1740  * This differs from the behavior of DetermineTimeZoneOffset() in that a
1741  * standard-time or daylight-time abbreviation forces use of the corresponding
1742  * GMT offset even when the zone was then in DS or standard time respectively.
1743  * (However, that happens only if we can match the given abbreviation to some
1744  * abbreviation that appears in the IANA timezone data. Otherwise, we fall
1745  * back to doing DetermineTimeZoneOffset().)
1746  */
1747 int
1748 DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
1749 {
1750  pg_time_t t;
1751  int zone_offset;
1752  int abbr_offset;
1753  int abbr_isdst;
1754 
1755  /*
1756  * Compute the UTC time we want to probe at. (In event of overflow, we'll
1757  * probe at the epoch, which is a bit random but probably doesn't matter.)
1758  */
1759  zone_offset = DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1760 
1761  /*
1762  * Try to match the abbreviation to something in the zone definition.
1763  */
1764  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1765  &abbr_offset, &abbr_isdst))
1766  {
1767  /* Success, so use the abbrev-specific answers. */
1768  tm->tm_isdst = abbr_isdst;
1769  return abbr_offset;
1770  }
1771 
1772  /*
1773  * No match, so use the answers we already got from
1774  * DetermineTimeZoneOffsetInternal.
1775  */
1776  return zone_offset;
1777 }
1778 
1779 
1780 /* DetermineTimeZoneAbbrevOffsetTS()
1781  *
1782  * As above but the probe time is specified as a TimestampTz (hence, UTC time),
1783  * and DST status is returned into *isdst rather than into tm->tm_isdst.
1784  */
1785 int
1787  pg_tz *tzp, int *isdst)
1788 {
1790  int zone_offset;
1791  int abbr_offset;
1792  int tz;
1793  struct pg_tm tm;
1794  fsec_t fsec;
1795 
1796  /*
1797  * If the abbrev matches anything in the zone data, this is pretty easy.
1798  */
1799  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1800  &abbr_offset, isdst))
1801  return abbr_offset;
1802 
1803  /*
1804  * Else, break down the timestamp so we can use DetermineTimeZoneOffset.
1805  */
1806  if (timestamp2tm(ts, &tz, &tm, &fsec, NULL, tzp) != 0)
1807  ereport(ERROR,
1808  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1809  errmsg("timestamp out of range")));
1810 
1811  zone_offset = DetermineTimeZoneOffset(&tm, tzp);
1812  *isdst = tm.tm_isdst;
1813  return zone_offset;
1814 }
1815 
1816 
1817 /* DetermineTimeZoneAbbrevOffsetInternal()
1818  *
1819  * Workhorse for above two functions: work from a pg_time_t probe instant.
1820  * On success, return GMT offset and DST status into *offset and *isdst.
1821  */
1822 static bool
1824  int *offset, int *isdst)
1825 {
1826  char upabbr[TZ_STRLEN_MAX + 1];
1827  unsigned char *p;
1828  long int gmtoff;
1829 
1830  /* We need to force the abbrev to upper case */
1831  strlcpy(upabbr, abbr, sizeof(upabbr));
1832  for (p = (unsigned char *) upabbr; *p; p++)
1833  *p = pg_toupper(*p);
1834 
1835  /* Look up the abbrev's meaning at this time in this zone */
1836  if (pg_interpret_timezone_abbrev(upabbr,
1837  &t,
1838  &gmtoff,
1839  isdst,
1840  tzp))
1841  {
1842  /* Change sign to agree with DetermineTimeZoneOffset() */
1843  *offset = (int) -gmtoff;
1844  return true;
1845  }
1846  return false;
1847 }
1848 
1849 
1850 /* DecodeTimeOnly()
1851  * Interpret parsed string as time fields only.
1852  * Returns 0 if successful, DTERR code if bogus input detected.
1853  *
1854  * Inputs are field[] and ftype[] arrays, of length nf.
1855  * Other arguments are outputs.
1856  *
1857  * Note that support for time zone is here for
1858  * SQL TIME WITH TIME ZONE, but it reveals
1859  * bogosity with SQL date/time standards, since
1860  * we must infer a time zone from current time.
1861  * - thomas 2000-03-10
1862  * Allow specifying date to get a better time zone,
1863  * if time zones are allowed. - thomas 2001-12-26
1864  */
1865 int
1866 DecodeTimeOnly(char **field, int *ftype, int nf,
1867  int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,
1868  DateTimeErrorExtra *extra)
1869 {
1870  int fmask = 0,
1871  tmask,
1872  type;
1873  int ptype = 0; /* "prefix type" for ISO and Julian formats */
1874  int i;
1875  int val;
1876  int dterr;
1877  bool isjulian = false;
1878  bool is2digits = false;
1879  bool bc = false;
1880  int mer = HR24;
1881  pg_tz *namedTz = NULL;
1882  pg_tz *abbrevTz = NULL;
1883  char *abbrev = NULL;
1884  pg_tz *valtz;
1885 
1886  *dtype = DTK_TIME;
1887  tm->tm_hour = 0;
1888  tm->tm_min = 0;
1889  tm->tm_sec = 0;
1890  *fsec = 0;
1891  /* don't know daylight savings time status apriori */
1892  tm->tm_isdst = -1;
1893 
1894  if (tzp != NULL)
1895  *tzp = 0;
1896 
1897  for (i = 0; i < nf; i++)
1898  {
1899  switch (ftype[i])
1900  {
1901  case DTK_DATE:
1902 
1903  /*
1904  * Time zone not allowed? Then should not accept dates or time
1905  * zones no matter what else!
1906  */
1907  if (tzp == NULL)
1908  return DTERR_BAD_FORMAT;
1909 
1910  /* Under limited circumstances, we will accept a date... */
1911  if (i == 0 && nf >= 2 &&
1912  (ftype[nf - 1] == DTK_DATE || ftype[1] == DTK_TIME))
1913  {
1914  dterr = DecodeDate(field[i], fmask,
1915  &tmask, &is2digits, tm);
1916  if (dterr)
1917  return dterr;
1918  }
1919  /* otherwise, this is a time and/or time zone */
1920  else
1921  {
1922  if (isdigit((unsigned char) *field[i]))
1923  {
1924  char *cp;
1925 
1926  /*
1927  * Starts with a digit but we already have a time
1928  * field? Then we are in trouble with time already...
1929  */
1930  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1931  return DTERR_BAD_FORMAT;
1932 
1933  /*
1934  * Should not get here and fail. Sanity check only...
1935  */
1936  if ((cp = strchr(field[i], '-')) == NULL)
1937  return DTERR_BAD_FORMAT;
1938 
1939  /* Get the time zone from the end of the string */
1940  dterr = DecodeTimezone(cp, tzp);
1941  if (dterr)
1942  return dterr;
1943  *cp = '\0';
1944 
1945  /*
1946  * Then read the rest of the field as a concatenated
1947  * time
1948  */
1949  dterr = DecodeNumberField(strlen(field[i]), field[i],
1950  (fmask | DTK_DATE_M),
1951  &tmask, tm,
1952  fsec, &is2digits);
1953  if (dterr < 0)
1954  return dterr;
1955  ftype[i] = dterr;
1956 
1957  tmask |= DTK_M(TZ);
1958  }
1959  else
1960  {
1961  namedTz = pg_tzset(field[i]);
1962  if (!namedTz)
1963  {
1964  extra->dtee_timezone = field[i];
1965  return DTERR_BAD_TIMEZONE;
1966  }
1967  /* we'll apply the zone setting below */
1968  ftype[i] = DTK_TZ;
1969  tmask = DTK_M(TZ);
1970  }
1971  }
1972  break;
1973 
1974  case DTK_TIME:
1975  dterr = DecodeTime(field[i], (fmask | DTK_DATE_M),
1977  &tmask, tm, fsec);
1978  if (dterr)
1979  return dterr;
1980  break;
1981 
1982  case DTK_TZ:
1983  {
1984  int tz;
1985 
1986  if (tzp == NULL)
1987  return DTERR_BAD_FORMAT;
1988 
1989  dterr = DecodeTimezone(field[i], &tz);
1990  if (dterr)
1991  return dterr;
1992  *tzp = tz;
1993  tmask = DTK_M(TZ);
1994  }
1995  break;
1996 
1997  case DTK_NUMBER:
1998 
1999  /*
2000  * Deal with cases where previous field labeled this one
2001  */
2002  if (ptype != 0)
2003  {
2004  char *cp;
2005  int value;
2006 
2007  errno = 0;
2008  value = strtoint(field[i], &cp, 10);
2009  if (errno == ERANGE)
2010  return DTERR_FIELD_OVERFLOW;
2011  if (*cp != '.' && *cp != '\0')
2012  return DTERR_BAD_FORMAT;
2013 
2014  switch (ptype)
2015  {
2016  case DTK_JULIAN:
2017  /* previous field was a label for "julian date" */
2018  if (tzp == NULL)
2019  return DTERR_BAD_FORMAT;
2020  if (value < 0)
2021  return DTERR_FIELD_OVERFLOW;
2022  tmask = DTK_DATE_M;
2023  j2date(value, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2024  isjulian = true;
2025 
2026  if (*cp == '.')
2027  {
2028  double time;
2029 
2030  dterr = ParseFraction(cp, &time);
2031  if (dterr)
2032  return dterr;
2033  time *= USECS_PER_DAY;
2034  dt2time(time,
2035  &tm->tm_hour, &tm->tm_min,
2036  &tm->tm_sec, fsec);
2037  tmask |= DTK_TIME_M;
2038  }
2039  break;
2040 
2041  case DTK_TIME:
2042  /* previous field was "t" for ISO time */
2043  dterr = DecodeNumberField(strlen(field[i]), field[i],
2044  (fmask | DTK_DATE_M),
2045  &tmask, tm,
2046  fsec, &is2digits);
2047  if (dterr < 0)
2048  return dterr;
2049  ftype[i] = dterr;
2050 
2051  if (tmask != DTK_TIME_M)
2052  return DTERR_BAD_FORMAT;
2053  break;
2054 
2055  default:
2056  return DTERR_BAD_FORMAT;
2057  break;
2058  }
2059 
2060  ptype = 0;
2061  *dtype = DTK_DATE;
2062  }
2063  else
2064  {
2065  char *cp;
2066  int flen;
2067 
2068  flen = strlen(field[i]);
2069  cp = strchr(field[i], '.');
2070 
2071  /* Embedded decimal? */
2072  if (cp != NULL)
2073  {
2074  /*
2075  * Under limited circumstances, we will accept a
2076  * date...
2077  */
2078  if (i == 0 && nf >= 2 && ftype[nf - 1] == DTK_DATE)
2079  {
2080  dterr = DecodeDate(field[i], fmask,
2081  &tmask, &is2digits, tm);
2082  if (dterr)
2083  return dterr;
2084  }
2085  /* embedded decimal and several digits before? */
2086  else if (flen - strlen(cp) > 2)
2087  {
2088  /*
2089  * Interpret as a concatenated date or time Set
2090  * the type field to allow decoding other fields
2091  * later. Example: 20011223 or 040506
2092  */
2093  dterr = DecodeNumberField(flen, field[i],
2094  (fmask | DTK_DATE_M),
2095  &tmask, tm,
2096  fsec, &is2digits);
2097  if (dterr < 0)
2098  return dterr;
2099  ftype[i] = dterr;
2100  }
2101  else
2102  return DTERR_BAD_FORMAT;
2103  }
2104  else if (flen > 4)
2105  {
2106  dterr = DecodeNumberField(flen, field[i],
2107  (fmask | DTK_DATE_M),
2108  &tmask, tm,
2109  fsec, &is2digits);
2110  if (dterr < 0)
2111  return dterr;
2112  ftype[i] = dterr;
2113  }
2114  /* otherwise it is a single date/time field... */
2115  else
2116  {
2117  dterr = DecodeNumber(flen, field[i],
2118  false,
2119  (fmask | DTK_DATE_M),
2120  &tmask, tm,
2121  fsec, &is2digits);
2122  if (dterr)
2123  return dterr;
2124  }
2125  }
2126  break;
2127 
2128  case DTK_STRING:
2129  case DTK_SPECIAL:
2130  /* timezone abbrevs take precedence over built-in tokens */
2131  dterr = DecodeTimezoneAbbrev(i, field[i],
2132  &type, &val, &valtz, extra);
2133  if (dterr)
2134  return dterr;
2135  if (type == UNKNOWN_FIELD)
2136  type = DecodeSpecial(i, field[i], &val);
2137  if (type == IGNORE_DTF)
2138  continue;
2139 
2140  tmask = DTK_M(type);
2141  switch (type)
2142  {
2143  case RESERV:
2144  switch (val)
2145  {
2146  case DTK_NOW:
2147  tmask = DTK_TIME_M;
2148  *dtype = DTK_TIME;
2149  GetCurrentTimeUsec(tm, fsec, NULL);
2150  break;
2151 
2152  case DTK_ZULU:
2153  tmask = (DTK_TIME_M | DTK_M(TZ));
2154  *dtype = DTK_TIME;
2155  tm->tm_hour = 0;
2156  tm->tm_min = 0;
2157  tm->tm_sec = 0;
2158  tm->tm_isdst = 0;
2159  break;
2160 
2161  default:
2162  return DTERR_BAD_FORMAT;
2163  }
2164 
2165  break;
2166 
2167  case DTZMOD:
2168 
2169  /*
2170  * daylight savings time modifier (solves "MET DST"
2171  * syntax)
2172  */
2173  tmask |= DTK_M(DTZ);
2174  tm->tm_isdst = 1;
2175  if (tzp == NULL)
2176  return DTERR_BAD_FORMAT;
2177  *tzp -= val;
2178  break;
2179 
2180  case DTZ:
2181 
2182  /*
2183  * set mask for TZ here _or_ check for DTZ later when
2184  * getting default timezone
2185  */
2186  tmask |= DTK_M(TZ);
2187  tm->tm_isdst = 1;
2188  if (tzp == NULL)
2189  return DTERR_BAD_FORMAT;
2190  *tzp = -val;
2191  ftype[i] = DTK_TZ;
2192  break;
2193 
2194  case TZ:
2195  tm->tm_isdst = 0;
2196  if (tzp == NULL)
2197  return DTERR_BAD_FORMAT;
2198  *tzp = -val;
2199  ftype[i] = DTK_TZ;
2200  break;
2201 
2202  case DYNTZ:
2203  tmask |= DTK_M(TZ);
2204  if (tzp == NULL)
2205  return DTERR_BAD_FORMAT;
2206  /* we'll determine the actual offset later */
2207  abbrevTz = valtz;
2208  abbrev = field[i];
2209  ftype[i] = DTK_TZ;
2210  break;
2211 
2212  case AMPM:
2213  mer = val;
2214  break;
2215 
2216  case ADBC:
2217  bc = (val == BC);
2218  break;
2219 
2220  case UNITS:
2221  tmask = 0;
2222  /* reject consecutive unhandled units */
2223  if (ptype != 0)
2224  return DTERR_BAD_FORMAT;
2225  ptype = val;
2226  break;
2227 
2228  case ISOTIME:
2229  tmask = 0;
2230  /* reject consecutive unhandled units */
2231  if (ptype != 0)
2232  return DTERR_BAD_FORMAT;
2233  ptype = val;
2234  break;
2235 
2236  case UNKNOWN_FIELD:
2237 
2238  /*
2239  * Before giving up and declaring error, check to see
2240  * if it is an all-alpha timezone name.
2241  */
2242  namedTz = pg_tzset(field[i]);
2243  if (!namedTz)
2244  return DTERR_BAD_FORMAT;
2245  /* we'll apply the zone setting below */
2246  tmask = DTK_M(TZ);
2247  break;
2248 
2249  default:
2250  return DTERR_BAD_FORMAT;
2251  }
2252  break;
2253 
2254  default:
2255  return DTERR_BAD_FORMAT;
2256  }
2257 
2258  if (tmask & fmask)
2259  return DTERR_BAD_FORMAT;
2260  fmask |= tmask;
2261  } /* end loop over fields */
2262 
2263  /* reject if prefix type appeared and was never handled */
2264  if (ptype != 0)
2265  return DTERR_BAD_FORMAT;
2266 
2267  /* do final checking/adjustment of Y/M/D fields */
2268  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
2269  if (dterr)
2270  return dterr;
2271 
2272  /* handle AM/PM */
2273  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
2274  return DTERR_FIELD_OVERFLOW;
2275  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
2276  tm->tm_hour = 0;
2277  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
2278  tm->tm_hour += HOURS_PER_DAY / 2;
2279 
2280  /* check for time overflow */
2281  if (time_overflows(tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec))
2282  return DTERR_FIELD_OVERFLOW;
2283 
2284  if ((fmask & DTK_TIME_M) != DTK_TIME_M)
2285  return DTERR_BAD_FORMAT;
2286 
2287  /*
2288  * If we had a full timezone spec, compute the offset (we could not do it
2289  * before, because we may need the date to resolve DST status).
2290  */
2291  if (namedTz != NULL)
2292  {
2293  long int gmtoff;
2294 
2295  /* daylight savings time modifier disallowed with full TZ */
2296  if (fmask & DTK_M(DTZMOD))
2297  return DTERR_BAD_FORMAT;
2298 
2299  /* if non-DST zone, we do not need to know the date */
2300  if (pg_get_timezone_offset(namedTz, &gmtoff))
2301  {
2302  *tzp = -(int) gmtoff;
2303  }
2304  else
2305  {
2306  /* a date has to be specified */
2307  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2308  return DTERR_BAD_FORMAT;
2309  *tzp = DetermineTimeZoneOffset(tm, namedTz);
2310  }
2311  }
2312 
2313  /*
2314  * Likewise, if we had a dynamic timezone abbreviation, resolve it now.
2315  */
2316  if (abbrevTz != NULL)
2317  {
2318  struct pg_tm tt,
2319  *tmp = &tt;
2320 
2321  /*
2322  * daylight savings time modifier but no standard timezone? then error
2323  */
2324  if (fmask & DTK_M(DTZMOD))
2325  return DTERR_BAD_FORMAT;
2326 
2327  if ((fmask & DTK_DATE_M) == 0)
2328  GetCurrentDateTime(tmp);
2329  else
2330  {
2331  /* a date has to be specified */
2332  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2333  return DTERR_BAD_FORMAT;
2334  tmp->tm_year = tm->tm_year;
2335  tmp->tm_mon = tm->tm_mon;
2336  tmp->tm_mday = tm->tm_mday;
2337  }
2338  tmp->tm_hour = tm->tm_hour;
2339  tmp->tm_min = tm->tm_min;
2340  tmp->tm_sec = tm->tm_sec;
2341  *tzp = DetermineTimeZoneAbbrevOffset(tmp, abbrev, abbrevTz);
2342  tm->tm_isdst = tmp->tm_isdst;
2343  }
2344 
2345  /* timezone not specified? then use session timezone */
2346  if (tzp != NULL && !(fmask & DTK_M(TZ)))
2347  {
2348  struct pg_tm tt,
2349  *tmp = &tt;
2350 
2351  /*
2352  * daylight savings time modifier but no standard timezone? then error
2353  */
2354  if (fmask & DTK_M(DTZMOD))
2355  return DTERR_BAD_FORMAT;
2356 
2357  if ((fmask & DTK_DATE_M) == 0)
2358  GetCurrentDateTime(tmp);
2359  else
2360  {
2361  /* a date has to be specified */
2362  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2363  return DTERR_BAD_FORMAT;
2364  tmp->tm_year = tm->tm_year;
2365  tmp->tm_mon = tm->tm_mon;
2366  tmp->tm_mday = tm->tm_mday;
2367  }
2368  tmp->tm_hour = tm->tm_hour;
2369  tmp->tm_min = tm->tm_min;
2370  tmp->tm_sec = tm->tm_sec;
2372  tm->tm_isdst = tmp->tm_isdst;
2373  }
2374 
2375  return 0;
2376 }
2377 
2378 /* DecodeDate()
2379  * Decode date string which includes delimiters.
2380  * Return 0 if okay, a DTERR code if not.
2381  *
2382  * str: field to be parsed
2383  * fmask: bitmask for field types already seen
2384  * *tmask: receives bitmask for fields found here
2385  * *is2digits: set to true if we find 2-digit year
2386  * *tm: field values are stored into appropriate members of this struct
2387  */
2388 static int
2389 DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
2390  struct pg_tm *tm)
2391 {
2392  fsec_t fsec;
2393  int nf = 0;
2394  int i,
2395  len;
2396  int dterr;
2397  bool haveTextMonth = false;
2398  int type,
2399  val,
2400  dmask = 0;
2401  char *field[MAXDATEFIELDS];
2402 
2403  *tmask = 0;
2404 
2405  /* parse this string... */
2406  while (*str != '\0' && nf < MAXDATEFIELDS)
2407  {
2408  /* skip field separators */
2409  while (*str != '\0' && !isalnum((unsigned char) *str))
2410  str++;
2411 
2412  if (*str == '\0')
2413  return DTERR_BAD_FORMAT; /* end of string after separator */
2414 
2415  field[nf] = str;
2416  if (isdigit((unsigned char) *str))
2417  {
2418  while (isdigit((unsigned char) *str))
2419  str++;
2420  }
2421  else if (isalpha((unsigned char) *str))
2422  {
2423  while (isalpha((unsigned char) *str))
2424  str++;
2425  }
2426 
2427  /* Just get rid of any non-digit, non-alpha characters... */
2428  if (*str != '\0')
2429  *str++ = '\0';
2430  nf++;
2431  }
2432 
2433  /* look first for text fields, since that will be unambiguous month */
2434  for (i = 0; i < nf; i++)
2435  {
2436  if (isalpha((unsigned char) *field[i]))
2437  {
2438  type = DecodeSpecial(i, field[i], &val);
2439  if (type == IGNORE_DTF)
2440  continue;
2441 
2442  dmask = DTK_M(type);
2443  switch (type)
2444  {
2445  case MONTH:
2446  tm->tm_mon = val;
2447  haveTextMonth = true;
2448  break;
2449 
2450  default:
2451  return DTERR_BAD_FORMAT;
2452  }
2453  if (fmask & dmask)
2454  return DTERR_BAD_FORMAT;
2455 
2456  fmask |= dmask;
2457  *tmask |= dmask;
2458 
2459  /* mark this field as being completed */
2460  field[i] = NULL;
2461  }
2462  }
2463 
2464  /* now pick up remaining numeric fields */
2465  for (i = 0; i < nf; i++)
2466  {
2467  if (field[i] == NULL)
2468  continue;
2469 
2470  if ((len = strlen(field[i])) <= 0)
2471  return DTERR_BAD_FORMAT;
2472 
2473  dterr = DecodeNumber(len, field[i], haveTextMonth, fmask,
2474  &dmask, tm,
2475  &fsec, is2digits);
2476  if (dterr)
2477  return dterr;
2478 
2479  if (fmask & dmask)
2480  return DTERR_BAD_FORMAT;
2481 
2482  fmask |= dmask;
2483  *tmask |= dmask;
2484  }
2485 
2486  if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
2487  return DTERR_BAD_FORMAT;
2488 
2489  /* validation of the field values must wait until ValidateDate() */
2490 
2491  return 0;
2492 }
2493 
2494 /* ValidateDate()
2495  * Check valid year/month/day values, handle BC and DOY cases
2496  * Return 0 if okay, a DTERR code if not.
2497  */
2498 int
2499 ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
2500  struct pg_tm *tm)
2501 {
2502  if (fmask & DTK_M(YEAR))
2503  {
2504  if (isjulian)
2505  {
2506  /* tm_year is correct and should not be touched */
2507  }
2508  else if (bc)
2509  {
2510  /* there is no year zero in AD/BC notation */
2511  if (tm->tm_year <= 0)
2512  return DTERR_FIELD_OVERFLOW;
2513  /* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
2514  tm->tm_year = -(tm->tm_year - 1);
2515  }
2516  else if (is2digits)
2517  {
2518  /* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
2519  if (tm->tm_year < 0) /* just paranoia */
2520  return DTERR_FIELD_OVERFLOW;
2521  if (tm->tm_year < 70)
2522  tm->tm_year += 2000;
2523  else if (tm->tm_year < 100)
2524  tm->tm_year += 1900;
2525  }
2526  else
2527  {
2528  /* there is no year zero in AD/BC notation */
2529  if (tm->tm_year <= 0)
2530  return DTERR_FIELD_OVERFLOW;
2531  }
2532  }
2533 
2534  /* now that we have correct year, decode DOY */
2535  if (fmask & DTK_M(DOY))
2536  {
2537  j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
2538  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2539  }
2540 
2541  /* check for valid month */
2542  if (fmask & DTK_M(MONTH))
2543  {
2544  if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
2545  return DTERR_MD_FIELD_OVERFLOW;
2546  }
2547 
2548  /* minimal check for valid day */
2549  if (fmask & DTK_M(DAY))
2550  {
2551  if (tm->tm_mday < 1 || tm->tm_mday > 31)
2552  return DTERR_MD_FIELD_OVERFLOW;
2553  }
2554 
2555  if ((fmask & DTK_DATE_M) == DTK_DATE_M)
2556  {
2557  /*
2558  * Check for valid day of month, now that we know for sure the month
2559  * and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
2560  * unlikely that "Feb 29" is a YMD-order error.
2561  */
2562  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
2563  return DTERR_FIELD_OVERFLOW;
2564  }
2565 
2566  return 0;
2567 }
2568 
2569 
2570 /* DecodeTimeCommon()
2571  * Decode time string which includes delimiters.
2572  * Return 0 if okay, a DTERR code if not.
2573  * tmask and itm are output parameters.
2574  *
2575  * This code is shared between the timestamp and interval cases.
2576  * We return a struct pg_itm (of which only the tm_usec, tm_sec, tm_min,
2577  * and tm_hour fields are used) and let the wrapper functions below
2578  * convert and range-check as necessary.
2579  */
2580 static int
2581 DecodeTimeCommon(char *str, int fmask, int range,
2582  int *tmask, struct pg_itm *itm)
2583 {
2584  char *cp;
2585  int dterr;
2586  fsec_t fsec = 0;
2587 
2588  *tmask = DTK_TIME_M;
2589 
2590  errno = 0;
2591  itm->tm_hour = strtoi64(str, &cp, 10);
2592  if (errno == ERANGE)
2593  return DTERR_FIELD_OVERFLOW;
2594  if (*cp != ':')
2595  return DTERR_BAD_FORMAT;
2596  errno = 0;
2597  itm->tm_min = strtoint(cp + 1, &cp, 10);
2598  if (errno == ERANGE)
2599  return DTERR_FIELD_OVERFLOW;
2600  if (*cp == '\0')
2601  {
2602  itm->tm_sec = 0;
2603  /* If it's a MINUTE TO SECOND interval, take 2 fields as being mm:ss */
2605  {
2606  if (itm->tm_hour > INT_MAX || itm->tm_hour < INT_MIN)
2607  return DTERR_FIELD_OVERFLOW;
2608  itm->tm_sec = itm->tm_min;
2609  itm->tm_min = (int) itm->tm_hour;
2610  itm->tm_hour = 0;
2611  }
2612  }
2613  else if (*cp == '.')
2614  {
2615  /* always assume mm:ss.sss is MINUTE TO SECOND */
2616  dterr = ParseFractionalSecond(cp, &fsec);
2617  if (dterr)
2618  return dterr;
2619  if (itm->tm_hour > INT_MAX || itm->tm_hour < INT_MIN)
2620  return DTERR_FIELD_OVERFLOW;
2621  itm->tm_sec = itm->tm_min;
2622  itm->tm_min = (int) itm->tm_hour;
2623  itm->tm_hour = 0;
2624  }
2625  else if (*cp == ':')
2626  {
2627  errno = 0;
2628  itm->tm_sec = strtoint(cp + 1, &cp, 10);
2629  if (errno == ERANGE)
2630  return DTERR_FIELD_OVERFLOW;
2631  if (*cp == '.')
2632  {
2633  dterr = ParseFractionalSecond(cp, &fsec);
2634  if (dterr)
2635  return dterr;
2636  }
2637  else if (*cp != '\0')
2638  return DTERR_BAD_FORMAT;
2639  }
2640  else
2641  return DTERR_BAD_FORMAT;
2642 
2643  /* do a sanity check; but caller must check the range of tm_hour */
2644  if (itm->tm_hour < 0 ||
2645  itm->tm_min < 0 || itm->tm_min > MINS_PER_HOUR - 1 ||
2646  itm->tm_sec < 0 || itm->tm_sec > SECS_PER_MINUTE ||
2647  fsec < 0 || fsec > USECS_PER_SEC)
2648  return DTERR_FIELD_OVERFLOW;
2649 
2650  itm->tm_usec = (int) fsec;
2651 
2652  return 0;
2653 }
2654 
2655 /* DecodeTime()
2656  * Decode time string which includes delimiters.
2657  * Return 0 if okay, a DTERR code if not.
2658  *
2659  * This version is used for timestamps. The results are returned into
2660  * the tm_hour/tm_min/tm_sec fields of *tm, and microseconds into *fsec.
2661  */
2662 static int
2663 DecodeTime(char *str, int fmask, int range,
2664  int *tmask, struct pg_tm *tm, fsec_t *fsec)
2665 {
2666  struct pg_itm itm;
2667  int dterr;
2668 
2669  dterr = DecodeTimeCommon(str, fmask, range,
2670  tmask, &itm);
2671  if (dterr)
2672  return dterr;
2673 
2674  if (itm.tm_hour > INT_MAX)
2675  return DTERR_FIELD_OVERFLOW;
2676  tm->tm_hour = (int) itm.tm_hour;
2677  tm->tm_min = itm.tm_min;
2678  tm->tm_sec = itm.tm_sec;
2679  *fsec = itm.tm_usec;
2680 
2681  return 0;
2682 }
2683 
2684 /* DecodeTimeForInterval()
2685  * Decode time string which includes delimiters.
2686  * Return 0 if okay, a DTERR code if not.
2687  *
2688  * This version is used for intervals. The results are returned into
2689  * itm_in->tm_usec.
2690  */
2691 static int
2692 DecodeTimeForInterval(char *str, int fmask, int range,
2693  int *tmask, struct pg_itm_in *itm_in)
2694 {
2695  struct pg_itm itm;
2696  int dterr;
2697 
2698  dterr = DecodeTimeCommon(str, fmask, range,
2699  tmask, &itm);
2700  if (dterr)
2701  return dterr;
2702 
2703  itm_in->tm_usec = itm.tm_usec;
2704  if (!int64_multiply_add(itm.tm_hour, USECS_PER_HOUR, &itm_in->tm_usec) ||
2707  return DTERR_FIELD_OVERFLOW;
2708 
2709  return 0;
2710 }
2711 
2712 
2713 /* DecodeNumber()
2714  * Interpret plain numeric field as a date value in context.
2715  * Return 0 if okay, a DTERR code if not.
2716  */
2717 static int
2718 DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask,
2719  int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
2720 {
2721  int val;
2722  char *cp;
2723  int dterr;
2724 
2725  *tmask = 0;
2726 
2727  errno = 0;
2728  val = strtoint(str, &cp, 10);
2729  if (errno == ERANGE)
2730  return DTERR_FIELD_OVERFLOW;
2731  if (cp == str)
2732  return DTERR_BAD_FORMAT;
2733 
2734  if (*cp == '.')
2735  {
2736  /*
2737  * More than two digits before decimal point? Then could be a date or
2738  * a run-together time: 2001.360 20011225 040506.789
2739  */
2740  if (cp - str > 2)
2741  {
2742  dterr = DecodeNumberField(flen, str,
2743  (fmask | DTK_DATE_M),
2744  tmask, tm,
2745  fsec, is2digits);
2746  if (dterr < 0)
2747  return dterr;
2748  return 0;
2749  }
2750 
2751  dterr = ParseFractionalSecond(cp, fsec);
2752  if (dterr)
2753  return dterr;
2754  }
2755  else if (*cp != '\0')
2756  return DTERR_BAD_FORMAT;
2757 
2758  /* Special case for day of year */
2759  if (flen == 3 && (fmask & DTK_DATE_M) == DTK_M(YEAR) && val >= 1 &&
2760  val <= 366)
2761  {
2762  *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
2763  tm->tm_yday = val;
2764  /* tm_mon and tm_mday can't actually be set yet ... */
2765  return 0;
2766  }
2767 
2768  /* Switch based on what we have so far */
2769  switch (fmask & DTK_DATE_M)
2770  {
2771  case 0:
2772 
2773  /*
2774  * Nothing so far; make a decision about what we think the input
2775  * is. There used to be lots of heuristics here, but the
2776  * consensus now is to be paranoid. It *must* be either
2777  * YYYY-MM-DD (with a more-than-two-digit year field), or the
2778  * field order defined by DateOrder.
2779  */
2780  if (flen >= 3 || DateOrder == DATEORDER_YMD)
2781  {
2782  *tmask = DTK_M(YEAR);
2783  tm->tm_year = val;
2784  }
2785  else if (DateOrder == DATEORDER_DMY)
2786  {
2787  *tmask = DTK_M(DAY);
2788  tm->tm_mday = val;
2789  }
2790  else
2791  {
2792  *tmask = DTK_M(MONTH);
2793  tm->tm_mon = val;
2794  }
2795  break;
2796 
2797  case (DTK_M(YEAR)):
2798  /* Must be at second field of YY-MM-DD */
2799  *tmask = DTK_M(MONTH);
2800  tm->tm_mon = val;
2801  break;
2802 
2803  case (DTK_M(MONTH)):
2804  if (haveTextMonth)
2805  {
2806  /*
2807  * We are at the first numeric field of a date that included a
2808  * textual month name. We want to support the variants
2809  * MON-DD-YYYY, DD-MON-YYYY, and YYYY-MON-DD as unambiguous
2810  * inputs. We will also accept MON-DD-YY or DD-MON-YY in
2811  * either DMY or MDY modes, as well as YY-MON-DD in YMD mode.
2812  */
2813  if (flen >= 3 || DateOrder == DATEORDER_YMD)
2814  {
2815  *tmask = DTK_M(YEAR);
2816  tm->tm_year = val;
2817  }
2818  else
2819  {
2820  *tmask = DTK_M(DAY);
2821  tm->tm_mday = val;
2822  }
2823  }
2824  else
2825  {
2826  /* Must be at second field of MM-DD-YY */
2827  *tmask = DTK_M(DAY);
2828  tm->tm_mday = val;
2829  }
2830  break;
2831 
2832  case (DTK_M(YEAR) | DTK_M(MONTH)):
2833  if (haveTextMonth)
2834  {
2835  /* Need to accept DD-MON-YYYY even in YMD mode */
2836  if (flen >= 3 && *is2digits)
2837  {
2838  /* Guess that first numeric field is day was wrong */
2839  *tmask = DTK_M(DAY); /* YEAR is already set */
2840  tm->tm_mday = tm->tm_year;
2841  tm->tm_year = val;
2842  *is2digits = false;
2843  }
2844  else
2845  {
2846  *tmask = DTK_M(DAY);
2847  tm->tm_mday = val;
2848  }
2849  }
2850  else
2851  {
2852  /* Must be at third field of YY-MM-DD */
2853  *tmask = DTK_M(DAY);
2854  tm->tm_mday = val;
2855  }
2856  break;
2857 
2858  case (DTK_M(DAY)):
2859  /* Must be at second field of DD-MM-YY */
2860  *tmask = DTK_M(MONTH);
2861  tm->tm_mon = val;
2862  break;
2863 
2864  case (DTK_M(MONTH) | DTK_M(DAY)):
2865  /* Must be at third field of DD-MM-YY or MM-DD-YY */
2866  *tmask = DTK_M(YEAR);
2867  tm->tm_year = val;
2868  break;
2869 
2870  case (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY)):
2871  /* we have all the date, so it must be a time field */
2872  dterr = DecodeNumberField(flen, str, fmask,
2873  tmask, tm,
2874  fsec, is2digits);
2875  if (dterr < 0)
2876  return dterr;
2877  return 0;
2878 
2879  default:
2880  /* Anything else is bogus input */
2881  return DTERR_BAD_FORMAT;
2882  }
2883 
2884  /*
2885  * When processing a year field, mark it for adjustment if it's only one
2886  * or two digits.
2887  */
2888  if (*tmask == DTK_M(YEAR))
2889  *is2digits = (flen <= 2);
2890 
2891  return 0;
2892 }
2893 
2894 
2895 /* DecodeNumberField()
2896  * Interpret numeric string as a concatenated date or time field.
2897  * Return a DTK token (>= 0) if successful, a DTERR code (< 0) if not.
2898  *
2899  * Use the context of previously decoded fields to help with
2900  * the interpretation.
2901  */
2902 static int
2903 DecodeNumberField(int len, char *str, int fmask,
2904  int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
2905 {
2906  char *cp;
2907 
2908  /*
2909  * Have a decimal point? Then this is a date or something with a seconds
2910  * field...
2911  */
2912  if ((cp = strchr(str, '.')) != NULL)
2913  {
2914  /*
2915  * Can we use ParseFractionalSecond here? Not clear whether trailing
2916  * junk should be rejected ...
2917  */
2918  if (cp[1] == '\0')
2919  {
2920  /* avoid assuming that strtod will accept "." */
2921  *fsec = 0;
2922  }
2923  else
2924  {
2925  double frac;
2926 
2927  errno = 0;
2928  frac = strtod(cp, NULL);
2929  if (errno != 0)
2930  return DTERR_BAD_FORMAT;
2931  *fsec = rint(frac * 1000000);
2932  }
2933  /* Now truncate off the fraction for further processing */
2934  *cp = '\0';
2935  len = strlen(str);
2936  }
2937  /* No decimal point and no complete date yet? */
2938  else if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2939  {
2940  if (len >= 6)
2941  {
2942  *tmask = DTK_DATE_M;
2943 
2944  /*
2945  * Start from end and consider first 2 as Day, next 2 as Month,
2946  * and the rest as Year.
2947  */
2948  tm->tm_mday = atoi(str + (len - 2));
2949  *(str + (len - 2)) = '\0';
2950  tm->tm_mon = atoi(str + (len - 4));
2951  *(str + (len - 4)) = '\0';
2952  tm->tm_year = atoi(str);
2953  if ((len - 4) == 2)
2954  *is2digits = true;
2955 
2956  return DTK_DATE;
2957  }
2958  }
2959 
2960  /* not all time fields are specified? */
2961  if ((fmask & DTK_TIME_M) != DTK_TIME_M)
2962  {
2963  /* hhmmss */
2964  if (len == 6)
2965  {
2966  *tmask = DTK_TIME_M;
2967  tm->tm_sec = atoi(str + 4);
2968  *(str + 4) = '\0';
2969  tm->tm_min = atoi(str + 2);
2970  *(str + 2) = '\0';
2971  tm->tm_hour = atoi(str);
2972 
2973  return DTK_TIME;
2974  }
2975  /* hhmm? */
2976  else if (len == 4)
2977  {
2978  *tmask = DTK_TIME_M;
2979  tm->tm_sec = 0;
2980  tm->tm_min = atoi(str + 2);
2981  *(str + 2) = '\0';
2982  tm->tm_hour = atoi(str);
2983 
2984  return DTK_TIME;
2985  }
2986  }
2987 
2988  return DTERR_BAD_FORMAT;
2989 }
2990 
2991 
2992 /* DecodeTimezone()
2993  * Interpret string as a numeric timezone.
2994  *
2995  * Return 0 if okay (and set *tzp), a DTERR code if not okay.
2996  */
2997 int
2998 DecodeTimezone(const char *str, int *tzp)
2999 {
3000  int tz;
3001  int hr,
3002  min,
3003  sec = 0;
3004  char *cp;
3005 
3006  /* leading character must be "+" or "-" */
3007  if (*str != '+' && *str != '-')
3008  return DTERR_BAD_FORMAT;
3009 
3010  errno = 0;
3011  hr = strtoint(str + 1, &cp, 10);
3012  if (errno == ERANGE)
3013  return DTERR_TZDISP_OVERFLOW;
3014 
3015  /* explicit delimiter? */
3016  if (*cp == ':')
3017  {
3018  errno = 0;
3019  min = strtoint(cp + 1, &cp, 10);
3020  if (errno == ERANGE)
3021  return DTERR_TZDISP_OVERFLOW;
3022  if (*cp == ':')
3023  {
3024  errno = 0;
3025  sec = strtoint(cp + 1, &cp, 10);
3026  if (errno == ERANGE)
3027  return DTERR_TZDISP_OVERFLOW;
3028  }
3029  }
3030  /* otherwise, might have run things together... */
3031  else if (*cp == '\0' && strlen(str) > 3)
3032  {
3033  min = hr % 100;
3034  hr = hr / 100;
3035  /* we could, but don't, support a run-together hhmmss format */
3036  }
3037  else
3038  min = 0;
3039 
3040  /* Range-check the values; see notes in datatype/timestamp.h */
3041  if (hr < 0 || hr > MAX_TZDISP_HOUR)
3042  return DTERR_TZDISP_OVERFLOW;
3043  if (min < 0 || min >= MINS_PER_HOUR)
3044  return DTERR_TZDISP_OVERFLOW;
3045  if (sec < 0 || sec >= SECS_PER_MINUTE)
3046  return DTERR_TZDISP_OVERFLOW;
3047 
3048  tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
3049  if (*str == '-')
3050  tz = -tz;
3051 
3052  *tzp = -tz;
3053 
3054  if (*cp != '\0')
3055  return DTERR_BAD_FORMAT;
3056 
3057  return 0;
3058 }
3059 
3060 
3061 /* DecodeTimezoneAbbrev()
3062  * Interpret string as a timezone abbreviation, if possible.
3063  *
3064  * Sets *ftype to an abbreviation type (TZ, DTZ, or DYNTZ), or UNKNOWN_FIELD if
3065  * string is not any known abbreviation. On success, set *offset and *tz to
3066  * represent the UTC offset (for TZ or DTZ) or underlying zone (for DYNTZ).
3067  * Note that full timezone names (such as America/New_York) are not handled
3068  * here, mostly for historical reasons.
3069  *
3070  * The function result is 0 or a DTERR code; in the latter case, *extra
3071  * is filled as needed. Note that unknown-abbreviation is not considered
3072  * an error case. Also note that many callers assume that the DTERR code
3073  * is one that DateTimeParseError does not require "str" or "datatype"
3074  * strings for.
3075  *
3076  * Given string must be lowercased already.
3077  *
3078  * Implement a cache lookup since it is likely that dates
3079  * will be related in format.
3080  */
3081 int
3082 DecodeTimezoneAbbrev(int field, const char *lowtoken,
3083  int *ftype, int *offset, pg_tz **tz,
3084  DateTimeErrorExtra *extra)
3085 {
3086  const datetkn *tp;
3087 
3088  tp = abbrevcache[field];
3089  /* use strncmp so that we match truncated tokens */
3090  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3091  {
3092  if (zoneabbrevtbl)
3093  tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
3095  else
3096  tp = NULL;
3097  }
3098  if (tp == NULL)
3099  {
3100  *ftype = UNKNOWN_FIELD;
3101  *offset = 0;
3102  *tz = NULL;
3103  }
3104  else
3105  {
3106  abbrevcache[field] = tp;
3107  *ftype = tp->type;
3108  if (tp->type == DYNTZ)
3109  {
3110  *offset = 0;
3111  *tz = FetchDynamicTimeZone(zoneabbrevtbl, tp, extra);
3112  if (*tz == NULL)
3113  return DTERR_BAD_ZONE_ABBREV;
3114  }
3115  else
3116  {
3117  *offset = tp->value;
3118  *tz = NULL;
3119  }
3120  }
3121 
3122  return 0;
3123 }
3124 
3125 
3126 /* DecodeSpecial()
3127  * Decode text string using lookup table.
3128  *
3129  * Recognizes the keywords listed in datetktbl.
3130  * Note: at one time this would also recognize timezone abbreviations,
3131  * but no more; use DecodeTimezoneAbbrev for that.
3132  *
3133  * Given string must be lowercased already.
3134  *
3135  * Implement a cache lookup since it is likely that dates
3136  * will be related in format.
3137  */
3138 int
3139 DecodeSpecial(int field, const char *lowtoken, int *val)
3140 {
3141  int type;
3142  const datetkn *tp;
3143 
3144  tp = datecache[field];
3145  /* use strncmp so that we match truncated tokens */
3146  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3147  {
3148  tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
3149  }
3150  if (tp == NULL)
3151  {
3152  type = UNKNOWN_FIELD;
3153  *val = 0;
3154  }
3155  else
3156  {
3157  datecache[field] = tp;
3158  type = tp->type;
3159  *val = tp->value;
3160  }
3161 
3162  return type;
3163 }
3164 
3165 
3166 /* DecodeTimezoneName()
3167  * Interpret string as a timezone abbreviation or name.
3168  * Throw error if the name is not recognized.
3169  *
3170  * The return value indicates what kind of zone identifier it is:
3171  * TZNAME_FIXED_OFFSET: fixed offset from UTC
3172  * TZNAME_DYNTZ: dynamic timezone abbreviation
3173  * TZNAME_ZONE: full tzdb zone name
3174  *
3175  * For TZNAME_FIXED_OFFSET, *offset receives the UTC offset (in seconds,
3176  * with ISO sign convention: positive is east of Greenwich).
3177  * For the other two cases, *tz receives the timezone struct representing
3178  * the zone name or the abbreviation's underlying zone.
3179  */
3180 int
3181 DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
3182 {
3183  char *lowzone;
3184  int dterr,
3185  type;
3186  DateTimeErrorExtra extra;
3187 
3188  /*
3189  * First we look in the timezone abbreviation table (to handle cases like
3190  * "EST"), and if that fails, we look in the timezone database (to handle
3191  * cases like "America/New_York"). This matches the order in which
3192  * timestamp input checks the cases; it's important because the timezone
3193  * database unwisely uses a few zone names that are identical to offset
3194  * abbreviations.
3195  */
3196 
3197  /* DecodeTimezoneAbbrev requires lowercase input */
3198  lowzone = downcase_truncate_identifier(tzname,
3199  strlen(tzname),
3200  false);
3201 
3202  dterr = DecodeTimezoneAbbrev(0, lowzone, &type, offset, tz, &extra);
3203  if (dterr)
3204  DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
3205 
3206  if (type == TZ || type == DTZ)
3207  {
3208  /* fixed-offset abbreviation, return the offset */
3209  return TZNAME_FIXED_OFFSET;
3210  }
3211  else if (type == DYNTZ)
3212  {
3213  /* dynamic-offset abbreviation, return its referenced timezone */
3214  return TZNAME_DYNTZ;
3215  }
3216  else
3217  {
3218  /* try it as a full zone name */
3219  *tz = pg_tzset(tzname);
3220  if (*tz == NULL)
3221  ereport(ERROR,
3222  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3223  errmsg("time zone \"%s\" not recognized", tzname)));
3224  return TZNAME_ZONE;
3225  }
3226 }
3227 
3228 /* DecodeTimezoneNameToTz()
3229  * Interpret string as a timezone abbreviation or name.
3230  * Throw error if the name is not recognized.
3231  *
3232  * This is a simple wrapper for DecodeTimezoneName that produces a pg_tz *
3233  * result in all cases.
3234  */
3235 pg_tz *
3236 DecodeTimezoneNameToTz(const char *tzname)
3237 {
3238  pg_tz *result;
3239  int offset;
3240 
3241  if (DecodeTimezoneName(tzname, &offset, &result) == TZNAME_FIXED_OFFSET)
3242  {
3243  /* fixed-offset abbreviation, get a pg_tz descriptor for that */
3244  result = pg_tzset_offset(-offset); /* flip to POSIX sign convention */
3245  }
3246  return result;
3247 }
3248 
3249 
3250 /* ClearPgItmIn
3251  *
3252  * Zero out a pg_itm_in
3253  */
3254 static inline void
3255 ClearPgItmIn(struct pg_itm_in *itm_in)
3256 {
3257  itm_in->tm_usec = 0;
3258  itm_in->tm_mday = 0;
3259  itm_in->tm_mon = 0;
3260  itm_in->tm_year = 0;
3261 }
3262 
3263 
3264 /* DecodeInterval()
3265  * Interpret previously parsed fields for general time interval.
3266  * Returns 0 if successful, DTERR code if bogus input detected.
3267  * dtype and itm_in are output parameters.
3268  *
3269  * Allow "date" field DTK_DATE since this could be just
3270  * an unsigned floating point number. - thomas 1997-11-16
3271  *
3272  * Allow ISO-style time span, with implicit units on number of days
3273  * preceding an hh:mm:ss field. - thomas 1998-04-30
3274  */
3275 int
3276 DecodeInterval(char **field, int *ftype, int nf, int range,
3277  int *dtype, struct pg_itm_in *itm_in)
3278 {
3279  bool force_negative = false;
3280  bool is_before = false;
3281  bool parsing_unit_val = false;
3282  char *cp;
3283  int fmask = 0,
3284  tmask,
3285  type,
3286  uval;
3287  int i;
3288  int dterr;
3289  int64 val;
3290  double fval;
3291 
3292  *dtype = DTK_DELTA;
3293  type = IGNORE_DTF;
3294  ClearPgItmIn(itm_in);
3295 
3296  /*----------
3297  * The SQL standard defines the interval literal
3298  * '-1 1:00:00'
3299  * to mean "negative 1 days and negative 1 hours", while Postgres
3300  * traditionally treats this as meaning "negative 1 days and positive
3301  * 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
3302  * to all fields if there are no other explicit signs.
3303  *
3304  * We leave the signs alone if there are additional explicit signs.
3305  * This protects us against misinterpreting postgres-style dump output,
3306  * since the postgres-style output code has always put an explicit sign on
3307  * all fields following a negative field. But note that SQL-spec output
3308  * is ambiguous and can be misinterpreted on load! (So it's best practice
3309  * to dump in postgres style, not SQL style.)
3310  *----------
3311  */
3312  if (IntervalStyle == INTSTYLE_SQL_STANDARD && nf > 0 && *field[0] == '-')
3313  {
3314  force_negative = true;
3315  /* Check for additional explicit signs */
3316  for (i = 1; i < nf; i++)
3317  {
3318  if (*field[i] == '-' || *field[i] == '+')
3319  {
3320  force_negative = false;
3321  break;
3322  }
3323  }
3324  }
3325 
3326  /* read through list backwards to pick up units before values */
3327  for (i = nf - 1; i >= 0; i--)
3328  {
3329  switch (ftype[i])
3330  {
3331  case DTK_TIME:
3332  dterr = DecodeTimeForInterval(field[i], fmask, range,
3333  &tmask, itm_in);
3334  if (dterr)
3335  return dterr;
3336  if (force_negative &&
3337  itm_in->tm_usec > 0)
3338  itm_in->tm_usec = -itm_in->tm_usec;
3339  type = DTK_DAY;
3340  parsing_unit_val = false;
3341  break;
3342 
3343  case DTK_TZ:
3344 
3345  /*
3346  * Timezone means a token with a leading sign character and at
3347  * least one digit; there could be ':', '.', '-' embedded in
3348  * it as well.
3349  */
3350  Assert(*field[i] == '-' || *field[i] == '+');
3351 
3352  /*
3353  * Check for signed hh:mm or hh:mm:ss. If so, process exactly
3354  * like DTK_TIME case above, plus handling the sign.
3355  */
3356  if (strchr(field[i] + 1, ':') != NULL &&
3357  DecodeTimeForInterval(field[i] + 1, fmask, range,
3358  &tmask, itm_in) == 0)
3359  {
3360  if (*field[i] == '-')
3361  {
3362  /* flip the sign on time field */
3363  if (itm_in->tm_usec == PG_INT64_MIN)
3364  return DTERR_FIELD_OVERFLOW;
3365  itm_in->tm_usec = -itm_in->tm_usec;
3366  }
3367 
3368  if (force_negative &&
3369  itm_in->tm_usec > 0)
3370  itm_in->tm_usec = -itm_in->tm_usec;
3371 
3372  /*
3373  * Set the next type to be a day, if units are not
3374  * specified. This handles the case of '1 +02:03' since we
3375  * are reading right to left.
3376  */
3377  type = DTK_DAY;
3378  parsing_unit_val = false;
3379  break;
3380  }
3381 
3382  /*
3383  * Otherwise, fall through to DTK_NUMBER case, which can
3384  * handle signed float numbers and signed year-month values.
3385  */
3386 
3387  /* FALLTHROUGH */
3388 
3389  case DTK_DATE:
3390  case DTK_NUMBER:
3391  if (type == IGNORE_DTF)
3392  {
3393  /* use typmod to decide what rightmost field is */
3394  switch (range)
3395  {
3396  case INTERVAL_MASK(YEAR):
3397  type = DTK_YEAR;
3398  break;
3399  case INTERVAL_MASK(MONTH):
3401  type = DTK_MONTH;
3402  break;
3403  case INTERVAL_MASK(DAY):
3404  type = DTK_DAY;
3405  break;
3406  case INTERVAL_MASK(HOUR):
3408  type = DTK_HOUR;
3409  break;
3410  case INTERVAL_MASK(MINUTE):
3413  type = DTK_MINUTE;
3414  break;
3415  case INTERVAL_MASK(SECOND):
3419  type = DTK_SECOND;
3420  break;
3421  default:
3422  type = DTK_SECOND;
3423  break;
3424  }
3425  }
3426 
3427  errno = 0;
3428  val = strtoi64(field[i], &cp, 10);
3429  if (errno == ERANGE)
3430  return DTERR_FIELD_OVERFLOW;
3431 
3432  if (*cp == '-')
3433  {
3434  /* SQL "years-months" syntax */
3435  int val2;
3436 
3437  val2 = strtoint(cp + 1, &cp, 10);
3438  if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
3439  return DTERR_FIELD_OVERFLOW;
3440  if (*cp != '\0')
3441  return DTERR_BAD_FORMAT;
3442  type = DTK_MONTH;
3443  if (*field[i] == '-')
3444  val2 = -val2;
3446  return DTERR_FIELD_OVERFLOW;
3447  if (pg_add_s64_overflow(val, val2, &val))
3448  return DTERR_FIELD_OVERFLOW;
3449  fval = 0;
3450  }
3451  else if (*cp == '.')
3452  {
3453  dterr = ParseFraction(cp, &fval);
3454  if (dterr)
3455  return dterr;
3456  if (*field[i] == '-')
3457  fval = -fval;
3458  }
3459  else if (*cp == '\0')
3460  fval = 0;
3461  else
3462  return DTERR_BAD_FORMAT;
3463 
3464  tmask = 0; /* DTK_M(type); */
3465 
3466  if (force_negative)
3467  {
3468  /* val and fval should be of same sign, but test anyway */
3469  if (val > 0)
3470  val = -val;
3471  if (fval > 0)
3472  fval = -fval;
3473  }
3474 
3475  switch (type)
3476  {
3477  case DTK_MICROSEC:
3478  if (!AdjustMicroseconds(val, fval, 1, itm_in))
3479  return DTERR_FIELD_OVERFLOW;
3480  tmask = DTK_M(MICROSECOND);
3481  break;
3482 
3483  case DTK_MILLISEC:
3484  if (!AdjustMicroseconds(val, fval, 1000, itm_in))
3485  return DTERR_FIELD_OVERFLOW;
3486  tmask = DTK_M(MILLISECOND);
3487  break;
3488 
3489  case DTK_SECOND:
3490  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3491  return DTERR_FIELD_OVERFLOW;
3492 
3493  /*
3494  * If any subseconds were specified, consider this
3495  * microsecond and millisecond input as well.
3496  */
3497  if (fval == 0)
3498  tmask = DTK_M(SECOND);
3499  else
3500  tmask = DTK_ALL_SECS_M;
3501  break;
3502 
3503  case DTK_MINUTE:
3504  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3505  return DTERR_FIELD_OVERFLOW;
3506  tmask = DTK_M(MINUTE);
3507  break;
3508 
3509  case DTK_HOUR:
3510  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3511  return DTERR_FIELD_OVERFLOW;
3512  tmask = DTK_M(HOUR);
3513  type = DTK_DAY; /* set for next field */
3514  break;
3515 
3516  case DTK_DAY:
3517  if (!AdjustDays(val, 1, itm_in) ||
3518  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3519  return DTERR_FIELD_OVERFLOW;
3520  tmask = DTK_M(DAY);
3521  break;
3522 
3523  case DTK_WEEK:
3524  if (!AdjustDays(val, 7, itm_in) ||
3525  !AdjustFractDays(fval, 7, itm_in))
3526  return DTERR_FIELD_OVERFLOW;
3527  tmask = DTK_M(WEEK);
3528  break;
3529 
3530  case DTK_MONTH:
3531  if (!AdjustMonths(val, itm_in) ||
3532  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3533  return DTERR_FIELD_OVERFLOW;
3534  tmask = DTK_M(MONTH);
3535  break;
3536 
3537  case DTK_YEAR:
3538  if (!AdjustYears(val, 1, itm_in) ||
3539  !AdjustFractYears(fval, 1, itm_in))
3540  return DTERR_FIELD_OVERFLOW;
3541  tmask = DTK_M(YEAR);
3542  break;
3543 
3544  case DTK_DECADE:
3545  if (!AdjustYears(val, 10, itm_in) ||
3546  !AdjustFractYears(fval, 10, itm_in))
3547  return DTERR_FIELD_OVERFLOW;
3548  tmask = DTK_M(DECADE);
3549  break;
3550 
3551  case DTK_CENTURY:
3552  if (!AdjustYears(val, 100, itm_in) ||
3553  !AdjustFractYears(fval, 100, itm_in))
3554  return DTERR_FIELD_OVERFLOW;
3555  tmask = DTK_M(CENTURY);
3556  break;
3557 
3558  case DTK_MILLENNIUM:
3559  if (!AdjustYears(val, 1000, itm_in) ||
3560  !AdjustFractYears(fval, 1000, itm_in))
3561  return DTERR_FIELD_OVERFLOW;
3562  tmask = DTK_M(MILLENNIUM);
3563  break;
3564 
3565  default:
3566  return DTERR_BAD_FORMAT;
3567  }
3568  parsing_unit_val = false;
3569  break;
3570 
3571  case DTK_STRING:
3572  case DTK_SPECIAL:
3573  /* reject consecutive unhandled units */
3574  if (parsing_unit_val)
3575  return DTERR_BAD_FORMAT;
3576  type = DecodeUnits(i, field[i], &uval);
3577  if (type == IGNORE_DTF)
3578  continue;
3579 
3580  tmask = 0; /* DTK_M(type); */
3581  switch (type)
3582  {
3583  case UNITS:
3584  type = uval;
3585  parsing_unit_val = true;
3586  break;
3587 
3588  case AGO:
3589 
3590  /*
3591  * "ago" is only allowed to appear at the end of the
3592  * interval.
3593  */
3594  if (i != nf - 1)
3595  return DTERR_BAD_FORMAT;
3596  is_before = true;
3597  type = uval;
3598  break;
3599 
3600  default:
3601  return DTERR_BAD_FORMAT;
3602  }
3603  break;
3604 
3605  default:
3606  return DTERR_BAD_FORMAT;
3607  }
3608 
3609  if (tmask & fmask)
3610  return DTERR_BAD_FORMAT;
3611  fmask |= tmask;
3612  }
3613 
3614  /* ensure that at least one time field has been found */
3615  if (fmask == 0)
3616  return DTERR_BAD_FORMAT;
3617 
3618  /* reject if unit appeared and was never handled */
3619  if (parsing_unit_val)
3620  return DTERR_BAD_FORMAT;
3621 
3622  /* finally, AGO negates everything */
3623  if (is_before)
3624  {
3625  if (itm_in->tm_usec == PG_INT64_MIN ||
3626  itm_in->tm_mday == INT_MIN ||
3627  itm_in->tm_mon == INT_MIN ||
3628  itm_in->tm_year == INT_MIN)
3629  return DTERR_FIELD_OVERFLOW;
3630 
3631  itm_in->tm_usec = -itm_in->tm_usec;
3632  itm_in->tm_mday = -itm_in->tm_mday;
3633  itm_in->tm_mon = -itm_in->tm_mon;
3634  itm_in->tm_year = -itm_in->tm_year;
3635  }
3636 
3637  return 0;
3638 }
3639 
3640 
3641 /*
3642  * Helper functions to avoid duplicated code in DecodeISO8601Interval.
3643  *
3644  * Parse a decimal value and break it into integer and fractional parts.
3645  * Set *endptr to end+1 of the parsed substring.
3646  * Returns 0 or DTERR code.
3647  */
3648 static int
3649 ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
3650 {
3651  double val;
3652 
3653  /*
3654  * Historically this has accepted anything that strtod() would take,
3655  * notably including "e" notation, so continue doing that. This is
3656  * slightly annoying because the precision of double is less than that of
3657  * int64, so we would lose accuracy for inputs larger than 2^53 or so.
3658  * However, historically we rejected inputs outside the int32 range,
3659  * making that concern moot. What we do now is reject abs(val) above
3660  * 1.0e15 (a round number a bit less than 2^50), so that any accepted
3661  * value will have an exact integer part, and thereby a fraction part with
3662  * abs(*fpart) less than 1. In the absence of field complaints it doesn't
3663  * seem worth working harder.
3664  */
3665  if (!(isdigit((unsigned char) *str) || *str == '-' || *str == '.'))
3666  return DTERR_BAD_FORMAT;
3667  errno = 0;
3668  val = strtod(str, endptr);
3669  /* did we not see anything that looks like a double? */
3670  if (*endptr == str || errno != 0)
3671  return DTERR_BAD_FORMAT;
3672  /* watch out for overflow, including infinities; reject NaN too */
3673  if (isnan(val) || val < -1.0e15 || val > 1.0e15)
3674  return DTERR_FIELD_OVERFLOW;
3675  /* be very sure we truncate towards zero (cf dtrunc()) */
3676  if (val >= 0)
3677  *ipart = (int64) floor(val);
3678  else
3679  *ipart = (int64) -floor(-val);
3680  *fpart = val - *ipart;
3681  /* Callers expect this to hold */
3682  Assert(*fpart > -1.0 && *fpart < 1.0);
3683  return 0;
3684 }
3685 
3686 /*
3687  * Determine number of integral digits in a valid ISO 8601 number field
3688  * (we should ignore sign and any fraction part)
3689  */
3690 static int
3691 ISO8601IntegerWidth(char *fieldstart)
3692 {
3693  /* We might have had a leading '-' */
3694  if (*fieldstart == '-')
3695  fieldstart++;
3696  return strspn(fieldstart, "0123456789");
3697 }
3698 
3699 
3700 /* DecodeISO8601Interval()
3701  * Decode an ISO 8601 time interval of the "format with designators"
3702  * (section 4.4.3.2) or "alternative format" (section 4.4.3.3)
3703  * Examples: P1D for 1 day
3704  * PT1H for 1 hour
3705  * P2Y6M7DT1H30M for 2 years, 6 months, 7 days 1 hour 30 min
3706  * P0002-06-07T01:30:00 the same value in alternative format
3707  *
3708  * Returns 0 if successful, DTERR code if bogus input detected.
3709  * Note: error code should be DTERR_BAD_FORMAT if input doesn't look like
3710  * ISO8601, otherwise this could cause unexpected error messages.
3711  * dtype and itm_in are output parameters.
3712  *
3713  * A couple exceptions from the spec:
3714  * - a week field ('W') may coexist with other units
3715  * - allows decimals in fields other than the least significant unit.
3716  */
3717 int
3719  int *dtype, struct pg_itm_in *itm_in)
3720 {
3721  bool datepart = true;
3722  bool havefield = false;
3723 
3724  *dtype = DTK_DELTA;
3725  ClearPgItmIn(itm_in);
3726 
3727  if (strlen(str) < 2 || str[0] != 'P')
3728  return DTERR_BAD_FORMAT;
3729 
3730  str++;
3731  while (*str)
3732  {
3733  char *fieldstart;
3734  int64 val;
3735  double fval;
3736  char unit;
3737  int dterr;
3738 
3739  if (*str == 'T') /* T indicates the beginning of the time part */
3740  {
3741  datepart = false;
3742  havefield = false;
3743  str++;
3744  continue;
3745  }
3746 
3747  fieldstart = str;
3748  dterr = ParseISO8601Number(str, &str, &val, &fval);
3749  if (dterr)
3750  return dterr;
3751 
3752  /*
3753  * Note: we could step off the end of the string here. Code below
3754  * *must* exit the loop if unit == '\0'.
3755  */
3756  unit = *str++;
3757 
3758  if (datepart)
3759  {
3760  switch (unit) /* before T: Y M W D */
3761  {
3762  case 'Y':
3763  if (!AdjustYears(val, 1, itm_in) ||
3764  !AdjustFractYears(fval, 1, itm_in))
3765  return DTERR_FIELD_OVERFLOW;
3766  break;
3767  case 'M':
3768  if (!AdjustMonths(val, itm_in) ||
3769  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3770  return DTERR_FIELD_OVERFLOW;
3771  break;
3772  case 'W':
3773  if (!AdjustDays(val, 7, itm_in) ||
3774  !AdjustFractDays(fval, 7, itm_in))
3775  return DTERR_FIELD_OVERFLOW;
3776  break;
3777  case 'D':
3778  if (!AdjustDays(val, 1, itm_in) ||
3779  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3780  return DTERR_FIELD_OVERFLOW;
3781  break;
3782  case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
3783  case '\0':
3784  if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
3785  {
3786  if (!AdjustYears(val / 10000, 1, itm_in) ||
3787  !AdjustMonths((val / 100) % 100, itm_in) ||
3788  !AdjustDays(val % 100, 1, itm_in) ||
3789  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3790  return DTERR_FIELD_OVERFLOW;
3791  if (unit == '\0')
3792  return 0;
3793  datepart = false;
3794  havefield = false;
3795  continue;
3796  }
3797  /* Else fall through to extended alternative format */
3798  /* FALLTHROUGH */
3799  case '-': /* ISO 8601 4.4.3.3 Alternative Format,
3800  * Extended */
3801  if (havefield)
3802  return DTERR_BAD_FORMAT;
3803 
3804  if (!AdjustYears(val, 1, itm_in) ||
3805  !AdjustFractYears(fval, 1, itm_in))
3806  return DTERR_FIELD_OVERFLOW;
3807  if (unit == '\0')
3808  return 0;
3809  if (unit == 'T')
3810  {
3811  datepart = false;
3812  havefield = false;
3813  continue;
3814  }
3815 
3816  dterr = ParseISO8601Number(str, &str, &val, &fval);
3817  if (dterr)
3818  return dterr;
3819  if (!AdjustMonths(val, itm_in) ||
3820  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3821  return DTERR_FIELD_OVERFLOW;
3822  if (*str == '\0')
3823  return 0;
3824  if (*str == 'T')
3825  {
3826  datepart = false;
3827  havefield = false;
3828  continue;
3829  }
3830  if (*str != '-')
3831  return DTERR_BAD_FORMAT;
3832  str++;
3833 
3834  dterr = ParseISO8601Number(str, &str, &val, &fval);
3835  if (dterr)
3836  return dterr;
3837  if (!AdjustDays(val, 1, itm_in) ||
3838  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3839  return DTERR_FIELD_OVERFLOW;
3840  if (*str == '\0')
3841  return 0;
3842  if (*str == 'T')
3843  {
3844  datepart = false;
3845  havefield = false;
3846  continue;
3847  }
3848  return DTERR_BAD_FORMAT;
3849  default:
3850  /* not a valid date unit suffix */
3851  return DTERR_BAD_FORMAT;
3852  }
3853  }
3854  else
3855  {
3856  switch (unit) /* after T: H M S */
3857  {
3858  case 'H':
3859  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3860  return DTERR_FIELD_OVERFLOW;
3861  break;
3862  case 'M':
3863  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3864  return DTERR_FIELD_OVERFLOW;
3865  break;
3866  case 'S':
3867  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3868  return DTERR_FIELD_OVERFLOW;
3869  break;
3870  case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
3871  if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
3872  {
3873  if (!AdjustMicroseconds(val / 10000, 0, USECS_PER_HOUR, itm_in) ||
3874  !AdjustMicroseconds((val / 100) % 100, 0, USECS_PER_MINUTE, itm_in) ||
3875  !AdjustMicroseconds(val % 100, 0, USECS_PER_SEC, itm_in) ||
3876  !AdjustFractMicroseconds(fval, 1, itm_in))
3877  return DTERR_FIELD_OVERFLOW;
3878  return 0;
3879  }
3880  /* Else fall through to extended alternative format */
3881  /* FALLTHROUGH */
3882  case ':': /* ISO 8601 4.4.3.3 Alternative Format,
3883  * Extended */
3884  if (havefield)
3885  return DTERR_BAD_FORMAT;
3886 
3887  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3888  return DTERR_FIELD_OVERFLOW;
3889  if (unit == '\0')
3890  return 0;
3891 
3892  dterr = ParseISO8601Number(str, &str, &val, &fval);
3893  if (dterr)
3894  return dterr;
3895  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3896  return DTERR_FIELD_OVERFLOW;
3897  if (*str == '\0')
3898  return 0;
3899  if (*str != ':')
3900  return DTERR_BAD_FORMAT;
3901  str++;
3902 
3903  dterr = ParseISO8601Number(str, &str, &val, &fval);
3904  if (dterr)
3905  return dterr;
3906  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3907  return DTERR_FIELD_OVERFLOW;
3908  if (*str == '\0')
3909  return 0;
3910  return DTERR_BAD_FORMAT;
3911 
3912  default:
3913  /* not a valid time unit suffix */
3914  return DTERR_BAD_FORMAT;
3915  }
3916  }
3917 
3918  havefield = true;
3919  }
3920 
3921  return 0;
3922 }
3923 
3924 
3925 /* DecodeUnits()
3926  * Decode text string using lookup table.
3927  *
3928  * This routine recognizes keywords associated with time interval units.
3929  *
3930  * Given string must be lowercased already.
3931  *
3932  * Implement a cache lookup since it is likely that dates
3933  * will be related in format.
3934  */
3935 int
3936 DecodeUnits(int field, const char *lowtoken, int *val)
3937 {
3938  int type;
3939  const datetkn *tp;
3940 
3941  tp = deltacache[field];
3942  /* use strncmp so that we match truncated tokens */
3943  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3944  {
3945  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3946  }
3947  if (tp == NULL)
3948  {
3949  type = UNKNOWN_FIELD;
3950  *val = 0;
3951  }
3952  else
3953  {
3954  deltacache[field] = tp;
3955  type = tp->type;
3956  *val = tp->value;
3957  }
3958 
3959  return type;
3960 } /* DecodeUnits() */
3961 
3962 /*
3963  * Report an error detected by one of the datetime input processing routines.
3964  *
3965  * dterr is the error code, and *extra contains any auxiliary info we need
3966  * for the error report. extra can be NULL if not needed for the particular
3967  * dterr value.
3968  *
3969  * str is the original input string, and datatype is the name of the datatype
3970  * we were trying to accept. (For some DTERR codes, these are not used and
3971  * can be NULL.)
3972  *
3973  * If escontext points to an ErrorSaveContext node, that is filled instead
3974  * of throwing an error.
3975  *
3976  * Note: it might seem useless to distinguish DTERR_INTERVAL_OVERFLOW and
3977  * DTERR_TZDISP_OVERFLOW from DTERR_FIELD_OVERFLOW, but SQL99 mandates three
3978  * separate SQLSTATE codes, so ...
3979  */
3980 void
3982  const char *str, const char *datatype,
3983  Node *escontext)
3984 {
3985  switch (dterr)
3986  {
3987  case DTERR_FIELD_OVERFLOW:
3988  errsave(escontext,
3989  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3990  errmsg("date/time field value out of range: \"%s\"",
3991  str)));
3992  break;
3994  /* <nanny>same as above, but add hint about DateStyle</nanny> */
3995  errsave(escontext,
3996  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3997  errmsg("date/time field value out of range: \"%s\"",
3998  str),
3999  errhint("Perhaps you need a different \"datestyle\" setting.")));
4000  break;
4002  errsave(escontext,
4003  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
4004  errmsg("interval field value out of range: \"%s\"",
4005  str)));
4006  break;
4007  case DTERR_TZDISP_OVERFLOW:
4008  errsave(escontext,
4009  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
4010  errmsg("time zone displacement out of range: \"%s\"",
4011  str)));
4012  break;
4013  case DTERR_BAD_TIMEZONE:
4014  errsave(escontext,
4015  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4016  errmsg("time zone \"%s\" not recognized",
4017  extra->dtee_timezone)));
4018  break;
4019  case DTERR_BAD_ZONE_ABBREV:
4020  errsave(escontext,
4021  (errcode(ERRCODE_CONFIG_FILE_ERROR),
4022  errmsg("time zone \"%s\" not recognized",
4023  extra->dtee_timezone),
4024  errdetail("This time zone name appears in the configuration file for time zone abbreviation \"%s\".",
4025  extra->dtee_abbrev)));
4026  break;
4027  case DTERR_BAD_FORMAT:
4028  default:
4029  errsave(escontext,
4030  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4031  errmsg("invalid input syntax for type %s: \"%s\"",
4032  datatype, str)));
4033  break;
4034  }
4035 }
4036 
4037 /* datebsearch()
4038  * Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
4039  * is WAY faster than the generic bsearch().
4040  */
4041 static const datetkn *
4042 datebsearch(const char *key, const datetkn *base, int nel)
4043 {
4044  if (nel > 0)
4045  {
4046  const datetkn *last = base + nel - 1,
4047  *position;
4048  int result;
4049 
4050  while (last >= base)
4051  {
4052  position = base + ((last - base) >> 1);
4053  /* precheck the first character for a bit of extra speed */
4054  result = (int) key[0] - (int) position->token[0];
4055  if (result == 0)
4056  {
4057  /* use strncmp so that we match truncated tokens */
4058  result = strncmp(key, position->token, TOKMAXLEN);
4059  if (result == 0)
4060  return position;
4061  }
4062  if (result < 0)
4063  last = position - 1;
4064  else
4065  base = position + 1;
4066  }
4067  }
4068  return NULL;
4069 }
4070 
4071 /* EncodeTimezone()
4072  * Copies representation of a numeric timezone offset to str.
4073  *
4074  * Returns a pointer to the new end of string. No NUL terminator is put
4075  * there; callers are responsible for NUL terminating str themselves.
4076  */
4077 static char *
4078 EncodeTimezone(char *str, int tz, int style)
4079 {
4080  int hour,
4081  min,
4082  sec;
4083 
4084  sec = abs(tz);
4085  min = sec / SECS_PER_MINUTE;
4086  sec -= min * SECS_PER_MINUTE;
4087  hour = min / MINS_PER_HOUR;
4088  min -= hour * MINS_PER_HOUR;
4089 
4090  /* TZ is negated compared to sign we wish to display ... */
4091  *str++ = (tz <= 0 ? '+' : '-');
4092 
4093  if (sec != 0)
4094  {
4095  str = pg_ultostr_zeropad(str, hour, 2);
4096  *str++ = ':';
4097  str = pg_ultostr_zeropad(str, min, 2);
4098  *str++ = ':';
4099  str = pg_ultostr_zeropad(str, sec, 2);
4100  }
4101  else if (min != 0 || style == USE_XSD_DATES)
4102  {
4103  str = pg_ultostr_zeropad(str, hour, 2);
4104  *str++ = ':';
4105  str = pg_ultostr_zeropad(str, min, 2);
4106  }
4107  else
4108  str = pg_ultostr_zeropad(str, hour, 2);
4109  return str;
4110 }
4111 
4112 /* EncodeDateOnly()
4113  * Encode date as local time.
4114  */
4115 void
4116 EncodeDateOnly(struct pg_tm *tm, int style, char *str)
4117 {
4118  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4119 
4120  switch (style)
4121  {
4122  case USE_ISO_DATES:
4123  case USE_XSD_DATES:
4124  /* compatible with ISO date formats */
4126  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4127  *str++ = '-';
4129  *str++ = '-';
4131  break;
4132 
4133  case USE_SQL_DATES:
4134  /* compatible with Oracle/Ingres date formats */
4135  if (DateOrder == DATEORDER_DMY)
4136  {
4138  *str++ = '/';
4140  }
4141  else
4142  {
4144  *str++ = '/';
4146  }
4147  *str++ = '/';
4149  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4150  break;
4151 
4152  case USE_GERMAN_DATES:
4153  /* German-style date format */
4155  *str++ = '.';
4157  *str++ = '.';
4159  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4160  break;
4161 
4162  case USE_POSTGRES_DATES:
4163  default:
4164  /* traditional date-only style for Postgres */
4165  if (DateOrder == DATEORDER_DMY)
4166  {
4168  *str++ = '-';
4170  }
4171  else
4172  {
4174  *str++ = '-';
4176  }
4177  *str++ = '-';
4179  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4180  break;
4181  }
4182 
4183  if (tm->tm_year <= 0)
4184  {
4185  memcpy(str, " BC", 3); /* Don't copy NUL */
4186  str += 3;
4187  }
4188  *str = '\0';
4189 }
4190 
4191 
4192 /* EncodeTimeOnly()
4193  * Encode time fields only.
4194  *
4195  * tm and fsec are the value to encode, print_tz determines whether to include
4196  * a time zone (the difference between time and timetz types), tz is the
4197  * numeric time zone offset, style is the date style, str is where to write the
4198  * output.
4199  */
4200 void
4201 EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
4202 {
4204  *str++ = ':';
4206  *str++ = ':';
4207  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
4208  if (print_tz)
4209  str = EncodeTimezone(str, tz, style);
4210  *str = '\0';
4211 }
4212 
4213 
4214 /* EncodeDateTime()
4215  * Encode date and time interpreted as local time.
4216  *
4217  * tm and fsec are the value to encode, print_tz determines whether to include
4218  * a time zone (the difference between timestamp and timestamptz types), tz is
4219  * the numeric time zone offset, tzn is the textual time zone, which if
4220  * specified will be used instead of tz by some styles, style is the date
4221  * style, str is where to write the output.
4222  *
4223  * Supported date styles:
4224  * Postgres - day mon hh:mm:ss yyyy tz
4225  * SQL - mm/dd/yyyy hh:mm:ss.ss tz
4226  * ISO - yyyy-mm-dd hh:mm:ss+/-tz
4227  * German - dd.mm.yyyy hh:mm:ss tz
4228  * XSD - yyyy-mm-ddThh:mm:ss.ss+/-tz
4229  */
4230 void
4231 EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
4232 {
4233  int day;
4234 
4235  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4236 
4237  /*
4238  * Negative tm_isdst means we have no valid time zone translation.
4239  */
4240  if (tm->tm_isdst < 0)
4241  print_tz = false;
4242 
4243  switch (style)
4244  {
4245  case USE_ISO_DATES:
4246  case USE_XSD_DATES:
4247  /* Compatible with ISO-8601 date formats */
4249  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4250  *str++ = '-';
4252  *str++ = '-';
4254  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4256  *str++ = ':';
4258  *str++ = ':';
4259  str = AppendTimestampSeconds(str, tm, fsec);
4260  if (print_tz)
4261  str = EncodeTimezone(str, tz, style);
4262  break;
4263 
4264  case USE_SQL_DATES:
4265  /* Compatible with Oracle/Ingres date formats */
4266  if (DateOrder == DATEORDER_DMY)
4267  {
4269  *str++ = '/';
4271  }
4272  else
4273  {
4275  *str++ = '/';
4277  }
4278  *str++ = '/';
4280  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4281  *str++ = ' ';
4283  *str++ = ':';
4285  *str++ = ':';
4286  str = AppendTimestampSeconds(str, tm, fsec);
4287 
4288  /*
4289  * Note: the uses of %.*s in this function would be risky if the
4290  * timezone names ever contain non-ASCII characters, since we are
4291  * not being careful to do encoding-aware clipping. However, all
4292  * TZ abbreviations in the IANA database are plain ASCII.
4293  */
4294  if (print_tz)
4295  {
4296  if (tzn)
4297  {
4298  sprintf(str, " %.*s", MAXTZLEN, tzn);
4299  str += strlen(str);
4300  }
4301  else
4302  str = EncodeTimezone(str, tz, style);
4303  }
4304  break;
4305 
4306  case USE_GERMAN_DATES:
4307  /* German variant on European style */
4309  *str++ = '.';
4311  *str++ = '.';
4313  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4314  *str++ = ' ';
4316  *str++ = ':';
4318  *str++ = ':';
4319  str = AppendTimestampSeconds(str, tm, fsec);
4320 
4321  if (print_tz)
4322  {
4323  if (tzn)
4324  {
4325  sprintf(str, " %.*s", MAXTZLEN, tzn);
4326  str += strlen(str);
4327  }
4328  else
4329  str = EncodeTimezone(str, tz, style);
4330  }
4331  break;
4332 
4333  case USE_POSTGRES_DATES:
4334  default:
4335  /* Backward-compatible with traditional Postgres abstime dates */
4336  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4337  tm->tm_wday = j2day(day);
4338  memcpy(str, days[tm->tm_wday], 3);
4339  str += 3;
4340  *str++ = ' ';
4341  if (DateOrder == DATEORDER_DMY)
4342  {
4344  *str++ = ' ';
4345  memcpy(str, months[tm->tm_mon - 1], 3);
4346  str += 3;
4347  }
4348  else
4349  {
4350  memcpy(str, months[tm->tm_mon - 1], 3);
4351  str += 3;
4352  *str++ = ' ';
4354  }
4355  *str++ = ' ';
4357  *str++ = ':';
4359  *str++ = ':';
4360  str = AppendTimestampSeconds(str, tm, fsec);
4361  *str++ = ' ';
4363  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4364 
4365  if (print_tz)
4366  {
4367  if (tzn)
4368  {
4369  sprintf(str, " %.*s", MAXTZLEN, tzn);
4370  str += strlen(str);
4371  }
4372  else
4373  {
4374  /*
4375  * We have a time zone, but no string version. Use the
4376  * numeric form, but be sure to include a leading space to
4377  * avoid formatting something which would be rejected by
4378  * the date/time parser later. - thomas 2001-10-19
4379  */
4380  *str++ = ' ';
4381  str = EncodeTimezone(str, tz, style);
4382  }
4383  }
4384  break;
4385  }
4386 
4387  if (tm->tm_year <= 0)
4388  {
4389  memcpy(str, " BC", 3); /* Don't copy NUL */
4390  str += 3;
4391  }
4392  *str = '\0';
4393 }
4394 
4395 
4396 /*
4397  * Helper functions to avoid duplicated code in EncodeInterval.
4398  */
4399 
4400 /* Append an ISO-8601-style interval field, but only if value isn't zero */
4401 static char *
4402 AddISO8601IntPart(char *cp, int64 value, char units)
4403 {
4404  if (value == 0)
4405  return cp;
4406  sprintf(cp, "%lld%c", (long long) value, units);
4407  return cp + strlen(cp);
4408 }
4409 
4410 /* Append a postgres-style interval field, but only if value isn't zero */
4411 static char *
4412 AddPostgresIntPart(char *cp, int64 value, const char *units,
4413  bool *is_zero, bool *is_before)
4414 {
4415  if (value == 0)
4416  return cp;
4417  sprintf(cp, "%s%s%lld %s%s",
4418  (!*is_zero) ? " " : "",
4419  (*is_before && value > 0) ? "+" : "",
4420  (long long) value,
4421  units,
4422  (value != 1) ? "s" : "");
4423 
4424  /*
4425  * Each nonzero field sets is_before for (only) the next one. This is a
4426  * tad bizarre but it's how it worked before...
4427  */
4428  *is_before = (value < 0);
4429  *is_zero = false;
4430  return cp + strlen(cp);
4431 }
4432 
4433 /* Append a verbose-style interval field, but only if value isn't zero */
4434 static char *
4435 AddVerboseIntPart(char *cp, int64 value, const char *units,
4436  bool *is_zero, bool *is_before)
4437 {
4438  if (value == 0)
4439  return cp;
4440  /* first nonzero value sets is_before */
4441  if (*is_zero)
4442  {
4443  *is_before = (value < 0);
4444  value = i64abs(value);
4445  }
4446  else if (*is_before)
4447  value = -value;
4448  sprintf(cp, " %lld %s%s", (long long) value, units, (value == 1) ? "" : "s");
4449  *is_zero = false;
4450  return cp + strlen(cp);
4451 }
4452 
4453 
4454 /* EncodeInterval()
4455  * Interpret time structure as a delta time and convert to string.
4456  *
4457  * Support "traditional Postgres" and ISO-8601 styles.
4458  * Actually, afaik ISO does not address time interval formatting,
4459  * but this looks similar to the spec for absolute date/time.
4460  * - thomas 1998-04-30
4461  *
4462  * Actually, afaik, ISO 8601 does specify formats for "time
4463  * intervals...[of the]...format with time-unit designators", which
4464  * are pretty ugly. The format looks something like
4465  * P1Y1M1DT1H1M1.12345S
4466  * but useful for exchanging data with computers instead of humans.
4467  * - ron 2003-07-14
4468  *
4469  * And ISO's SQL 2008 standard specifies standards for
4470  * "year-month literal"s (that look like '2-3') and
4471  * "day-time literal"s (that look like ('4 5:6:7')
4472  */
4473 void
4474 EncodeInterval(struct pg_itm *itm, int style, char *str)
4475 {
4476  char *cp = str;
4477  int year = itm->tm_year;
4478  int mon = itm->tm_mon;
4479  int64 mday = itm->tm_mday; /* tm_mday could be INT_MIN */
4480  int64 hour = itm->tm_hour;
4481  int min = itm->tm_min;
4482  int sec = itm->tm_sec;
4483  int fsec = itm->tm_usec;
4484  bool is_before = false;
4485  bool is_zero = true;
4486 
4487  /*
4488  * The sign of year and month are guaranteed to match, since they are
4489  * stored internally as "month". But we'll need to check for is_before and
4490  * is_zero when determining the signs of day and hour/minute/seconds
4491  * fields.
4492  */
4493  switch (style)
4494  {
4495  /* SQL Standard interval format */
4496  case INTSTYLE_SQL_STANDARD:
4497  {
4498  bool has_negative = year < 0 || mon < 0 ||
4499  mday < 0 || hour < 0 ||
4500  min < 0 || sec < 0 || fsec < 0;
4501  bool has_positive = year > 0 || mon > 0 ||
4502  mday > 0 || hour > 0 ||
4503  min > 0 || sec > 0 || fsec > 0;
4504  bool has_year_month = year != 0 || mon != 0;
4505  bool has_day_time = mday != 0 || hour != 0 ||
4506  min != 0 || sec != 0 || fsec != 0;
4507  bool has_day = mday != 0;
4508  bool sql_standard_value = !(has_negative && has_positive) &&
4509  !(has_year_month && has_day_time);
4510 
4511  /*
4512  * SQL Standard wants only 1 "<sign>" preceding the whole
4513  * interval ... but can't do that if mixed signs.
4514  */
4515  if (has_negative && sql_standard_value)
4516  {
4517  *cp++ = '-';
4518  year = -year;
4519  mon = -mon;
4520  mday = -mday;
4521  hour = -hour;
4522  min = -min;
4523  sec = -sec;
4524  fsec = -fsec;
4525  }
4526 
4527  if (!has_negative && !has_positive)
4528  {
4529  sprintf(cp, "0");
4530  }
4531  else if (!sql_standard_value)
4532  {
4533  /*
4534  * For non sql-standard interval values, force outputting
4535  * the signs to avoid ambiguities with intervals with
4536  * mixed sign components.
4537  */
4538  char year_sign = (year < 0 || mon < 0) ? '-' : '+';
4539  char day_sign = (mday < 0) ? '-' : '+';
4540  char sec_sign = (hour < 0 || min < 0 ||
4541  sec < 0 || fsec < 0) ? '-' : '+';
4542 
4543  sprintf(cp, "%c%d-%d %c%lld %c%lld:%02d:",
4544  year_sign, abs(year), abs(mon),
4545  day_sign, (long long) i64abs(mday),
4546  sec_sign, (long long) i64abs(hour), abs(min));
4547  cp += strlen(cp);
4548  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4549  *cp = '\0';
4550  }
4551  else if (has_year_month)
4552  {
4553  sprintf(cp, "%d-%d", year, mon);
4554  }
4555  else if (has_day)
4556  {
4557  sprintf(cp, "%lld %lld:%02d:",
4558  (long long) mday, (long long) hour, min);
4559  cp += strlen(cp);
4560  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4561  *cp = '\0';
4562  }
4563  else
4564  {
4565  sprintf(cp, "%lld:%02d:", (long long) hour, min);
4566  cp += strlen(cp);
4567  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4568  *cp = '\0';
4569  }
4570  }
4571  break;
4572 
4573  /* ISO 8601 "time-intervals by duration only" */
4574  case INTSTYLE_ISO_8601:
4575  /* special-case zero to avoid printing nothing */
4576  if (year == 0 && mon == 0 && mday == 0 &&
4577  hour == 0 && min == 0 && sec == 0 && fsec == 0)
4578  {
4579  sprintf(cp, "PT0S");
4580  break;
4581  }
4582  *cp++ = 'P';
4583  cp = AddISO8601IntPart(cp, year, 'Y');
4584  cp = AddISO8601IntPart(cp, mon, 'M');
4585  cp = AddISO8601IntPart(cp, mday, 'D');
4586  if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
4587  *cp++ = 'T';
4588  cp = AddISO8601IntPart(cp, hour, 'H');
4589  cp = AddISO8601IntPart(cp, min, 'M');
4590  if (sec != 0 || fsec != 0)
4591  {
4592  if (sec < 0 || fsec < 0)
4593  *cp++ = '-';
4594  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4595  *cp++ = 'S';
4596  *cp++ = '\0';
4597  }
4598  break;
4599 
4600  /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
4601  case INTSTYLE_POSTGRES:
4602  cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
4603 
4604  /*
4605  * Ideally we should spell out "month" like we do for "year" and
4606  * "day". However, for backward compatibility, we can't easily
4607  * fix this. bjm 2011-05-24
4608  */
4609  cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
4610  cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
4611  if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
4612  {
4613  bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
4614 
4615  sprintf(cp, "%s%s%02lld:%02d:",
4616  is_zero ? "" : " ",
4617  (minus ? "-" : (is_before ? "+" : "")),
4618  (long long) i64abs(hour), abs(min));
4619  cp += strlen(cp);
4620  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4621  *cp = '\0';
4622  }
4623  break;
4624 
4625  /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
4627  default:
4628  strcpy(cp, "@");
4629  cp++;
4630  cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
4631  cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
4632  cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
4633  cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
4634  cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
4635  if (sec != 0 || fsec != 0)
4636  {
4637  *cp++ = ' ';
4638  if (sec < 0 || (sec == 0 && fsec < 0))
4639  {
4640  if (is_zero)
4641  is_before = true;
4642  else if (!is_before)
4643  *cp++ = '-';
4644  }
4645  else if (is_before)
4646  *cp++ = '-';
4647  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4648  /* We output "ago", not negatives, so use abs(). */
4649  sprintf(cp, " sec%s",
4650  (abs(sec) != 1 || fsec != 0) ? "s" : "");
4651  is_zero = false;
4652  }
4653  /* identically zero? then put in a unitless zero... */
4654  if (is_zero)
4655  strcat(cp, " 0");
4656  if (is_before)
4657  strcat(cp, " ago");
4658  break;
4659  }
4660 }
4661 
4662 
4663 /*
4664  * We've been burnt by stupid errors in the ordering of the datetkn tables
4665  * once too often. Arrange to check them during postmaster start.
4666  */
4667 static bool
4668 CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
4669 {
4670  bool ok = true;
4671  int i;
4672 
4673  for (i = 0; i < nel; i++)
4674  {
4675  /* check for token strings that don't fit */
4676  if (strlen(base[i].token) > TOKMAXLEN)
4677  {
4678  /* %.*s is safe since all our tokens are ASCII */
4679  elog(LOG, "token too long in %s table: \"%.*s\"",
4680  tablename,
4681  TOKMAXLEN + 1, base[i].token);
4682  ok = false;
4683  break; /* don't risk applying strcmp */
4684  }
4685  /* check for out of order */
4686  if (i > 0 &&
4687  strcmp(base[i - 1].token, base[i].token) >= 0)
4688  {
4689  elog(LOG, "ordering error in %s table: \"%s\" >= \"%s\"",
4690  tablename,
4691  base[i - 1].token,
4692  base[i].token);
4693  ok = false;
4694  }
4695  }
4696  return ok;
4697 }
4698 
4699 bool
4701 {
4702  bool ok = true;
4703 
4704  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4705  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4706 
4707  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4708  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4709  return ok;
4710 }
4711 
4712 /*
4713  * Common code for temporal prosupport functions: simplify, if possible,
4714  * a call to a temporal type's length-coercion function.
4715  *
4716  * Types time, timetz, timestamp and timestamptz each have a range of allowed
4717  * precisions. An unspecified precision is rigorously equivalent to the
4718  * highest specifiable precision. We can replace the function call with a
4719  * no-op RelabelType if it is coercing to the same or higher precision as the
4720  * input is known to have.
4721  *
4722  * The input Node is always a FuncExpr, but to reduce the #include footprint
4723  * of datetime.h, we declare it as Node *.
4724  *
4725  * Note: timestamp_scale throws an error when the typmod is out of range, but
4726  * we can't get there from a cast: our typmodin will have caught it already.
4727  */
4728 Node *
4729 TemporalSimplify(int32 max_precis, Node *node)
4730 {
4731  FuncExpr *expr = castNode(FuncExpr, node);
4732  Node *ret = NULL;
4733  Node *typmod;
4734 
4735  Assert(list_length(expr->args) >= 2);
4736 
4737  typmod = (Node *) lsecond(expr->args);
4738 
4739  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
4740  {
4741  Node *source = (Node *) linitial(expr->args);
4742  int32 old_precis = exprTypmod(source);
4743  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4744 
4745  if (new_precis < 0 || new_precis == max_precis ||
4746  (old_precis >= 0 && new_precis >= old_precis))
4747  ret = relabel_to_typmod(source, new_precis);
4748  }
4749 
4750  return ret;
4751 }
4752 
4753 /*
4754  * This function gets called during timezone config file load or reload
4755  * to create the final array of timezone tokens. The argument array
4756  * is already sorted in name order.
4757  *
4758  * The result is a TimeZoneAbbrevTable (which must be a single guc_malloc'd
4759  * chunk) or NULL on alloc failure. No other error conditions are defined.
4760  */
4762 ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs, int n)
4763 {
4764  TimeZoneAbbrevTable *tbl;
4765  Size tbl_size;
4766  int i;
4767 
4768  /* Space for fixed fields and datetkn array */
4769  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4770  n * sizeof(datetkn);
4771  tbl_size = MAXALIGN(tbl_size);
4772  /* Count up space for dynamic abbreviations */
4773  for (i = 0; i < n; i++)
4774  {
4775  struct tzEntry *abbr = abbrevs + i;
4776 
4777  if (abbr->zone != NULL)
4778  {
4779  Size dsize;
4780 
4781  dsize = offsetof(DynamicZoneAbbrev, zone) +
4782  strlen(abbr->zone) + 1;
4783  tbl_size += MAXALIGN(dsize);
4784  }
4785  }
4786 
4787  /* Alloc the result ... */
4788  tbl = guc_malloc(LOG, tbl_size);
4789  if (!tbl)
4790  return NULL;
4791 
4792  /* ... and fill it in */
4793  tbl->tblsize = tbl_size;
4794  tbl->numabbrevs = n;
4795  /* in this loop, tbl_size reprises the space calculation above */
4796  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4797  n * sizeof(datetkn);
4798  tbl_size = MAXALIGN(tbl_size);
4799  for (i = 0; i < n; i++)
4800  {
4801  struct tzEntry *abbr = abbrevs + i;
4802  datetkn *dtoken = tbl->abbrevs + i;
4803 
4804  /* use strlcpy to truncate name if necessary */
4805  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4806  if (abbr->zone != NULL)
4807  {
4808  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4809  DynamicZoneAbbrev *dtza;
4810  Size dsize;
4811 
4812  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4813  dtza->tz = NULL;
4814  strcpy(dtza->zone, abbr->zone);
4815 
4816  dtoken->type = DYNTZ;
4817  /* value is offset from table start to DynamicZoneAbbrev */
4818  dtoken->value = (int32) tbl_size;
4819 
4820  dsize = offsetof(DynamicZoneAbbrev, zone) +
4821  strlen(abbr->zone) + 1;
4822  tbl_size += MAXALIGN(dsize);
4823  }
4824  else
4825  {
4826  dtoken->type = abbr->is_dst ? DTZ : TZ;
4827  dtoken->value = abbr->offset;
4828  }
4829  }
4830 
4831  /* Assert the two loops above agreed on size calculations */
4832  Assert(tbl->tblsize == tbl_size);
4833 
4834  /* Check the ordering, if testing */
4835  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4836 
4837  return tbl;
4838 }
4839 
4840 /*
4841  * Install a TimeZoneAbbrevTable as the active table.
4842  *
4843  * Caller is responsible that the passed table doesn't go away while in use.
4844  */
4845 void
4847 {
4848  zoneabbrevtbl = tbl;
4849  /* reset abbrevcache, which may contain pointers into old table */
4850  memset(abbrevcache, 0, sizeof(abbrevcache));
4851 }
4852 
4853 /*
4854  * Helper subroutine to locate pg_tz timezone for a dynamic abbreviation.
4855  *
4856  * On failure, returns NULL and fills *extra for a DTERR_BAD_ZONE_ABBREV error.
4857  */
4858 static pg_tz *
4860  DateTimeErrorExtra *extra)
4861 {
4862  DynamicZoneAbbrev *dtza;
4863 
4864  /* Just some sanity checks to prevent indexing off into nowhere */
4865  Assert(tp->type == DYNTZ);
4866  Assert(tp->value > 0 && tp->value < tbl->tblsize);
4867 
4868  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tp->value);
4869 
4870  /* Look up the underlying zone if we haven't already */
4871  if (dtza->tz == NULL)
4872  {
4873  dtza->tz = pg_tzset(dtza->zone);
4874  if (dtza->tz == NULL)
4875  {
4876  /* Ooops, bogus zone name in config file entry */
4877  extra->dtee_timezone = dtza->zone;
4878  extra->dtee_abbrev = tp->token;
4879  }
4880  }
4881  return dtza->tz;
4882 }
4883 
4884 
4885 /*
4886  * This set-returning function reads all the available time zone abbreviations
4887  * and returns a set of (abbrev, utc_offset, is_dst).
4888  */
4889 Datum
4891 {
4892  FuncCallContext *funcctx;
4893  int *pindex;
4894  Datum result;
4895  HeapTuple tuple;
4896  Datum values[3];
4897  bool nulls[3] = {0};
4898  const datetkn *tp;
4899  char buffer[TOKMAXLEN + 1];
4900  int gmtoffset;
4901  bool is_dst;
4902  unsigned char *p;
4903  struct pg_itm_in itm_in;
4904  Interval *resInterval;
4905 
4906  /* stuff done only on the first call of the function */
4907  if (SRF_IS_FIRSTCALL())
4908  {
4909  TupleDesc tupdesc;
4910  MemoryContext oldcontext;
4911 
4912  /* create a function context for cross-call persistence */
4913  funcctx = SRF_FIRSTCALL_INIT();
4914 
4915  /*
4916  * switch to memory context appropriate for multiple function calls
4917  */
4918  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
4919 
4920  /* allocate memory for user context */
4921  pindex = (int *) palloc(sizeof(int));
4922  *pindex = 0;
4923  funcctx->user_fctx = (void *) pindex;
4924 
4925  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
4926  elog(ERROR, "return type must be a row type");
4927  funcctx->tuple_desc = tupdesc;
4928 
4929  MemoryContextSwitchTo(oldcontext);
4930  }
4931 
4932  /* stuff done on every call of the function */
4933  funcctx = SRF_PERCALL_SETUP();
4934  pindex = (int *) funcctx->user_fctx;
4935 
4936  if (zoneabbrevtbl == NULL ||
4937  *pindex >= zoneabbrevtbl->numabbrevs)
4938  SRF_RETURN_DONE(funcctx);
4939 
4940  tp = zoneabbrevtbl->abbrevs + *pindex;
4941 
4942  switch (tp->type)
4943  {
4944  case TZ:
4945  gmtoffset = tp->value;
4946  is_dst = false;
4947  break;
4948  case DTZ:
4949  gmtoffset = tp->value;
4950  is_dst = true;
4951  break;
4952  case DYNTZ:
4953  {
4954  /* Determine the current meaning of the abbrev */
4955  pg_tz *tzp;
4956  DateTimeErrorExtra extra;
4957  TimestampTz now;
4958  int isdst;
4959 
4960  tzp = FetchDynamicTimeZone(zoneabbrevtbl, tp, &extra);
4961  if (tzp == NULL)
4963  NULL, NULL, NULL);
4965  gmtoffset = -DetermineTimeZoneAbbrevOffsetTS(now,
4966  tp->token,
4967  tzp,
4968  &isdst);
4969  is_dst = (bool) isdst;
4970  break;
4971  }
4972  default:
4973  elog(ERROR, "unrecognized timezone type %d", (int) tp->type);
4974  gmtoffset = 0; /* keep compiler quiet */
4975  is_dst = false;
4976  break;
4977  }
4978 
4979  /*
4980  * Convert name to text, using upcasing conversion that is the inverse of
4981  * what ParseDateTime() uses.
4982  */
4983  strlcpy(buffer, tp->token, sizeof(buffer));
4984  for (p = (unsigned char *) buffer; *p; p++)
4985  *p = pg_toupper(*p);
4986 
4987  values[0] = CStringGetTextDatum(buffer);
4988 
4989  /* Convert offset (in seconds) to an interval; can't overflow */
4990  MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
4991  itm_in.tm_usec = (int64) gmtoffset * USECS_PER_SEC;
4992  resInterval = (Interval *) palloc(sizeof(Interval));
4993  (void) itmin2interval(&itm_in, resInterval);
4994  values[1] = IntervalPGetDatum(resInterval);
4995 
4996  values[2] = BoolGetDatum(is_dst);
4997 
4998  (*pindex)++;
4999 
5000  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
5001  result = HeapTupleGetDatum(tuple);
5002 
5003  SRF_RETURN_NEXT(funcctx, result);
5004 }
5005 
5006 /*
5007  * This set-returning function reads all the available full time zones
5008  * and returns a set of (name, abbrev, utc_offset, is_dst).
5009  */
5010 Datum
5012 {
5013  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
5014  pg_tzenum *tzenum;
5015  pg_tz *tz;
5016  Datum values[4];
5017  bool nulls[4] = {0};
5018  int tzoff;
5019  struct pg_tm tm;
5020  fsec_t fsec;
5021  const char *tzn;
5022  Interval *resInterval;
5023  struct pg_itm_in itm_in;
5024 
5025  InitMaterializedSRF(fcinfo, 0);
5026 
5027  /* initialize timezone scanning code */
5028  tzenum = pg_tzenumerate_start();
5029 
5030  /* search for another zone to display */
5031  for (;;)
5032  {
5033  tz = pg_tzenumerate_next(tzenum);
5034  if (!tz)
5035  break;
5036 
5037  /* Convert now() to local time in this zone */
5039  &tzoff, &tm, &fsec, &tzn, tz) != 0)
5040  continue; /* ignore if conversion fails */
5041 
5042  /*
5043  * IANA's rather silly "Factory" time zone used to emit ridiculously
5044  * long "abbreviations" such as "Local time zone must be set--see zic
5045  * manual page" or "Local time zone must be set--use tzsetup". While
5046  * modern versions of tzdb emit the much saner "-00", it seems some
5047  * benighted packagers are hacking the IANA data so that it continues
5048  * to produce these strings. To prevent producing a weirdly wide
5049  * abbrev column, reject ridiculously long abbreviations.
5050  */
5051  if (tzn && strlen(tzn) > 31)
5052  continue;
5053 
5055  values[1] = CStringGetTextDatum(tzn ? tzn : "");
5056 
5057  /* Convert tzoff to an interval; can't overflow */
5058  MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
5059  itm_in.tm_usec = (int64) -tzoff * USECS_PER_SEC;
5060  resInterval = (Interval *) palloc(sizeof(Interval));
5061  (void) itmin2interval(&itm_in, resInterval);
5062  values[2] = IntervalPGetDatum(resInterval);
5063 
5064  values[3] = BoolGetDatum(tm.tm_isdst > 0);
5065 
5066  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
5067  }
5068 
5069  pg_tzenumerate_end(tzenum);
5070  return (Datum) 0;
5071 }
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:264
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits, struct pg_tm *tm)
Definition: datetime.c:2389
const int day_tab[2][13]
Definition: datetime.c:77
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
Definition: datetime.c:1609
static char * AddVerboseIntPart(char *cp, int64 value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4435
#define APPEND_CHAR(bufptr, end, newchar)
static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2903
pg_tz * DecodeTimezoneNameToTz(const char *tzname)
Definition: datetime.c:3236
static char * AddPostgresIntPart(char *cp, int64 value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4412
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4668
int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
Definition: datetime.c:1786
static int ParseFraction(char *cp, double *frac)
Definition: datetime.c:682
void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl)
Definition: datetime.c:4846
static const datetkn datetktbl[]
Definition: datetime.c:107
static bool int64_multiply_add(int64 val, int64 multiplier, int64 *sum)
Definition: datetime.c:524
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:3936
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:4078
int DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:1866
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:256
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:262
int j2day(int date)
Definition: datetime.c:346
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:756
void EncodeInterval(struct pg_itm *itm, int style, char *str)
Definition: datetime.c:4474
static bool AdjustDays(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:635
static const datetkn * datecache[MAXDATEFIELDS]
Definition: datetime.c:260
static int DecodeNumber(int flen, char *str, bool haveTextMonth, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2718
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1587
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1823
static char * AddISO8601IntPart(char *cp, int64 value, char units)
Definition: datetime.c:4402
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:3981
static int ParseFractionalSecond(char *cp, fsec_t *fsec)
Definition: datetime.c:711
static bool AdjustFractYears(double frac, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:603
static bool AdjustMicroseconds(int64 val, double fval, int64 scale, struct pg_itm_in *itm_in)
Definition: datetime.c:620
static int DecodeTimeCommon(char *str, int fmask, int range, int *tmask, struct pg_itm *itm)
Definition: datetime.c:2581
int DecodeInterval(char **field, int *ftype, int nf, int range, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3276
static int DecodeTimeForInterval(char *str, int fmask, int range, int *tmask, struct pg_itm_in *itm_in)
Definition: datetime.c:2692
bool CheckDateTokenTables(void)
Definition: datetime.c:4700
static const int szdeltatktbl
Definition: datetime.c:254
int DecodeTimezoneAbbrev(int field, const char *lowtoken, int *ftype, int *offset, pg_tz **tz, DateTimeErrorExtra *extra)
Definition: datetime.c:3082
Datum pg_timezone_names(PG_FUNCTION_ARGS)
Definition: datetime.c:5011
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4201
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2663
static bool AdjustFractMicroseconds(double frac, int64 scale, struct pg_itm_in *itm_in)
Definition: datetime.c:539
int DecodeISO8601Interval(char *str, int *dtype, struct pg_itm_in *itm_in)
Definition: datetime.c:3718
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2499
int DecodeSpecial(int field, const char *lowtoken, int *val)
Definition: datetime.c:3139
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:313
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:368
static int ISO8601IntegerWidth(char *fieldstart)
Definition: datetime.c:3691
static bool AdjustYears(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:663
Datum pg_timezone_abbrevs(PG_FUNCTION_ARGS)
Definition: datetime.c:4890
TimeZoneAbbrevTable * ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs, int n)
Definition: datetime.c:4762
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4231
int DecodeTimezone(const char *str, int *tzp)
Definition: datetime.c:2998
const char *const months[]
Definition: datetime.c:83
static bool AdjustMonths(int64 val, struct pg_itm_in *itm_in)
Definition: datetime.c:651
static char * AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Definition: datetime.c:450
static const int szdatetktbl
Definition: datetime.c:183
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4116
static char * AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
Definition: datetime.c:513
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:4042
static int ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
Definition: datetime.c:3649
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:980
int date2j(int year, int month, int day)
Definition: datetime.c:288
static bool AdjustFractDays(double frac, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:571
static void ClearPgItmIn(struct pg_itm_in *itm_in)
Definition: datetime.c:3255
static const datetkn deltatktbl[]
Definition: datetime.c:189
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:389
const char *const days[]
Definition: datetime.c:86
static pg_tz * FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp, DateTimeErrorExtra *extra)
Definition: datetime.c:4859
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3181
Node * TemporalSimplify(int32 max_precis, Node *node)
Definition: datetime.c:4729
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1748
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1803
int itmin2interval(struct pg_itm_in *itm_in, Interval *span)
Definition: timestamp.c:2032
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1762
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define MAXALIGN(LEN)
Definition: c.h:800
signed int int32
Definition: c.h:483
#define strtoi64(str, endptr, base)
Definition: c.h:1307
unsigned char bool
Definition: c.h:445
#define PG_INT64_MIN
Definition: c.h:580
#define MemSet(start, val, len)
Definition: c.h:1009
size_t Size
Definition: c.h:594
#define i64abs(i)
Definition: c.h:1317
int64 TimestampTz
Definition: timestamp.h:39
#define SECS_PER_HOUR
Definition: timestamp.h:126
#define MAX_TIMESTAMP_PRECISION
Definition: timestamp.h:92
#define MAX_TZDISP_HOUR
Definition: timestamp.h:142
int32 fsec_t
Definition: timestamp.h:41
#define USECS_PER_HOUR
Definition: timestamp.h:131
#define MONTHS_PER_YEAR
Definition: timestamp.h:108
#define MINS_PER_HOUR
Definition: timestamp.h:128
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:201
#define MAX_INTERVAL_PRECISION
Definition: timestamp.h:93
#define SECS_PER_MINUTE
Definition: timestamp.h:127
#define USECS_PER_DAY
Definition: timestamp.h:130
#define USECS_PER_SEC
Definition: timestamp.h:133
#define HOURS_PER_DAY
Definition: timestamp.h:117
#define USECS_PER_MINUTE
Definition: timestamp.h:132
#define DAYS_PER_MONTH
Definition: timestamp.h:116
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:208
#define SECS_PER_DAY
Definition: timestamp.h:125
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
bool time_overflows(int hour, int min, int sec, fsec_t fsec)
Definition: date.c:1426
#define MAX_TIME_PRECISION
Definition: date.h:45
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define LOG
Definition: elog.h:31
#define errsave(context,...)
Definition: elog.h:260
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149