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-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/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 /* DecodeTimezoneAbbrevPrefix()
3250  * Interpret prefix of string as a timezone abbreviation, if possible.
3251  *
3252  * This has roughly the same functionality as DecodeTimezoneAbbrev(),
3253  * but the API is adapted to the needs of formatting.c. Notably,
3254  * we will match the longest possible prefix of the given string
3255  * rather than insisting on a complete match, and downcasing is applied
3256  * here rather than in the caller.
3257  *
3258  * Returns the length of the timezone abbreviation, or -1 if not recognized.
3259  * On success, sets *offset to the GMT offset for the abbreviation if it
3260  * is a fixed-offset abbreviation, or sets *tz to the pg_tz struct for
3261  * a dynamic abbreviation.
3262  */
3263 int
3264 DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz)
3265 {
3266  char lowtoken[TOKMAXLEN + 1];
3267  int len;
3268 
3269  *offset = 0; /* avoid uninitialized vars on failure */
3270  *tz = NULL;
3271 
3272  if (!zoneabbrevtbl)
3273  return -1; /* no abbrevs known, so fail immediately */
3274 
3275  /* Downcase as much of the string as we could need */
3276  for (len = 0; len < TOKMAXLEN; len++)
3277  {
3278  if (*str == '\0' || !isalpha((unsigned char) *str))
3279  break;
3280  lowtoken[len] = pg_tolower((unsigned char) *str++);
3281  }
3282  lowtoken[len] = '\0';
3283 
3284  /*
3285  * We could avoid doing repeated binary searches if we cared to duplicate
3286  * datebsearch here, but it's not clear that such an optimization would be
3287  * worth the trouble. In common cases there's probably not anything after
3288  * the zone abbrev anyway. So just search with successively truncated
3289  * strings.
3290  */
3291  while (len > 0)
3292  {
3293  const datetkn *tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
3295 
3296  if (tp != NULL)
3297  {
3298  if (tp->type == DYNTZ)
3299  {
3300  DateTimeErrorExtra extra;
3302  &extra);
3303 
3304  if (tzp != NULL)
3305  {
3306  /* Caller must resolve the abbrev's current meaning */
3307  *tz = tzp;
3308  return len;
3309  }
3310  }
3311  else
3312  {
3313  /* Fixed-offset zone abbrev, so it's easy */
3314  *offset = tp->value;
3315  return len;
3316  }
3317  }
3318  lowtoken[--len] = '\0';
3319  }
3320 
3321  /* Did not find a match */
3322  return -1;
3323 }
3324 
3325 
3326 /* ClearPgItmIn
3327  *
3328  * Zero out a pg_itm_in
3329  */
3330 static inline void
3331 ClearPgItmIn(struct pg_itm_in *itm_in)
3332 {
3333  itm_in->tm_usec = 0;
3334  itm_in->tm_mday = 0;
3335  itm_in->tm_mon = 0;
3336  itm_in->tm_year = 0;
3337 }
3338 
3339 
3340 /* DecodeInterval()
3341  * Interpret previously parsed fields for general time interval.
3342  * Returns 0 if successful, DTERR code if bogus input detected.
3343  * dtype and itm_in are output parameters.
3344  *
3345  * Allow "date" field DTK_DATE since this could be just
3346  * an unsigned floating point number. - thomas 1997-11-16
3347  *
3348  * Allow ISO-style time span, with implicit units on number of days
3349  * preceding an hh:mm:ss field. - thomas 1998-04-30
3350  *
3351  * itm_in remains undefined for infinite interval values for which dtype alone
3352  * suffices.
3353  */
3354 int
3355 DecodeInterval(char **field, int *ftype, int nf, int range,
3356  int *dtype, struct pg_itm_in *itm_in)
3357 {
3358  bool force_negative = false;
3359  bool is_before = false;
3360  bool parsing_unit_val = false;
3361  char *cp;
3362  int fmask = 0,
3363  tmask,
3364  type,
3365  uval;
3366  int i;
3367  int dterr;
3368  int64 val;
3369  double fval;
3370 
3371  *dtype = DTK_DELTA;
3372  type = IGNORE_DTF;
3373  ClearPgItmIn(itm_in);
3374 
3375  /*----------
3376  * The SQL standard defines the interval literal
3377  * '-1 1:00:00'
3378  * to mean "negative 1 days and negative 1 hours", while Postgres
3379  * traditionally treats this as meaning "negative 1 days and positive
3380  * 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
3381  * to all fields if there are no other explicit signs.
3382  *
3383  * We leave the signs alone if there are additional explicit signs.
3384  * This protects us against misinterpreting postgres-style dump output,
3385  * since the postgres-style output code has always put an explicit sign on
3386  * all fields following a negative field. But note that SQL-spec output
3387  * is ambiguous and can be misinterpreted on load! (So it's best practice
3388  * to dump in postgres style, not SQL style.)
3389  *----------
3390  */
3391  if (IntervalStyle == INTSTYLE_SQL_STANDARD && nf > 0 && *field[0] == '-')
3392  {
3393  force_negative = true;
3394  /* Check for additional explicit signs */
3395  for (i = 1; i < nf; i++)
3396  {
3397  if (*field[i] == '-' || *field[i] == '+')
3398  {
3399  force_negative = false;
3400  break;
3401  }
3402  }
3403  }
3404 
3405  /* read through list backwards to pick up units before values */
3406  for (i = nf - 1; i >= 0; i--)
3407  {
3408  switch (ftype[i])
3409  {
3410  case DTK_TIME:
3411  dterr = DecodeTimeForInterval(field[i], fmask, range,
3412  &tmask, itm_in);
3413  if (dterr)
3414  return dterr;
3415  if (force_negative &&
3416  itm_in->tm_usec > 0)
3417  itm_in->tm_usec = -itm_in->tm_usec;
3418  type = DTK_DAY;
3419  parsing_unit_val = false;
3420  break;
3421 
3422  case DTK_TZ:
3423 
3424  /*
3425  * Timezone means a token with a leading sign character and at
3426  * least one digit; there could be ':', '.', '-' embedded in
3427  * it as well.
3428  */
3429  Assert(*field[i] == '-' || *field[i] == '+');
3430 
3431  /*
3432  * Check for signed hh:mm or hh:mm:ss. If so, process exactly
3433  * like DTK_TIME case above, plus handling the sign.
3434  */
3435  if (strchr(field[i] + 1, ':') != NULL &&
3436  DecodeTimeForInterval(field[i] + 1, fmask, range,
3437  &tmask, itm_in) == 0)
3438  {
3439  if (*field[i] == '-')
3440  {
3441  /* flip the sign on time field */
3442  if (itm_in->tm_usec == PG_INT64_MIN)
3443  return DTERR_FIELD_OVERFLOW;
3444  itm_in->tm_usec = -itm_in->tm_usec;
3445  }
3446 
3447  if (force_negative &&
3448  itm_in->tm_usec > 0)
3449  itm_in->tm_usec = -itm_in->tm_usec;
3450 
3451  /*
3452  * Set the next type to be a day, if units are not
3453  * specified. This handles the case of '1 +02:03' since we
3454  * are reading right to left.
3455  */
3456  type = DTK_DAY;
3457  parsing_unit_val = false;
3458  break;
3459  }
3460 
3461  /*
3462  * Otherwise, fall through to DTK_NUMBER case, which can
3463  * handle signed float numbers and signed year-month values.
3464  */
3465 
3466  /* FALLTHROUGH */
3467 
3468  case DTK_DATE:
3469  case DTK_NUMBER:
3470  if (type == IGNORE_DTF)
3471  {
3472  /* use typmod to decide what rightmost field is */
3473  switch (range)
3474  {
3475  case INTERVAL_MASK(YEAR):
3476  type = DTK_YEAR;
3477  break;
3478  case INTERVAL_MASK(MONTH):
3480  type = DTK_MONTH;
3481  break;
3482  case INTERVAL_MASK(DAY):
3483  type = DTK_DAY;
3484  break;
3485  case INTERVAL_MASK(HOUR):
3487  type = DTK_HOUR;
3488  break;
3489  case INTERVAL_MASK(MINUTE):
3492  type = DTK_MINUTE;
3493  break;
3494  case INTERVAL_MASK(SECOND):
3498  type = DTK_SECOND;
3499  break;
3500  default:
3501  type = DTK_SECOND;
3502  break;
3503  }
3504  }
3505 
3506  errno = 0;
3507  val = strtoi64(field[i], &cp, 10);
3508  if (errno == ERANGE)
3509  return DTERR_FIELD_OVERFLOW;
3510 
3511  if (*cp == '-')
3512  {
3513  /* SQL "years-months" syntax */
3514  int val2;
3515 
3516  val2 = strtoint(cp + 1, &cp, 10);
3517  if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
3518  return DTERR_FIELD_OVERFLOW;
3519  if (*cp != '\0')
3520  return DTERR_BAD_FORMAT;
3521  type = DTK_MONTH;
3522  if (*field[i] == '-')
3523  val2 = -val2;
3525  return DTERR_FIELD_OVERFLOW;
3526  if (pg_add_s64_overflow(val, val2, &val))
3527  return DTERR_FIELD_OVERFLOW;
3528  fval = 0;
3529  }
3530  else if (*cp == '.')
3531  {
3532  dterr = ParseFraction(cp, &fval);
3533  if (dterr)
3534  return dterr;
3535  if (*field[i] == '-')
3536  fval = -fval;
3537  }
3538  else if (*cp == '\0')
3539  fval = 0;
3540  else
3541  return DTERR_BAD_FORMAT;
3542 
3543  tmask = 0; /* DTK_M(type); */
3544 
3545  if (force_negative)
3546  {
3547  /* val and fval should be of same sign, but test anyway */
3548  if (val > 0)
3549  val = -val;
3550  if (fval > 0)
3551  fval = -fval;
3552  }
3553 
3554  switch (type)
3555  {
3556  case DTK_MICROSEC:
3557  if (!AdjustMicroseconds(val, fval, 1, itm_in))
3558  return DTERR_FIELD_OVERFLOW;
3559  tmask = DTK_M(MICROSECOND);
3560  break;
3561 
3562  case DTK_MILLISEC:
3563  if (!AdjustMicroseconds(val, fval, 1000, itm_in))
3564  return DTERR_FIELD_OVERFLOW;
3565  tmask = DTK_M(MILLISECOND);
3566  break;
3567 
3568  case DTK_SECOND:
3569  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3570  return DTERR_FIELD_OVERFLOW;
3571 
3572  /*
3573  * If any subseconds were specified, consider this
3574  * microsecond and millisecond input as well.
3575  */
3576  if (fval == 0)
3577  tmask = DTK_M(SECOND);
3578  else
3579  tmask = DTK_ALL_SECS_M;
3580  break;
3581 
3582  case DTK_MINUTE:
3583  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3584  return DTERR_FIELD_OVERFLOW;
3585  tmask = DTK_M(MINUTE);
3586  break;
3587 
3588  case DTK_HOUR:
3589  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3590  return DTERR_FIELD_OVERFLOW;
3591  tmask = DTK_M(HOUR);
3592  type = DTK_DAY; /* set for next field */
3593  break;
3594 
3595  case DTK_DAY:
3596  if (!AdjustDays(val, 1, itm_in) ||
3597  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3598  return DTERR_FIELD_OVERFLOW;
3599  tmask = DTK_M(DAY);
3600  break;
3601 
3602  case DTK_WEEK:
3603  if (!AdjustDays(val, 7, itm_in) ||
3604  !AdjustFractDays(fval, 7, itm_in))
3605  return DTERR_FIELD_OVERFLOW;
3606  tmask = DTK_M(WEEK);
3607  break;
3608 
3609  case DTK_MONTH:
3610  if (!AdjustMonths(val, itm_in) ||
3611  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3612  return DTERR_FIELD_OVERFLOW;
3613  tmask = DTK_M(MONTH);
3614  break;
3615 
3616  case DTK_YEAR:
3617  if (!AdjustYears(val, 1, itm_in) ||
3618  !AdjustFractYears(fval, 1, itm_in))
3619  return DTERR_FIELD_OVERFLOW;
3620  tmask = DTK_M(YEAR);
3621  break;
3622 
3623  case DTK_DECADE:
3624  if (!AdjustYears(val, 10, itm_in) ||
3625  !AdjustFractYears(fval, 10, itm_in))
3626  return DTERR_FIELD_OVERFLOW;
3627  tmask = DTK_M(DECADE);
3628  break;
3629 
3630  case DTK_CENTURY:
3631  if (!AdjustYears(val, 100, itm_in) ||
3632  !AdjustFractYears(fval, 100, itm_in))
3633  return DTERR_FIELD_OVERFLOW;
3634  tmask = DTK_M(CENTURY);
3635  break;
3636 
3637  case DTK_MILLENNIUM:
3638  if (!AdjustYears(val, 1000, itm_in) ||
3639  !AdjustFractYears(fval, 1000, itm_in))
3640  return DTERR_FIELD_OVERFLOW;
3641  tmask = DTK_M(MILLENNIUM);
3642  break;
3643 
3644  default:
3645  return DTERR_BAD_FORMAT;
3646  }
3647  parsing_unit_val = false;
3648  break;
3649 
3650  case DTK_STRING:
3651  case DTK_SPECIAL:
3652  /* reject consecutive unhandled units */
3653  if (parsing_unit_val)
3654  return DTERR_BAD_FORMAT;
3655  type = DecodeUnits(i, field[i], &uval);
3656  if (type == UNKNOWN_FIELD)
3657  type = DecodeSpecial(i, field[i], &uval);
3658  if (type == IGNORE_DTF)
3659  continue;
3660 
3661  tmask = 0; /* DTK_M(type); */
3662  switch (type)
3663  {
3664  case UNITS:
3665  type = uval;
3666  parsing_unit_val = true;
3667  break;
3668 
3669  case AGO:
3670 
3671  /*
3672  * "ago" is only allowed to appear at the end of the
3673  * interval.
3674  */
3675  if (i != nf - 1)
3676  return DTERR_BAD_FORMAT;
3677  is_before = true;
3678  type = uval;
3679  break;
3680 
3681  case RESERV:
3682  tmask = (DTK_DATE_M | DTK_TIME_M);
3683 
3684  /*
3685  * Only reserved words corresponding to infinite
3686  * intervals are accepted.
3687  */
3688  if (uval != DTK_LATE && uval != DTK_EARLY)
3689  return DTERR_BAD_FORMAT;
3690 
3691  /*
3692  * Infinity cannot be followed by anything else. We
3693  * could allow "ago" to reverse the sign of infinity
3694  * but using signed infinity is more intuitive.
3695  */
3696  if (i != nf - 1)
3697  return DTERR_BAD_FORMAT;
3698 
3699  *dtype = uval;
3700  break;
3701 
3702  default:
3703  return DTERR_BAD_FORMAT;
3704  }
3705  break;
3706 
3707  default:
3708  return DTERR_BAD_FORMAT;
3709  }
3710 
3711  if (tmask & fmask)
3712  return DTERR_BAD_FORMAT;
3713  fmask |= tmask;
3714  }
3715 
3716  /* ensure that at least one time field has been found */
3717  if (fmask == 0)
3718  return DTERR_BAD_FORMAT;
3719 
3720  /* reject if unit appeared and was never handled */
3721  if (parsing_unit_val)
3722  return DTERR_BAD_FORMAT;
3723 
3724  /* finally, AGO negates everything */
3725  if (is_before)
3726  {
3727  if (itm_in->tm_usec == PG_INT64_MIN ||
3728  itm_in->tm_mday == INT_MIN ||
3729  itm_in->tm_mon == INT_MIN ||
3730  itm_in->tm_year == INT_MIN)
3731  return DTERR_FIELD_OVERFLOW;
3732 
3733  itm_in->tm_usec = -itm_in->tm_usec;
3734  itm_in->tm_mday = -itm_in->tm_mday;
3735  itm_in->tm_mon = -itm_in->tm_mon;
3736  itm_in->tm_year = -itm_in->tm_year;
3737  }
3738 
3739  return 0;
3740 }
3741 
3742 
3743 /*
3744  * Helper functions to avoid duplicated code in DecodeISO8601Interval.
3745  *
3746  * Parse a decimal value and break it into integer and fractional parts.
3747  * Set *endptr to end+1 of the parsed substring.
3748  * Returns 0 or DTERR code.
3749  */
3750 static int
3751 ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
3752 {
3753  double val;
3754 
3755  /*
3756  * Historically this has accepted anything that strtod() would take,
3757  * notably including "e" notation, so continue doing that. This is
3758  * slightly annoying because the precision of double is less than that of
3759  * int64, so we would lose accuracy for inputs larger than 2^53 or so.
3760  * However, historically we rejected inputs outside the int32 range,
3761  * making that concern moot. What we do now is reject abs(val) above
3762  * 1.0e15 (a round number a bit less than 2^50), so that any accepted
3763  * value will have an exact integer part, and thereby a fraction part with
3764  * abs(*fpart) less than 1. In the absence of field complaints it doesn't
3765  * seem worth working harder.
3766  */
3767  if (!(isdigit((unsigned char) *str) || *str == '-' || *str == '.'))
3768  return DTERR_BAD_FORMAT;
3769  errno = 0;
3770  val = strtod(str, endptr);
3771  /* did we not see anything that looks like a double? */
3772  if (*endptr == str || errno != 0)
3773  return DTERR_BAD_FORMAT;
3774  /* watch out for overflow, including infinities; reject NaN too */
3775  if (isnan(val) || val < -1.0e15 || val > 1.0e15)
3776  return DTERR_FIELD_OVERFLOW;
3777  /* be very sure we truncate towards zero (cf dtrunc()) */
3778  if (val >= 0)
3779  *ipart = (int64) floor(val);
3780  else
3781  *ipart = (int64) -floor(-val);
3782  *fpart = val - *ipart;
3783  /* Callers expect this to hold */
3784  Assert(*fpart > -1.0 && *fpart < 1.0);
3785  return 0;
3786 }
3787 
3788 /*
3789  * Determine number of integral digits in a valid ISO 8601 number field
3790  * (we should ignore sign and any fraction part)
3791  */
3792 static int
3793 ISO8601IntegerWidth(char *fieldstart)
3794 {
3795  /* We might have had a leading '-' */
3796  if (*fieldstart == '-')
3797  fieldstart++;
3798  return strspn(fieldstart, "0123456789");
3799 }
3800 
3801 
3802 /* DecodeISO8601Interval()
3803  * Decode an ISO 8601 time interval of the "format with designators"
3804  * (section 4.4.3.2) or "alternative format" (section 4.4.3.3)
3805  * Examples: P1D for 1 day
3806  * PT1H for 1 hour
3807  * P2Y6M7DT1H30M for 2 years, 6 months, 7 days 1 hour 30 min
3808  * P0002-06-07T01:30:00 the same value in alternative format
3809  *
3810  * Returns 0 if successful, DTERR code if bogus input detected.
3811  * Note: error code should be DTERR_BAD_FORMAT if input doesn't look like
3812  * ISO8601, otherwise this could cause unexpected error messages.
3813  * dtype and itm_in are output parameters.
3814  *
3815  * A couple exceptions from the spec:
3816  * - a week field ('W') may coexist with other units
3817  * - allows decimals in fields other than the least significant unit.
3818  */
3819 int
3821  int *dtype, struct pg_itm_in *itm_in)
3822 {
3823  bool datepart = true;
3824  bool havefield = false;
3825 
3826  *dtype = DTK_DELTA;
3827  ClearPgItmIn(itm_in);
3828 
3829  if (strlen(str) < 2 || str[0] != 'P')
3830  return DTERR_BAD_FORMAT;
3831 
3832  str++;
3833  while (*str)
3834  {
3835  char *fieldstart;
3836  int64 val;
3837  double fval;
3838  char unit;
3839  int dterr;
3840 
3841  if (*str == 'T') /* T indicates the beginning of the time part */
3842  {
3843  datepart = false;
3844  havefield = false;
3845  str++;
3846  continue;
3847  }
3848 
3849  fieldstart = str;
3850  dterr = ParseISO8601Number(str, &str, &val, &fval);
3851  if (dterr)
3852  return dterr;
3853 
3854  /*
3855  * Note: we could step off the end of the string here. Code below
3856  * *must* exit the loop if unit == '\0'.
3857  */
3858  unit = *str++;
3859 
3860  if (datepart)
3861  {
3862  switch (unit) /* before T: Y M W D */
3863  {
3864  case 'Y':
3865  if (!AdjustYears(val, 1, itm_in) ||
3866  !AdjustFractYears(fval, 1, itm_in))
3867  return DTERR_FIELD_OVERFLOW;
3868  break;
3869  case 'M':
3870  if (!AdjustMonths(val, itm_in) ||
3871  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3872  return DTERR_FIELD_OVERFLOW;
3873  break;
3874  case 'W':
3875  if (!AdjustDays(val, 7, itm_in) ||
3876  !AdjustFractDays(fval, 7, itm_in))
3877  return DTERR_FIELD_OVERFLOW;
3878  break;
3879  case 'D':
3880  if (!AdjustDays(val, 1, itm_in) ||
3881  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3882  return DTERR_FIELD_OVERFLOW;
3883  break;
3884  case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
3885  case '\0':
3886  if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
3887  {
3888  if (!AdjustYears(val / 10000, 1, itm_in) ||
3889  !AdjustMonths((val / 100) % 100, itm_in) ||
3890  !AdjustDays(val % 100, 1, itm_in) ||
3891  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3892  return DTERR_FIELD_OVERFLOW;
3893  if (unit == '\0')
3894  return 0;
3895  datepart = false;
3896  havefield = false;
3897  continue;
3898  }
3899  /* Else fall through to extended alternative format */
3900  /* FALLTHROUGH */
3901  case '-': /* ISO 8601 4.4.3.3 Alternative Format,
3902  * Extended */
3903  if (havefield)
3904  return DTERR_BAD_FORMAT;
3905 
3906  if (!AdjustYears(val, 1, itm_in) ||
3907  !AdjustFractYears(fval, 1, itm_in))
3908  return DTERR_FIELD_OVERFLOW;
3909  if (unit == '\0')
3910  return 0;
3911  if (unit == 'T')
3912  {
3913  datepart = false;
3914  havefield = false;
3915  continue;
3916  }
3917 
3918  dterr = ParseISO8601Number(str, &str, &val, &fval);
3919  if (dterr)
3920  return dterr;
3921  if (!AdjustMonths(val, itm_in) ||
3922  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3923  return DTERR_FIELD_OVERFLOW;
3924  if (*str == '\0')
3925  return 0;
3926  if (*str == 'T')
3927  {
3928  datepart = false;
3929  havefield = false;
3930  continue;
3931  }
3932  if (*str != '-')
3933  return DTERR_BAD_FORMAT;
3934  str++;
3935 
3936  dterr = ParseISO8601Number(str, &str, &val, &fval);
3937  if (dterr)
3938  return dterr;
3939  if (!AdjustDays(val, 1, itm_in) ||
3940  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3941  return DTERR_FIELD_OVERFLOW;
3942  if (*str == '\0')
3943  return 0;
3944  if (*str == 'T')
3945  {
3946  datepart = false;
3947  havefield = false;
3948  continue;
3949  }
3950  return DTERR_BAD_FORMAT;
3951  default:
3952  /* not a valid date unit suffix */
3953  return DTERR_BAD_FORMAT;
3954  }
3955  }
3956  else
3957  {
3958  switch (unit) /* after T: H M S */
3959  {
3960  case 'H':
3961  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3962  return DTERR_FIELD_OVERFLOW;
3963  break;
3964  case 'M':
3965  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3966  return DTERR_FIELD_OVERFLOW;
3967  break;
3968  case 'S':
3969  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3970  return DTERR_FIELD_OVERFLOW;
3971  break;
3972  case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
3973  if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
3974  {
3975  if (!AdjustMicroseconds(val / 10000, 0, USECS_PER_HOUR, itm_in) ||
3976  !AdjustMicroseconds((val / 100) % 100, 0, USECS_PER_MINUTE, itm_in) ||
3977  !AdjustMicroseconds(val % 100, 0, USECS_PER_SEC, itm_in) ||
3978  !AdjustFractMicroseconds(fval, 1, itm_in))
3979  return DTERR_FIELD_OVERFLOW;
3980  return 0;
3981  }
3982  /* Else fall through to extended alternative format */
3983  /* FALLTHROUGH */
3984  case ':': /* ISO 8601 4.4.3.3 Alternative Format,
3985  * Extended */
3986  if (havefield)
3987  return DTERR_BAD_FORMAT;
3988 
3989  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3990  return DTERR_FIELD_OVERFLOW;
3991  if (unit == '\0')
3992  return 0;
3993 
3994  dterr = ParseISO8601Number(str, &str, &val, &fval);
3995  if (dterr)
3996  return dterr;
3997  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3998  return DTERR_FIELD_OVERFLOW;
3999  if (*str == '\0')
4000  return 0;
4001  if (*str != ':')
4002  return DTERR_BAD_FORMAT;
4003  str++;
4004 
4005  dterr = ParseISO8601Number(str, &str, &val, &fval);
4006  if (dterr)
4007  return dterr;
4008  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
4009  return DTERR_FIELD_OVERFLOW;
4010  if (*str == '\0')
4011  return 0;
4012  return DTERR_BAD_FORMAT;
4013 
4014  default:
4015  /* not a valid time unit suffix */
4016  return DTERR_BAD_FORMAT;
4017  }
4018  }
4019 
4020  havefield = true;
4021  }
4022 
4023  return 0;
4024 }
4025 
4026 
4027 /* DecodeUnits()
4028  * Decode text string using lookup table.
4029  *
4030  * This routine recognizes keywords associated with time interval units.
4031  *
4032  * Given string must be lowercased already.
4033  *
4034  * Implement a cache lookup since it is likely that dates
4035  * will be related in format.
4036  */
4037 int
4038 DecodeUnits(int field, const char *lowtoken, int *val)
4039 {
4040  int type;
4041  const datetkn *tp;
4042 
4043  tp = deltacache[field];
4044  /* use strncmp so that we match truncated tokens */
4045  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
4046  {
4047  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
4048  }
4049  if (tp == NULL)
4050  {
4051  type = UNKNOWN_FIELD;
4052  *val = 0;
4053  }
4054  else
4055  {
4056  deltacache[field] = tp;
4057  type = tp->type;
4058  *val = tp->value;
4059  }
4060 
4061  return type;
4062 } /* DecodeUnits() */
4063 
4064 /*
4065  * Report an error detected by one of the datetime input processing routines.
4066  *
4067  * dterr is the error code, and *extra contains any auxiliary info we need
4068  * for the error report. extra can be NULL if not needed for the particular
4069  * dterr value.
4070  *
4071  * str is the original input string, and datatype is the name of the datatype
4072  * we were trying to accept. (For some DTERR codes, these are not used and
4073  * can be NULL.)
4074  *
4075  * If escontext points to an ErrorSaveContext node, that is filled instead
4076  * of throwing an error.
4077  *
4078  * Note: it might seem useless to distinguish DTERR_INTERVAL_OVERFLOW and
4079  * DTERR_TZDISP_OVERFLOW from DTERR_FIELD_OVERFLOW, but SQL99 mandates three
4080  * separate SQLSTATE codes, so ...
4081  */
4082 void
4084  const char *str, const char *datatype,
4085  Node *escontext)
4086 {
4087  switch (dterr)
4088  {
4089  case DTERR_FIELD_OVERFLOW:
4090  errsave(escontext,
4091  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
4092  errmsg("date/time field value out of range: \"%s\"",
4093  str)));
4094  break;
4096  /* <nanny>same as above, but add hint about DateStyle</nanny> */
4097  errsave(escontext,
4098  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
4099  errmsg("date/time field value out of range: \"%s\"",
4100  str),
4101  errhint("Perhaps you need a different \"datestyle\" setting.")));
4102  break;
4104  errsave(escontext,
4105  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
4106  errmsg("interval field value out of range: \"%s\"",
4107  str)));
4108  break;
4109  case DTERR_TZDISP_OVERFLOW:
4110  errsave(escontext,
4111  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
4112  errmsg("time zone displacement out of range: \"%s\"",
4113  str)));
4114  break;
4115  case DTERR_BAD_TIMEZONE:
4116  errsave(escontext,
4117  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4118  errmsg("time zone \"%s\" not recognized",
4119  extra->dtee_timezone)));
4120  break;
4121  case DTERR_BAD_ZONE_ABBREV:
4122  errsave(escontext,
4123  (errcode(ERRCODE_CONFIG_FILE_ERROR),
4124  errmsg("time zone \"%s\" not recognized",
4125  extra->dtee_timezone),
4126  errdetail("This time zone name appears in the configuration file for time zone abbreviation \"%s\".",
4127  extra->dtee_abbrev)));
4128  break;
4129  case DTERR_BAD_FORMAT:
4130  default:
4131  errsave(escontext,
4132  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4133  errmsg("invalid input syntax for type %s: \"%s\"",
4134  datatype, str)));
4135  break;
4136  }
4137 }
4138 
4139 /* datebsearch()
4140  * Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
4141  * is WAY faster than the generic bsearch().
4142  */
4143 static const datetkn *
4144 datebsearch(const char *key, const datetkn *base, int nel)
4145 {
4146  if (nel > 0)
4147  {
4148  const datetkn *last = base + nel - 1,
4149  *position;
4150  int result;
4151 
4152  while (last >= base)
4153  {
4154  position = base + ((last - base) >> 1);
4155  /* precheck the first character for a bit of extra speed */
4156  result = (int) key[0] - (int) position->token[0];
4157  if (result == 0)
4158  {
4159  /* use strncmp so that we match truncated tokens */
4160  result = strncmp(key, position->token, TOKMAXLEN);
4161  if (result == 0)
4162  return position;
4163  }
4164  if (result < 0)
4165  last = position - 1;
4166  else
4167  base = position + 1;
4168  }
4169  }
4170  return NULL;
4171 }
4172 
4173 /* EncodeTimezone()
4174  * Copies representation of a numeric timezone offset to str.
4175  *
4176  * Returns a pointer to the new end of string. No NUL terminator is put
4177  * there; callers are responsible for NUL terminating str themselves.
4178  */
4179 static char *
4180 EncodeTimezone(char *str, int tz, int style)
4181 {
4182  int hour,
4183  min,
4184  sec;
4185 
4186  sec = abs(tz);
4187  min = sec / SECS_PER_MINUTE;
4188  sec -= min * SECS_PER_MINUTE;
4189  hour = min / MINS_PER_HOUR;
4190  min -= hour * MINS_PER_HOUR;
4191 
4192  /* TZ is negated compared to sign we wish to display ... */
4193  *str++ = (tz <= 0 ? '+' : '-');
4194 
4195  if (sec != 0)
4196  {
4197  str = pg_ultostr_zeropad(str, hour, 2);
4198  *str++ = ':';
4199  str = pg_ultostr_zeropad(str, min, 2);
4200  *str++ = ':';
4201  str = pg_ultostr_zeropad(str, sec, 2);
4202  }
4203  else if (min != 0 || style == USE_XSD_DATES)
4204  {
4205  str = pg_ultostr_zeropad(str, hour, 2);
4206  *str++ = ':';
4207  str = pg_ultostr_zeropad(str, min, 2);
4208  }
4209  else
4210  str = pg_ultostr_zeropad(str, hour, 2);
4211  return str;
4212 }
4213 
4214 /* EncodeDateOnly()
4215  * Encode date as local time.
4216  */
4217 void
4218 EncodeDateOnly(struct pg_tm *tm, int style, char *str)
4219 {
4220  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4221 
4222  switch (style)
4223  {
4224  case USE_ISO_DATES:
4225  case USE_XSD_DATES:
4226  /* compatible with ISO date formats */
4228  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4229  *str++ = '-';
4231  *str++ = '-';
4233  break;
4234 
4235  case USE_SQL_DATES:
4236  /* compatible with Oracle/Ingres date formats */
4237  if (DateOrder == DATEORDER_DMY)
4238  {
4240  *str++ = '/';
4242  }
4243  else
4244  {
4246  *str++ = '/';
4248  }
4249  *str++ = '/';
4251  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4252  break;
4253 
4254  case USE_GERMAN_DATES:
4255  /* German-style date format */
4257  *str++ = '.';
4259  *str++ = '.';
4261  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4262  break;
4263 
4264  case USE_POSTGRES_DATES:
4265  default:
4266  /* traditional date-only style for Postgres */
4267  if (DateOrder == DATEORDER_DMY)
4268  {
4270  *str++ = '-';
4272  }
4273  else
4274  {
4276  *str++ = '-';
4278  }
4279  *str++ = '-';
4281  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4282  break;
4283  }
4284 
4285  if (tm->tm_year <= 0)
4286  {
4287  memcpy(str, " BC", 3); /* Don't copy NUL */
4288  str += 3;
4289  }
4290  *str = '\0';
4291 }
4292 
4293 
4294 /* EncodeTimeOnly()
4295  * Encode time fields only.
4296  *
4297  * tm and fsec are the value to encode, print_tz determines whether to include
4298  * a time zone (the difference between time and timetz types), tz is the
4299  * numeric time zone offset, style is the date style, str is where to write the
4300  * output.
4301  */
4302 void
4303 EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
4304 {
4306  *str++ = ':';
4308  *str++ = ':';
4309  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
4310  if (print_tz)
4311  str = EncodeTimezone(str, tz, style);
4312  *str = '\0';
4313 }
4314 
4315 
4316 /* EncodeDateTime()
4317  * Encode date and time interpreted as local time.
4318  *
4319  * tm and fsec are the value to encode, print_tz determines whether to include
4320  * a time zone (the difference between timestamp and timestamptz types), tz is
4321  * the numeric time zone offset, tzn is the textual time zone, which if
4322  * specified will be used instead of tz by some styles, style is the date
4323  * style, str is where to write the output.
4324  *
4325  * Supported date styles:
4326  * Postgres - day mon hh:mm:ss yyyy tz
4327  * SQL - mm/dd/yyyy hh:mm:ss.ss tz
4328  * ISO - yyyy-mm-dd hh:mm:ss+/-tz
4329  * German - dd.mm.yyyy hh:mm:ss tz
4330  * XSD - yyyy-mm-ddThh:mm:ss.ss+/-tz
4331  */
4332 void
4333 EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
4334 {
4335  int day;
4336 
4337  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4338 
4339  /*
4340  * Negative tm_isdst means we have no valid time zone translation.
4341  */
4342  if (tm->tm_isdst < 0)
4343  print_tz = false;
4344 
4345  switch (style)
4346  {
4347  case USE_ISO_DATES:
4348  case USE_XSD_DATES:
4349  /* Compatible with ISO-8601 date formats */
4351  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4352  *str++ = '-';
4354  *str++ = '-';
4356  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4358  *str++ = ':';
4360  *str++ = ':';
4361  str = AppendTimestampSeconds(str, tm, fsec);
4362  if (print_tz)
4363  str = EncodeTimezone(str, tz, style);
4364  break;
4365 
4366  case USE_SQL_DATES:
4367  /* Compatible with Oracle/Ingres date formats */
4368  if (DateOrder == DATEORDER_DMY)
4369  {
4371  *str++ = '/';
4373  }
4374  else
4375  {
4377  *str++ = '/';
4379  }
4380  *str++ = '/';
4382  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4383  *str++ = ' ';
4385  *str++ = ':';
4387  *str++ = ':';
4388  str = AppendTimestampSeconds(str, tm, fsec);
4389 
4390  /*
4391  * Note: the uses of %.*s in this function would be risky if the
4392  * timezone names ever contain non-ASCII characters, since we are
4393  * not being careful to do encoding-aware clipping. However, all
4394  * TZ abbreviations in the IANA database are plain ASCII.
4395  */
4396  if (print_tz)
4397  {
4398  if (tzn)
4399  {
4400  sprintf(str, " %.*s", MAXTZLEN, tzn);
4401  str += strlen(str);
4402  }
4403  else
4404  str = EncodeTimezone(str, tz, style);
4405  }
4406  break;
4407 
4408  case USE_GERMAN_DATES:
4409  /* German variant on European style */
4411  *str++ = '.';
4413  *str++ = '.';
4415  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4416  *str++ = ' ';
4418  *str++ = ':';
4420  *str++ = ':';
4421  str = AppendTimestampSeconds(str, tm, fsec);
4422 
4423  if (print_tz)
4424  {
4425  if (tzn)
4426  {
4427  sprintf(str, " %.*s", MAXTZLEN, tzn);
4428  str += strlen(str);
4429  }
4430  else
4431  str = EncodeTimezone(str, tz, style);
4432  }
4433  break;
4434 
4435  case USE_POSTGRES_DATES:
4436  default:
4437  /* Backward-compatible with traditional Postgres abstime dates */
4438  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4439  tm->tm_wday = j2day(day);
4440  memcpy(str, days[tm->tm_wday], 3);
4441  str += 3;
4442  *str++ = ' ';
4443  if (DateOrder == DATEORDER_DMY)
4444  {
4446  *str++ = ' ';
4447  memcpy(str, months[tm->tm_mon - 1], 3);
4448  str += 3;
4449  }
4450  else
4451  {
4452  memcpy(str, months[tm->tm_mon - 1], 3);
4453  str += 3;
4454  *str++ = ' ';
4456  }
4457  *str++ = ' ';
4459  *str++ = ':';
4461  *str++ = ':';
4462  str = AppendTimestampSeconds(str, tm, fsec);
4463  *str++ = ' ';
4465  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4466 
4467  if (print_tz)
4468  {
4469  if (tzn)
4470  {
4471  sprintf(str, " %.*s", MAXTZLEN, tzn);
4472  str += strlen(str);
4473  }
4474  else
4475  {
4476  /*
4477  * We have a time zone, but no string version. Use the
4478  * numeric form, but be sure to include a leading space to
4479  * avoid formatting something which would be rejected by
4480  * the date/time parser later. - thomas 2001-10-19
4481  */
4482  *str++ = ' ';
4483  str = EncodeTimezone(str, tz, style);
4484  }
4485  }
4486  break;
4487  }
4488 
4489  if (tm->tm_year <= 0)
4490  {
4491  memcpy(str, " BC", 3); /* Don't copy NUL */
4492  str += 3;
4493  }
4494  *str = '\0';
4495 }
4496 
4497 
4498 /*
4499  * Helper functions to avoid duplicated code in EncodeInterval.
4500  */
4501 
4502 /* Append an ISO-8601-style interval field, but only if value isn't zero */
4503 static char *
4504 AddISO8601IntPart(char *cp, int64 value, char units)
4505 {
4506  if (value == 0)
4507  return cp;
4508  sprintf(cp, "%lld%c", (long long) value, units);
4509  return cp + strlen(cp);
4510 }
4511 
4512 /* Append a postgres-style interval field, but only if value isn't zero */
4513 static char *
4514 AddPostgresIntPart(char *cp, int64 value, const char *units,
4515  bool *is_zero, bool *is_before)
4516 {
4517  if (value == 0)
4518  return cp;
4519  sprintf(cp, "%s%s%lld %s%s",
4520  (!*is_zero) ? " " : "",
4521  (*is_before && value > 0) ? "+" : "",
4522  (long long) value,
4523  units,
4524  (value != 1) ? "s" : "");
4525 
4526  /*
4527  * Each nonzero field sets is_before for (only) the next one. This is a
4528  * tad bizarre but it's how it worked before...
4529  */
4530  *is_before = (value < 0);
4531  *is_zero = false;
4532  return cp + strlen(cp);
4533 }
4534 
4535 /* Append a verbose-style interval field, but only if value isn't zero */
4536 static char *
4537 AddVerboseIntPart(char *cp, int64 value, const char *units,
4538  bool *is_zero, bool *is_before)
4539 {
4540  if (value == 0)
4541  return cp;
4542  /* first nonzero value sets is_before */
4543  if (*is_zero)
4544  {
4545  *is_before = (value < 0);
4546  value = i64abs(value);
4547  }
4548  else if (*is_before)
4549  value = -value;
4550  sprintf(cp, " %lld %s%s", (long long) value, units, (value == 1) ? "" : "s");
4551  *is_zero = false;
4552  return cp + strlen(cp);
4553 }
4554 
4555 
4556 /* EncodeInterval()
4557  * Interpret time structure as a delta time and convert to string.
4558  *
4559  * Support "traditional Postgres" and ISO-8601 styles.
4560  * Actually, afaik ISO does not address time interval formatting,
4561  * but this looks similar to the spec for absolute date/time.
4562  * - thomas 1998-04-30
4563  *
4564  * Actually, afaik, ISO 8601 does specify formats for "time
4565  * intervals...[of the]...format with time-unit designators", which
4566  * are pretty ugly. The format looks something like
4567  * P1Y1M1DT1H1M1.12345S
4568  * but useful for exchanging data with computers instead of humans.
4569  * - ron 2003-07-14
4570  *
4571  * And ISO's SQL 2008 standard specifies standards for
4572  * "year-month literal"s (that look like '2-3') and
4573  * "day-time literal"s (that look like ('4 5:6:7')
4574  */
4575 void
4576 EncodeInterval(struct pg_itm *itm, int style, char *str)
4577 {
4578  char *cp = str;
4579  int year = itm->tm_year;
4580  int mon = itm->tm_mon;
4581  int64 mday = itm->tm_mday; /* tm_mday could be INT_MIN */
4582  int64 hour = itm->tm_hour;
4583  int min = itm->tm_min;
4584  int sec = itm->tm_sec;
4585  int fsec = itm->tm_usec;
4586  bool is_before = false;
4587  bool is_zero = true;
4588 
4589  /*
4590  * The sign of year and month are guaranteed to match, since they are
4591  * stored internally as "month". But we'll need to check for is_before and
4592  * is_zero when determining the signs of day and hour/minute/seconds
4593  * fields.
4594  */
4595  switch (style)
4596  {
4597  /* SQL Standard interval format */
4598  case INTSTYLE_SQL_STANDARD:
4599  {
4600  bool has_negative = year < 0 || mon < 0 ||
4601  mday < 0 || hour < 0 ||
4602  min < 0 || sec < 0 || fsec < 0;
4603  bool has_positive = year > 0 || mon > 0 ||
4604  mday > 0 || hour > 0 ||
4605  min > 0 || sec > 0 || fsec > 0;
4606  bool has_year_month = year != 0 || mon != 0;
4607  bool has_day_time = mday != 0 || hour != 0 ||
4608  min != 0 || sec != 0 || fsec != 0;
4609  bool has_day = mday != 0;
4610  bool sql_standard_value = !(has_negative && has_positive) &&
4611  !(has_year_month && has_day_time);
4612 
4613  /*
4614  * SQL Standard wants only 1 "<sign>" preceding the whole
4615  * interval ... but can't do that if mixed signs.
4616  */
4617  if (has_negative && sql_standard_value)
4618  {
4619  *cp++ = '-';
4620  year = -year;
4621  mon = -mon;
4622  mday = -mday;
4623  hour = -hour;
4624  min = -min;
4625  sec = -sec;
4626  fsec = -fsec;
4627  }
4628 
4629  if (!has_negative && !has_positive)
4630  {
4631  sprintf(cp, "0");
4632  }
4633  else if (!sql_standard_value)
4634  {
4635  /*
4636  * For non sql-standard interval values, force outputting
4637  * the signs to avoid ambiguities with intervals with
4638  * mixed sign components.
4639  */
4640  char year_sign = (year < 0 || mon < 0) ? '-' : '+';
4641  char day_sign = (mday < 0) ? '-' : '+';
4642  char sec_sign = (hour < 0 || min < 0 ||
4643  sec < 0 || fsec < 0) ? '-' : '+';
4644 
4645  sprintf(cp, "%c%d-%d %c%lld %c%lld:%02d:",
4646  year_sign, abs(year), abs(mon),
4647  day_sign, (long long) i64abs(mday),
4648  sec_sign, (long long) i64abs(hour), abs(min));
4649  cp += strlen(cp);
4650  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4651  *cp = '\0';
4652  }
4653  else if (has_year_month)
4654  {
4655  sprintf(cp, "%d-%d", year, mon);
4656  }
4657  else if (has_day)
4658  {
4659  sprintf(cp, "%lld %lld:%02d:",
4660  (long long) mday, (long long) hour, min);
4661  cp += strlen(cp);
4662  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4663  *cp = '\0';
4664  }
4665  else
4666  {
4667  sprintf(cp, "%lld:%02d:", (long long) hour, min);
4668  cp += strlen(cp);
4669  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4670  *cp = '\0';
4671  }
4672  }
4673  break;
4674 
4675  /* ISO 8601 "time-intervals by duration only" */
4676  case INTSTYLE_ISO_8601:
4677  /* special-case zero to avoid printing nothing */
4678  if (year == 0 && mon == 0 && mday == 0 &&
4679  hour == 0 && min == 0 && sec == 0 && fsec == 0)
4680  {
4681  sprintf(cp, "PT0S");
4682  break;
4683  }
4684  *cp++ = 'P';
4685  cp = AddISO8601IntPart(cp, year, 'Y');
4686  cp = AddISO8601IntPart(cp, mon, 'M');
4687  cp = AddISO8601IntPart(cp, mday, 'D');
4688  if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
4689  *cp++ = 'T';
4690  cp = AddISO8601IntPart(cp, hour, 'H');
4691  cp = AddISO8601IntPart(cp, min, 'M');
4692  if (sec != 0 || fsec != 0)
4693  {
4694  if (sec < 0 || fsec < 0)
4695  *cp++ = '-';
4696  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4697  *cp++ = 'S';
4698  *cp++ = '\0';
4699  }
4700  break;
4701 
4702  /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
4703  case INTSTYLE_POSTGRES:
4704  cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
4705 
4706  /*
4707  * Ideally we should spell out "month" like we do for "year" and
4708  * "day". However, for backward compatibility, we can't easily
4709  * fix this. bjm 2011-05-24
4710  */
4711  cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
4712  cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
4713  if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
4714  {
4715  bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
4716 
4717  sprintf(cp, "%s%s%02lld:%02d:",
4718  is_zero ? "" : " ",
4719  (minus ? "-" : (is_before ? "+" : "")),
4720  (long long) i64abs(hour), abs(min));
4721  cp += strlen(cp);
4722  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4723  *cp = '\0';
4724  }
4725  break;
4726 
4727  /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
4729  default:
4730  strcpy(cp, "@");
4731  cp++;
4732  cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
4733  cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
4734  cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
4735  cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
4736  cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
4737  if (sec != 0 || fsec != 0)
4738  {
4739  *cp++ = ' ';
4740  if (sec < 0 || (sec == 0 && fsec < 0))
4741  {
4742  if (is_zero)
4743  is_before = true;
4744  else if (!is_before)
4745  *cp++ = '-';
4746  }
4747  else if (is_before)
4748  *cp++ = '-';
4749  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4750  /* We output "ago", not negatives, so use abs(). */
4751  sprintf(cp, " sec%s",
4752  (abs(sec) != 1 || fsec != 0) ? "s" : "");
4753  is_zero = false;
4754  }
4755  /* identically zero? then put in a unitless zero... */
4756  if (is_zero)
4757  strcat(cp, " 0");
4758  if (is_before)
4759  strcat(cp, " ago");
4760  break;
4761  }
4762 }
4763 
4764 
4765 /*
4766  * We've been burnt by stupid errors in the ordering of the datetkn tables
4767  * once too often. Arrange to check them during postmaster start.
4768  */
4769 static bool
4770 CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
4771 {
4772  bool ok = true;
4773  int i;
4774 
4775  for (i = 0; i < nel; i++)
4776  {
4777  /* check for token strings that don't fit */
4778  if (strlen(base[i].token) > TOKMAXLEN)
4779  {
4780  /* %.*s is safe since all our tokens are ASCII */
4781  elog(LOG, "token too long in %s table: \"%.*s\"",
4782  tablename,
4783  TOKMAXLEN + 1, base[i].token);
4784  ok = false;
4785  break; /* don't risk applying strcmp */
4786  }
4787  /* check for out of order */
4788  if (i > 0 &&
4789  strcmp(base[i - 1].token, base[i].token) >= 0)
4790  {
4791  elog(LOG, "ordering error in %s table: \"%s\" >= \"%s\"",
4792  tablename,
4793  base[i - 1].token,
4794  base[i].token);
4795  ok = false;
4796  }
4797  }
4798  return ok;
4799 }
4800 
4801 bool
4803 {
4804  bool ok = true;
4805 
4806  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4807  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4808 
4809  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4810  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4811  return ok;
4812 }
4813 
4814 /*
4815  * Common code for temporal prosupport functions: simplify, if possible,
4816  * a call to a temporal type's length-coercion function.
4817  *
4818  * Types time, timetz, timestamp and timestamptz each have a range of allowed
4819  * precisions. An unspecified precision is rigorously equivalent to the
4820  * highest specifiable precision. We can replace the function call with a
4821  * no-op RelabelType if it is coercing to the same or higher precision as the
4822  * input is known to have.
4823  *
4824  * The input Node is always a FuncExpr, but to reduce the #include footprint
4825  * of datetime.h, we declare it as Node *.
4826  *
4827  * Note: timestamp_scale throws an error when the typmod is out of range, but
4828  * we can't get there from a cast: our typmodin will have caught it already.
4829  */
4830 Node *
4831 TemporalSimplify(int32 max_precis, Node *node)
4832 {
4833  FuncExpr *expr = castNode(FuncExpr, node);
4834  Node *ret = NULL;
4835  Node *typmod;
4836 
4837  Assert(list_length(expr->args) >= 2);
4838 
4839  typmod = (Node *) lsecond(expr->args);
4840 
4841  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
4842  {
4843  Node *source = (Node *) linitial(expr->args);
4844  int32 old_precis = exprTypmod(source);
4845  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4846 
4847  if (new_precis < 0 || new_precis == max_precis ||
4848  (old_precis >= 0 && new_precis >= old_precis))
4849  ret = relabel_to_typmod(source, new_precis);
4850  }
4851 
4852  return ret;
4853 }
4854 
4855 /*
4856  * This function gets called during timezone config file load or reload
4857  * to create the final array of timezone tokens. The argument array
4858  * is already sorted in name order.
4859  *
4860  * The result is a TimeZoneAbbrevTable (which must be a single guc_malloc'd
4861  * chunk) or NULL on alloc failure. No other error conditions are defined.
4862  */
4864 ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs, int n)
4865 {
4866  TimeZoneAbbrevTable *tbl;
4867  Size tbl_size;
4868  int i;
4869 
4870  /* Space for fixed fields and datetkn array */
4871  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4872  n * sizeof(datetkn);
4873  tbl_size = MAXALIGN(tbl_size);
4874  /* Count up space for dynamic abbreviations */
4875  for (i = 0; i < n; i++)
4876  {
4877  struct tzEntry *abbr = abbrevs + i;
4878 
4879  if (abbr->zone != NULL)
4880  {
4881  Size dsize;
4882 
4883  dsize = offsetof(DynamicZoneAbbrev, zone) +
4884  strlen(abbr->zone) + 1;
4885  tbl_size += MAXALIGN(dsize);
4886  }
4887  }
4888 
4889  /* Alloc the result ... */
4890  tbl = guc_malloc(LOG, tbl_size);
4891  if (!tbl)
4892  return NULL;
4893 
4894  /* ... and fill it in */
4895  tbl->tblsize = tbl_size;
4896  tbl->numabbrevs = n;
4897  /* in this loop, tbl_size reprises the space calculation above */
4898  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4899  n * sizeof(datetkn);
4900  tbl_size = MAXALIGN(tbl_size);
4901  for (i = 0; i < n; i++)
4902  {
4903  struct tzEntry *abbr = abbrevs + i;
4904  datetkn *dtoken = tbl->abbrevs + i;
4905 
4906  /* use strlcpy to truncate name if necessary */
4907  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4908  if (abbr->zone != NULL)
4909  {
4910  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4911  DynamicZoneAbbrev *dtza;
4912  Size dsize;
4913 
4914  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4915  dtza->tz = NULL;
4916  strcpy(dtza->zone, abbr->zone);
4917 
4918  dtoken->type = DYNTZ;
4919  /* value is offset from table start to DynamicZoneAbbrev */
4920  dtoken->value = (int32) tbl_size;
4921 
4922  dsize = offsetof(DynamicZoneAbbrev, zone) +
4923  strlen(abbr->zone) + 1;
4924  tbl_size += MAXALIGN(dsize);
4925  }
4926  else
4927  {
4928  dtoken->type = abbr->is_dst ? DTZ : TZ;
4929  dtoken->value = abbr->offset;
4930  }
4931  }
4932 
4933  /* Assert the two loops above agreed on size calculations */
4934  Assert(tbl->tblsize == tbl_size);
4935 
4936  /* Check the ordering, if testing */
4937  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4938 
4939  return tbl;
4940 }
4941 
4942 /*
4943  * Install a TimeZoneAbbrevTable as the active table.
4944  *
4945  * Caller is responsible that the passed table doesn't go away while in use.
4946  */
4947 void
4949 {
4950  zoneabbrevtbl = tbl;
4951  /* reset abbrevcache, which may contain pointers into old table */
4952  memset(abbrevcache, 0, sizeof(abbrevcache));
4953 }
4954 
4955 /*
4956  * Helper subroutine to locate pg_tz timezone for a dynamic abbreviation.
4957  *
4958  * On failure, returns NULL and fills *extra for a DTERR_BAD_ZONE_ABBREV error.
4959  */
4960 static pg_tz *
4962  DateTimeErrorExtra *extra)
4963 {
4964  DynamicZoneAbbrev *dtza;
4965 
4966  /* Just some sanity checks to prevent indexing off into nowhere */
4967  Assert(tp->type == DYNTZ);
4968  Assert(tp->value > 0 && tp->value < tbl->tblsize);
4969 
4970  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tp->value);
4971 
4972  /* Look up the underlying zone if we haven't already */
4973  if (dtza->tz == NULL)
4974  {
4975  dtza->tz = pg_tzset(dtza->zone);
4976  if (dtza->tz == NULL)
4977  {
4978  /* Ooops, bogus zone name in config file entry */
4979  extra->dtee_timezone = dtza->zone;
4980  extra->dtee_abbrev = tp->token;
4981  }
4982  }
4983  return dtza->tz;
4984 }
4985 
4986 
4987 /*
4988  * This set-returning function reads all the available time zone abbreviations
4989  * and returns a set of (abbrev, utc_offset, is_dst).
4990  */
4991 Datum
4993 {
4994  FuncCallContext *funcctx;
4995  int *pindex;
4996  Datum result;
4997  HeapTuple tuple;
4998  Datum values[3];
4999  bool nulls[3] = {0};
5000  const datetkn *tp;
5001  char buffer[TOKMAXLEN + 1];
5002  int gmtoffset;
5003  bool is_dst;
5004  unsigned char *p;
5005  struct pg_itm_in itm_in;
5006  Interval *resInterval;
5007 
5008  /* stuff done only on the first call of the function */
5009  if (SRF_IS_FIRSTCALL())
5010  {
5011  TupleDesc tupdesc;
5012  MemoryContext oldcontext;
5013 
5014  /* create a function context for cross-call persistence */
5015  funcctx = SRF_FIRSTCALL_INIT();
5016 
5017  /*
5018  * switch to memory context appropriate for multiple function calls
5019  */
5020  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
5021 
5022  /* allocate memory for user context */
5023  pindex = (int *) palloc(sizeof(int));
5024  *pindex = 0;
5025  funcctx->user_fctx = (void *) pindex;
5026 
5027  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
5028  elog(ERROR, "return type must be a row type");
5029  funcctx->tuple_desc = tupdesc;
5030 
5031  MemoryContextSwitchTo(oldcontext);
5032  }
5033 
5034  /* stuff done on every call of the function */
5035  funcctx = SRF_PERCALL_SETUP();
5036  pindex = (int *) funcctx->user_fctx;
5037 
5038  if (zoneabbrevtbl == NULL ||
5039  *pindex >= zoneabbrevtbl->numabbrevs)
5040  SRF_RETURN_DONE(funcctx);
5041 
5042  tp = zoneabbrevtbl->abbrevs + *pindex;
5043 
5044  switch (tp->type)
5045  {
5046  case TZ:
5047  gmtoffset = tp->value;
5048  is_dst = false;
5049  break;
5050  case DTZ:
5051  gmtoffset = tp->value;
5052  is_dst = true;
5053  break;
5054  case DYNTZ:
5055  {
5056  /* Determine the current meaning of the abbrev */
5057  pg_tz *tzp;
5058  DateTimeErrorExtra extra;
5059  TimestampTz now;
5060  int isdst;
5061 
5062  tzp = FetchDynamicTimeZone(zoneabbrevtbl, tp, &extra);
5063  if (tzp == NULL)
5065  NULL, NULL, NULL);
5067  gmtoffset = -DetermineTimeZoneAbbrevOffsetTS(now,
5068  tp->token,
5069  tzp,
5070  &isdst);
5071  is_dst = (bool) isdst;
5072  break;
5073  }
5074  default:
5075  elog(ERROR, "unrecognized timezone type %d", (int) tp->type);
5076  gmtoffset = 0; /* keep compiler quiet */
5077  is_dst = false;
5078  break;
5079  }
5080 
5081  /*
5082  * Convert name to text, using upcasing conversion that is the inverse of
5083  * what ParseDateTime() uses.
5084  */
5085  strlcpy(buffer, tp->token, sizeof(buffer));
5086  for (p = (unsigned char *) buffer; *p; p++)
5087  *p = pg_toupper(*p);
5088 
5089  values[0] = CStringGetTextDatum(buffer);
5090 
5091  /* Convert offset (in seconds) to an interval; can't overflow */
5092  MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
5093  itm_in.tm_usec = (int64) gmtoffset * USECS_PER_SEC;
5094  resInterval = (Interval *) palloc(sizeof(Interval));
5095  (void) itmin2interval(&itm_in, resInterval);
5096  values[1] = IntervalPGetDatum(resInterval);
5097 
5098  values[2] = BoolGetDatum(is_dst);
5099 
5100  (*pindex)++;
5101 
5102  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
5103  result = HeapTupleGetDatum(tuple);
5104 
5105  SRF_RETURN_NEXT(funcctx, result);
5106 }
5107 
5108 /*
5109  * This set-returning function reads all the available full time zones
5110  * and returns a set of (name, abbrev, utc_offset, is_dst).
5111  */
5112 Datum
5114 {
5115  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
5116  pg_tzenum *tzenum;
5117  pg_tz *tz;
5118  Datum values[4];
5119  bool nulls[4] = {0};
5120  int tzoff;
5121  struct pg_tm tm;
5122  fsec_t fsec;
5123  const char *tzn;
5124  Interval *resInterval;
5125  struct pg_itm_in itm_in;
5126 
5127  InitMaterializedSRF(fcinfo, 0);
5128 
5129  /* initialize timezone scanning code */
5130  tzenum = pg_tzenumerate_start();
5131 
5132  /* search for another zone to display */
5133  for (;;)
5134  {
5135  tz = pg_tzenumerate_next(tzenum);
5136  if (!tz)
5137  break;
5138 
5139  /* Convert now() to local time in this zone */
5141  &tzoff, &tm, &fsec, &tzn, tz) != 0)
5142  continue; /* ignore if conversion fails */
5143 
5144  /*
5145  * IANA's rather silly "Factory" time zone used to emit ridiculously
5146  * long "abbreviations" such as "Local time zone must be set--see zic
5147  * manual page" or "Local time zone must be set--use tzsetup". While
5148  * modern versions of tzdb emit the much saner "-00", it seems some
5149  * benighted packagers are hacking the IANA data so that it continues
5150  * to produce these strings. To prevent producing a weirdly wide
5151  * abbrev column, reject ridiculously long abbreviations.
5152  */
5153  if (tzn && strlen(tzn) > 31)
5154  continue;
5155 
5157  values[1] = CStringGetTextDatum(tzn ? tzn : "");
5158 
5159  /* Convert tzoff to an interval; can't overflow */
5160  MemSet(&itm_in, 0, sizeof(struct pg_itm_in));
5161  itm_in.tm_usec = (int64) -tzoff * USECS_PER_SEC;
5162  resInterval = (Interval *) palloc(sizeof(Interval));
5163  (void) itmin2interval(&itm_in, resInterval);
5164  values[2] = IntervalPGetDatum(resInterval);
5165 
5166  values[3] = BoolGetDatum(tm.tm_isdst > 0);
5167 
5168  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
5169  }
5170 
5171  pg_tzenumerate_end(tzenum);
5172  return (Datum) 0;
5173 }
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:4537
#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:4514
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4770
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:4948
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:4038
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:4180
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:4576
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:4504
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:4083
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:3355
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:4802
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:5113
void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
Definition: datetime.c:4303
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:3820
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:3793
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:4992
TimeZoneAbbrevTable * ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs, int n)
Definition: datetime.c:4864
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4333
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:4218
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:4144
static int ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
Definition: datetime.c:3751
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:3331
static const datetkn deltatktbl[]
Definition: datetime.c:189
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:389