PostgreSQL Source Code  git master
datetime.h File Reference
#include "utils/timestamp.h"
Include dependency graph for datetime.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  datetkn
 
struct  TimeZoneAbbrevTable
 
struct  DynamicZoneAbbrev
 
struct  DateTimeErrorExtra
 

Macros

#define DAGO   "ago"
 
#define DCURRENT   "current"
 
#define EPOCH   "epoch"
 
#define INVALID   "invalid"
 
#define EARLY   "-infinity"
 
#define LATE   "infinity"
 
#define NOW   "now"
 
#define TODAY   "today"
 
#define TOMORROW   "tomorrow"
 
#define YESTERDAY   "yesterday"
 
#define ZULU   "zulu"
 
#define DMICROSEC   "usecond"
 
#define DMILLISEC   "msecond"
 
#define DSECOND   "second"
 
#define DMINUTE   "minute"
 
#define DHOUR   "hour"
 
#define DDAY   "day"
 
#define DWEEK   "week"
 
#define DMONTH   "month"
 
#define DQUARTER   "quarter"
 
#define DYEAR   "year"
 
#define DDECADE   "decade"
 
#define DCENTURY   "century"
 
#define DMILLENNIUM   "millennium"
 
#define DA_D   "ad"
 
#define DB_C   "bc"
 
#define DTIMEZONE   "timezone"
 
#define AM   0
 
#define PM   1
 
#define HR24   2
 
#define AD   0
 
#define BC   1
 
#define RESERV   0
 
#define MONTH   1
 
#define YEAR   2
 
#define DAY   3
 
#define JULIAN   4
 
#define TZ   5 /* fixed-offset timezone abbreviation */
 
#define DTZ   6 /* fixed-offset timezone abbrev, DST */
 
#define DYNTZ   7 /* dynamic timezone abbreviation */
 
#define IGNORE_DTF   8
 
#define AMPM   9
 
#define HOUR   10
 
#define MINUTE   11
 
#define SECOND   12
 
#define MILLISECOND   13
 
#define MICROSECOND   14
 
#define DOY   15
 
#define DOW   16
 
#define UNITS   17
 
#define ADBC   18
 
#define AGO   19
 
#define ABS_BEFORE   20
 
#define ABS_AFTER   21
 
#define ISODATE   22
 
#define ISOTIME   23
 
#define WEEK   24
 
#define DECADE   25
 
#define CENTURY   26
 
#define MILLENNIUM   27
 
#define DTZMOD   28 /* "DST" as a separate word */
 
#define UNKNOWN_FIELD   31
 
#define DTK_NUMBER   0
 
#define DTK_STRING   1
 
#define DTK_DATE   2
 
#define DTK_TIME   3
 
#define DTK_TZ   4
 
#define DTK_AGO   5
 
#define DTK_SPECIAL   6
 
#define DTK_EARLY   9
 
#define DTK_LATE   10
 
#define DTK_EPOCH   11
 
#define DTK_NOW   12
 
#define DTK_YESTERDAY   13
 
#define DTK_TODAY   14
 
#define DTK_TOMORROW   15
 
#define DTK_ZULU   16
 
#define DTK_DELTA   17
 
#define DTK_SECOND   18
 
#define DTK_MINUTE   19
 
#define DTK_HOUR   20
 
#define DTK_DAY   21
 
#define DTK_WEEK   22
 
#define DTK_MONTH   23
 
#define DTK_QUARTER   24
 
#define DTK_YEAR   25
 
#define DTK_DECADE   26
 
#define DTK_CENTURY   27
 
#define DTK_MILLENNIUM   28
 
#define DTK_MILLISEC   29
 
#define DTK_MICROSEC   30
 
#define DTK_JULIAN   31
 
#define DTK_DOW   32
 
#define DTK_DOY   33
 
#define DTK_TZ_HOUR   34
 
#define DTK_TZ_MINUTE   35
 
#define DTK_ISOYEAR   36
 
#define DTK_ISODOW   37
 
#define DTK_M(t)   (0x01 << (t))
 
#define DTK_ALL_SECS_M   (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))
 
#define DTK_DATE_M   (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
 
#define DTK_TIME_M   (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_ALL_SECS_M)
 
#define MAXDATELEN   128
 
#define MAXDATEFIELDS   25
 
#define TOKMAXLEN   10
 
#define FMODULO(t, q, u)
 
#define TMODULO(t, q, u)
 
#define isleap(y)   (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 
#define DTERR_BAD_FORMAT   (-1)
 
#define DTERR_FIELD_OVERFLOW   (-2)
 
#define DTERR_MD_FIELD_OVERFLOW   (-3) /* triggers hint about DateStyle */
 
#define DTERR_INTERVAL_OVERFLOW   (-4)
 
#define DTERR_TZDISP_OVERFLOW   (-5)
 
#define DTERR_BAD_TIMEZONE   (-6)
 
#define DTERR_BAD_ZONE_ABBREV   (-7)
 
#define TZNAME_FIXED_OFFSET   0
 
#define TZNAME_DYNTZ   1
 
#define TZNAME_ZONE   2
 

Typedefs

typedef struct TimeZoneAbbrevTable TimeZoneAbbrevTable
 
typedef struct DynamicZoneAbbrev DynamicZoneAbbrev
 
typedef struct DateTimeErrorExtra DateTimeErrorExtra
 

Functions

void GetCurrentDateTime (struct pg_tm *tm)
 
void GetCurrentTimeUsec (struct pg_tm *tm, fsec_t *fsec, int *tzp)
 
void j2date (int jd, int *year, int *month, int *day)
 
int date2j (int year, int month, int day)
 
int ParseDateTime (const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
 
int DecodeDateTime (char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
 
int DecodeTimezone (const char *str, int *tzp)
 
int DecodeTimeOnly (char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
 
int DecodeInterval (char **field, int *ftype, int nf, int range, int *dtype, struct pg_itm_in *itm_in)
 
int DecodeISO8601Interval (char *str, int *dtype, struct pg_itm_in *itm_in)
 
void DateTimeParseError (int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, struct Node *escontext)
 
int DetermineTimeZoneOffset (struct pg_tm *tm, pg_tz *tzp)
 
int DetermineTimeZoneAbbrevOffset (struct pg_tm *tm, const char *abbr, pg_tz *tzp)
 
int DetermineTimeZoneAbbrevOffsetTS (TimestampTz ts, const char *abbr, pg_tz *tzp, int *isdst)
 
void EncodeDateOnly (struct pg_tm *tm, int style, char *str)
 
void EncodeTimeOnly (struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str)
 
void EncodeDateTime (struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
 
void EncodeInterval (struct pg_itm *itm, int style, char *str)
 
void EncodeSpecialTimestamp (Timestamp dt, char *str)
 
int ValidateDate (int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
 
int DecodeTimezoneAbbrev (int field, const char *lowtoken, int *ftype, int *offset, pg_tz **tz, DateTimeErrorExtra *extra)
 
int DecodeSpecial (int field, const char *lowtoken, int *val)
 
int DecodeUnits (int field, const char *lowtoken, int *val)
 
int DecodeTimezoneName (const char *tzname, int *offset, pg_tz **tz)
 
pg_tzDecodeTimezoneNameToTz (const char *tzname)
 
int j2day (int date)
 
struct NodeTemporalSimplify (int32 max_precis, struct Node *node)
 
bool CheckDateTokenTables (void)
 
TimeZoneAbbrevTableConvertTimeZoneAbbrevs (struct tzEntry *abbrevs, int n)
 
void InstallTimeZoneAbbrevs (TimeZoneAbbrevTable *tbl)
 
bool AdjustTimestampForTypmod (Timestamp *time, int32 typmod, struct Node *escontext)
 

Variables

PGDLLIMPORT const char *const months []
 
PGDLLIMPORT const char *const days []
 
PGDLLIMPORT const int day_tab [2][13]
 

Macro Definition Documentation

◆ ABS_AFTER

#define ABS_AFTER   21

Definition at line 112 of file datetime.h.

◆ ABS_BEFORE

#define ABS_BEFORE   20

Definition at line 111 of file datetime.h.

◆ AD

#define AD   0

Definition at line 75 of file datetime.h.

◆ ADBC

#define ADBC   18

Definition at line 108 of file datetime.h.

◆ AGO

#define AGO   19

Definition at line 110 of file datetime.h.

◆ AM

#define AM   0

Definition at line 71 of file datetime.h.

◆ AMPM

#define AMPM   9

Definition at line 99 of file datetime.h.

◆ BC

#define BC   1

Definition at line 76 of file datetime.h.

◆ CENTURY

#define CENTURY   26

Definition at line 119 of file datetime.h.

◆ DA_D

#define DA_D   "ad"

Definition at line 60 of file datetime.h.

◆ DAGO

#define DAGO   "ago"

Definition at line 35 of file datetime.h.

◆ DAY

#define DAY   3

Definition at line 93 of file datetime.h.

◆ DB_C

#define DB_C   "bc"

Definition at line 61 of file datetime.h.

◆ DCENTURY

#define DCENTURY   "century"

Definition at line 58 of file datetime.h.

◆ DCURRENT

#define DCURRENT   "current"

Definition at line 36 of file datetime.h.

◆ DDAY

#define DDAY   "day"

Definition at line 52 of file datetime.h.

◆ DDECADE

#define DDECADE   "decade"

Definition at line 57 of file datetime.h.

◆ DECADE

#define DECADE   25

Definition at line 118 of file datetime.h.

◆ DHOUR

#define DHOUR   "hour"

Definition at line 51 of file datetime.h.

◆ DMICROSEC

#define DMICROSEC   "usecond"

Definition at line 47 of file datetime.h.

◆ DMILLENNIUM

#define DMILLENNIUM   "millennium"

Definition at line 59 of file datetime.h.

◆ DMILLISEC

#define DMILLISEC   "msecond"

Definition at line 48 of file datetime.h.

◆ DMINUTE

#define DMINUTE   "minute"

Definition at line 50 of file datetime.h.

◆ DMONTH

#define DMONTH   "month"

Definition at line 54 of file datetime.h.

◆ DOW

#define DOW   16

Definition at line 106 of file datetime.h.

◆ DOY

#define DOY   15

Definition at line 105 of file datetime.h.

◆ DQUARTER

#define DQUARTER   "quarter"

Definition at line 55 of file datetime.h.

◆ DSECOND

#define DSECOND   "second"

Definition at line 49 of file datetime.h.

◆ DTERR_BAD_FORMAT

#define DTERR_BAD_FORMAT   (-1)

Definition at line 282 of file datetime.h.

◆ DTERR_BAD_TIMEZONE

#define DTERR_BAD_TIMEZONE   (-6)

Definition at line 287 of file datetime.h.

◆ DTERR_BAD_ZONE_ABBREV

#define DTERR_BAD_ZONE_ABBREV   (-7)

Definition at line 288 of file datetime.h.

◆ DTERR_FIELD_OVERFLOW

#define DTERR_FIELD_OVERFLOW   (-2)

Definition at line 283 of file datetime.h.

◆ DTERR_INTERVAL_OVERFLOW

#define DTERR_INTERVAL_OVERFLOW   (-4)

Definition at line 285 of file datetime.h.

◆ DTERR_MD_FIELD_OVERFLOW

#define DTERR_MD_FIELD_OVERFLOW   (-3) /* triggers hint about DateStyle */

Definition at line 284 of file datetime.h.

◆ DTERR_TZDISP_OVERFLOW

#define DTERR_TZDISP_OVERFLOW   (-5)

Definition at line 286 of file datetime.h.

◆ DTIMEZONE

#define DTIMEZONE   "timezone"

Definition at line 62 of file datetime.h.

◆ DTK_AGO

#define DTK_AGO   5

Definition at line 147 of file datetime.h.

◆ DTK_ALL_SECS_M

#define DTK_ALL_SECS_M   (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))

Definition at line 190 of file datetime.h.

◆ DTK_CENTURY

#define DTK_CENTURY   27

Definition at line 169 of file datetime.h.

◆ DTK_DATE

#define DTK_DATE   2

Definition at line 144 of file datetime.h.

◆ DTK_DATE_M

#define DTK_DATE_M   (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))

Definition at line 191 of file datetime.h.

◆ DTK_DAY

#define DTK_DAY   21

Definition at line 163 of file datetime.h.

◆ DTK_DECADE

#define DTK_DECADE   26

Definition at line 168 of file datetime.h.

◆ DTK_DELTA

#define DTK_DELTA   17

Definition at line 159 of file datetime.h.

◆ DTK_DOW

#define DTK_DOW   32

Definition at line 175 of file datetime.h.

◆ DTK_DOY

#define DTK_DOY   33

Definition at line 176 of file datetime.h.

◆ DTK_EARLY

#define DTK_EARLY   9

Definition at line 150 of file datetime.h.

◆ DTK_EPOCH

#define DTK_EPOCH   11

Definition at line 152 of file datetime.h.

◆ DTK_HOUR

#define DTK_HOUR   20

Definition at line 162 of file datetime.h.

◆ DTK_ISODOW

#define DTK_ISODOW   37

Definition at line 180 of file datetime.h.

◆ DTK_ISOYEAR

#define DTK_ISOYEAR   36

Definition at line 179 of file datetime.h.

◆ DTK_JULIAN

#define DTK_JULIAN   31

Definition at line 173 of file datetime.h.

◆ DTK_LATE

#define DTK_LATE   10

Definition at line 151 of file datetime.h.

◆ DTK_M

#define DTK_M (   t)    (0x01 << (t))

Definition at line 187 of file datetime.h.

◆ DTK_MICROSEC

#define DTK_MICROSEC   30

Definition at line 172 of file datetime.h.

◆ DTK_MILLENNIUM

#define DTK_MILLENNIUM   28

Definition at line 170 of file datetime.h.

◆ DTK_MILLISEC

#define DTK_MILLISEC   29

Definition at line 171 of file datetime.h.

◆ DTK_MINUTE

#define DTK_MINUTE   19

Definition at line 161 of file datetime.h.

◆ DTK_MONTH

#define DTK_MONTH   23

Definition at line 165 of file datetime.h.

◆ DTK_NOW

#define DTK_NOW   12

Definition at line 153 of file datetime.h.

◆ DTK_NUMBER

#define DTK_NUMBER   0

Definition at line 141 of file datetime.h.

◆ DTK_QUARTER

#define DTK_QUARTER   24

Definition at line 166 of file datetime.h.

◆ DTK_SECOND

#define DTK_SECOND   18

Definition at line 160 of file datetime.h.

◆ DTK_SPECIAL

#define DTK_SPECIAL   6

Definition at line 149 of file datetime.h.

◆ DTK_STRING

#define DTK_STRING   1

Definition at line 142 of file datetime.h.

◆ DTK_TIME

#define DTK_TIME   3

Definition at line 145 of file datetime.h.

◆ DTK_TIME_M

#define DTK_TIME_M   (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_ALL_SECS_M)

Definition at line 192 of file datetime.h.

◆ DTK_TODAY

#define DTK_TODAY   14

Definition at line 155 of file datetime.h.

◆ DTK_TOMORROW

#define DTK_TOMORROW   15

Definition at line 156 of file datetime.h.

◆ DTK_TZ

#define DTK_TZ   4

Definition at line 146 of file datetime.h.

◆ DTK_TZ_HOUR

#define DTK_TZ_HOUR   34

Definition at line 177 of file datetime.h.

◆ DTK_TZ_MINUTE

#define DTK_TZ_MINUTE   35

Definition at line 178 of file datetime.h.

◆ DTK_WEEK

#define DTK_WEEK   22

Definition at line 164 of file datetime.h.

◆ DTK_YEAR

#define DTK_YEAR   25

Definition at line 167 of file datetime.h.

◆ DTK_YESTERDAY

#define DTK_YESTERDAY   13

Definition at line 154 of file datetime.h.

◆ DTK_ZULU

#define DTK_ZULU   16

Definition at line 157 of file datetime.h.

◆ DTZ

#define DTZ   6 /* fixed-offset timezone abbrev, DST */

Definition at line 96 of file datetime.h.

◆ DTZMOD

#define DTZMOD   28 /* "DST" as a separate word */

Definition at line 122 of file datetime.h.

◆ DWEEK

#define DWEEK   "week"

Definition at line 53 of file datetime.h.

◆ DYEAR

#define DYEAR   "year"

Definition at line 56 of file datetime.h.

◆ DYNTZ

#define DYNTZ   7 /* dynamic timezone abbreviation */

Definition at line 97 of file datetime.h.

◆ EARLY

#define EARLY   "-infinity"

Definition at line 39 of file datetime.h.

◆ EPOCH

#define EPOCH   "epoch"

Definition at line 37 of file datetime.h.

◆ FMODULO

#define FMODULO (   t,
  q,
 
)
Value:
do { \
(q) = (((t) < 0) ? ceil((t) / (u)) : floor((t) / (u))); \
if ((q) != 0) (t) -= rint((q) * (u)); \
} while(0)

Definition at line 237 of file datetime.h.

◆ HOUR

#define HOUR   10

Definition at line 100 of file datetime.h.

◆ HR24

#define HR24   2

Definition at line 73 of file datetime.h.

◆ IGNORE_DTF

#define IGNORE_DTF   8

Definition at line 98 of file datetime.h.

◆ INVALID

#define INVALID   "invalid"

Definition at line 38 of file datetime.h.

◆ isleap

#define isleap (   y)    (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

Definition at line 271 of file datetime.h.

◆ ISODATE

#define ISODATE   22

Definition at line 114 of file datetime.h.

◆ ISOTIME

#define ISOTIME   23

Definition at line 115 of file datetime.h.

◆ JULIAN

#define JULIAN   4

Definition at line 94 of file datetime.h.

◆ LATE

#define LATE   "infinity"

Definition at line 40 of file datetime.h.

◆ MAXDATEFIELDS

#define MAXDATEFIELDS   25

Definition at line 202 of file datetime.h.

◆ MAXDATELEN

#define MAXDATELEN   128

Definition at line 200 of file datetime.h.

◆ MICROSECOND

#define MICROSECOND   14

Definition at line 104 of file datetime.h.

◆ MILLENNIUM

#define MILLENNIUM   27

Definition at line 120 of file datetime.h.

◆ MILLISECOND

#define MILLISECOND   13

Definition at line 103 of file datetime.h.

◆ MINUTE

#define MINUTE   11

Definition at line 101 of file datetime.h.

◆ MONTH

#define MONTH   1

Definition at line 91 of file datetime.h.

◆ NOW

#define NOW   "now"

Definition at line 41 of file datetime.h.

◆ PM

#define PM   1

Definition at line 72 of file datetime.h.

◆ RESERV

#define RESERV   0

Definition at line 90 of file datetime.h.

◆ SECOND

#define SECOND   12

Definition at line 102 of file datetime.h.

◆ TMODULO

#define TMODULO (   t,
  q,
 
)
Value:
do { \
(q) = ((t) / (u)); \
if ((q) != 0) (t) -= ((q) * (u)); \
} while(0)

Definition at line 248 of file datetime.h.

◆ TODAY

#define TODAY   "today"

Definition at line 42 of file datetime.h.

◆ TOKMAXLEN

#define TOKMAXLEN   10

Definition at line 204 of file datetime.h.

◆ TOMORROW

#define TOMORROW   "tomorrow"

Definition at line 43 of file datetime.h.

◆ TZ

#define TZ   5 /* fixed-offset timezone abbreviation */

Definition at line 95 of file datetime.h.

◆ TZNAME_DYNTZ

#define TZNAME_DYNTZ   1

Definition at line 300 of file datetime.h.

◆ TZNAME_FIXED_OFFSET

#define TZNAME_FIXED_OFFSET   0

Definition at line 299 of file datetime.h.

◆ TZNAME_ZONE

#define TZNAME_ZONE   2

Definition at line 301 of file datetime.h.

◆ UNITS

#define UNITS   17

Definition at line 107 of file datetime.h.

◆ UNKNOWN_FIELD

#define UNKNOWN_FIELD   31

Definition at line 124 of file datetime.h.

◆ WEEK

#define WEEK   24

Definition at line 117 of file datetime.h.

◆ YEAR

#define YEAR   2

Definition at line 92 of file datetime.h.

◆ YESTERDAY

#define YESTERDAY   "yesterday"

Definition at line 44 of file datetime.h.

◆ ZULU

#define ZULU   "zulu"

Definition at line 45 of file datetime.h.

Typedef Documentation

◆ DateTimeErrorExtra

◆ DynamicZoneAbbrev

◆ TimeZoneAbbrevTable

Function Documentation

◆ AdjustTimestampForTypmod()

bool AdjustTimestampForTypmod ( Timestamp time,
int32  typmod,
struct Node escontext 
)

Definition at line 350 of file timestamp.c.

351 {
352  static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
353  INT64CONST(1000000),
354  INT64CONST(100000),
355  INT64CONST(10000),
356  INT64CONST(1000),
357  INT64CONST(100),
358  INT64CONST(10),
359  INT64CONST(1)
360  };
361 
362  static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
363  INT64CONST(500000),
364  INT64CONST(50000),
365  INT64CONST(5000),
366  INT64CONST(500),
367  INT64CONST(50),
368  INT64CONST(5),
369  INT64CONST(0)
370  };
371 
372  if (!TIMESTAMP_NOT_FINITE(*time)
373  && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
374  {
375  if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
376  ereturn(escontext, false,
377  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
378  errmsg("timestamp(%d) precision must be between %d and %d",
379  typmod, 0, MAX_TIMESTAMP_PRECISION)));
380 
381  if (*time >= INT64CONST(0))
382  {
383  *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
384  TimestampScales[typmod];
385  }
386  else
387  {
388  *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
389  * TimestampScales[typmod]);
390  }
391  }
392 
393  return true;
394 }
#define MAX_TIMESTAMP_PRECISION
Definition: timestamp.h:92
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:168
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereturn(context, dummy_value,...)
Definition: elog.h:276

References ereturn, errcode(), errmsg(), MAX_TIMESTAMP_PRECISION, and TIMESTAMP_NOT_FINITE.

Referenced by GetSQLCurrentTimestamp(), GetSQLLocalTimestamp(), parse_datetime(), timestamp_in(), timestamp_recv(), timestamp_scale(), timestamptz_in(), timestamptz_recv(), timestamptz_scale(), and to_timestamp().

◆ CheckDateTokenTables()

bool CheckDateTokenTables ( void  )

Definition at line 4700 of file datetime.c.

4701 {
4702  bool ok = true;
4703 
4704  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4705  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4706 
4707  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4708  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4709  return ok;
4710 }
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4668
static const datetkn datetktbl[]
Definition: datetime.c:107
static const int szdeltatktbl
Definition: datetime.c:254
static const int szdatetktbl
Definition: datetime.c:183
int date2j(int year, int month, int day)
Definition: datetime.c:288
static const datetkn deltatktbl[]
Definition: datetime.c:189
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:208
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
Assert(fmt[strlen(fmt) - 1] !='\n')

◆ ConvertTimeZoneAbbrevs()

TimeZoneAbbrevTable* ConvertTimeZoneAbbrevs ( struct tzEntry abbrevs,
int  n 
)

Definition at line 4762 of file datetime.c.

4763 {
4764  TimeZoneAbbrevTable *tbl;
4765  Size tbl_size;
4766  int i;
4767 
4768  /* Space for fixed fields and datetkn array */
4769  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4770  n * sizeof(datetkn);
4771  tbl_size = MAXALIGN(tbl_size);
4772  /* Count up space for dynamic abbreviations */
4773  for (i = 0; i < n; i++)
4774  {
4775  struct tzEntry *abbr = abbrevs + i;
4776 
4777  if (abbr->zone != NULL)
4778  {
4779  Size dsize;
4780 
4781  dsize = offsetof(DynamicZoneAbbrev, zone) +
4782  strlen(abbr->zone) + 1;
4783  tbl_size += MAXALIGN(dsize);
4784  }
4785  }
4786 
4787  /* Alloc the result ... */
4788  tbl = guc_malloc(LOG, tbl_size);
4789  if (!tbl)
4790  return NULL;
4791 
4792  /* ... and fill it in */
4793  tbl->tblsize = tbl_size;
4794  tbl->numabbrevs = n;
4795  /* in this loop, tbl_size reprises the space calculation above */
4796  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4797  n * sizeof(datetkn);
4798  tbl_size = MAXALIGN(tbl_size);
4799  for (i = 0; i < n; i++)
4800  {
4801  struct tzEntry *abbr = abbrevs + i;
4802  datetkn *dtoken = tbl->abbrevs + i;
4803 
4804  /* use strlcpy to truncate name if necessary */
4805  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4806  if (abbr->zone != NULL)
4807  {
4808  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4809  DynamicZoneAbbrev *dtza;
4810  Size dsize;
4811 
4812  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4813  dtza->tz = NULL;
4814  strcpy(dtza->zone, abbr->zone);
4815 
4816  dtoken->type = DYNTZ;
4817  /* value is offset from table start to DynamicZoneAbbrev */
4818  dtoken->value = (int32) tbl_size;
4819 
4820  dsize = offsetof(DynamicZoneAbbrev, zone) +
4821  strlen(abbr->zone) + 1;
4822  tbl_size += MAXALIGN(dsize);
4823  }
4824  else
4825  {
4826  dtoken->type = abbr->is_dst ? DTZ : TZ;
4827  dtoken->value = abbr->offset;
4828  }
4829  }
4830 
4831  /* Assert the two loops above agreed on size calculations */
4832  Assert(tbl->tblsize == tbl_size);
4833 
4834  /* Check the ordering, if testing */
4835  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4836 
4837  return tbl;
4838 }
#define MAXALIGN(LEN)
Definition: c.h:800
signed int int32
Definition: c.h:483
size_t Size
Definition: c.h:594
#define LOG
Definition: elog.h:31
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:631
#define TZ
Definition: datetime.h:95
#define DTZ
Definition: datetime.h:96
#define TOKMAXLEN
Definition: datetime.h:204
#define DYNTZ
Definition: datetime.h:97
int i
Definition: isn.c:73
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char zone[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:227
datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:219
char token[TOKMAXLEN+1]
Definition: datetime.h:209
int32 value
Definition: datetime.h:211
char type
Definition: datetime.h:210
char * zone
Definition: tzparser.h:27
int offset
Definition: tzparser.h:29
char * abbrev
Definition: tzparser.h:26
bool is_dst
Definition: tzparser.h:30
Definition: zic.c:94

References tzEntry::abbrev, TimeZoneAbbrevTable::abbrevs, Assert(), CheckDateTokenTable(), DTZ, DYNTZ, guc_malloc(), i, tzEntry::is_dst, LOG, MAXALIGN, TimeZoneAbbrevTable::numabbrevs, tzEntry::offset, strlcpy(), TimeZoneAbbrevTable::tblsize, datetkn::token, TOKMAXLEN, datetkn::type, TZ, DynamicZoneAbbrev::tz, datetkn::value, DynamicZoneAbbrev::zone, and tzEntry::zone.

Referenced by load_tzoffsets().

◆ date2j()

int date2j ( int  year,
int  month,
int  day 
)

Definition at line 288 of file datetime.c.

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() */

◆ DateTimeParseError()

void DateTimeParseError ( int  dterr,
DateTimeErrorExtra extra,
const char *  str,
const char *  datatype,
struct Node escontext 
)

Definition at line 3981 of file datetime.c.

3984 {
3985  switch (dterr)
3986  {
3987  case DTERR_FIELD_OVERFLOW:
3988  errsave(escontext,
3989  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3990  errmsg("date/time field value out of range: \"%s\"",
3991  str)));
3992  break;
3994  /* <nanny>same as above, but add hint about DateStyle</nanny> */
3995  errsave(escontext,
3996  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3997  errmsg("date/time field value out of range: \"%s\"",
3998  str),
3999  errhint("Perhaps you need a different \"datestyle\" setting.")));
4000  break;
4002  errsave(escontext,
4003  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
4004  errmsg("interval field value out of range: \"%s\"",
4005  str)));
4006  break;
4007  case DTERR_TZDISP_OVERFLOW:
4008  errsave(escontext,
4009  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
4010  errmsg("time zone displacement out of range: \"%s\"",
4011  str)));
4012  break;
4013  case DTERR_BAD_TIMEZONE:
4014  errsave(escontext,
4015  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4016  errmsg("time zone \"%s\" not recognized",
4017  extra->dtee_timezone)));
4018  break;
4019  case DTERR_BAD_ZONE_ABBREV:
4020  errsave(escontext,
4021  (errcode(ERRCODE_CONFIG_FILE_ERROR),
4022  errmsg("time zone \"%s\" not recognized",
4023  extra->dtee_timezone),
4024  errdetail("This time zone name appears in the configuration file for time zone abbreviation \"%s\".",
4025  extra->dtee_abbrev)));
4026  break;
4027  case DTERR_BAD_FORMAT:
4028  default:
4029  errsave(escontext,
4030  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4031  errmsg("invalid input syntax for type %s: \"%s\"",
4032  datatype, str)));
4033  break;
4034  }
4035 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
#define errsave(context,...)
Definition: elog.h:260
#define DTERR_BAD_ZONE_ABBREV
Definition: datetime.h:288
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:285
#define DTERR_BAD_TIMEZONE
Definition: datetime.h:287
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DTERR_MD_FIELD_OVERFLOW
Definition: datetime.h:284
const char * dtee_timezone
Definition: datetime.h:293
const char * dtee_abbrev
Definition: datetime.h:295

References DateTimeErrorExtra::dtee_abbrev, DateTimeErrorExtra::dtee_timezone, DTERR_BAD_FORMAT, DTERR_BAD_TIMEZONE, DTERR_BAD_ZONE_ABBREV, DTERR_FIELD_OVERFLOW, DTERR_INTERVAL_OVERFLOW, DTERR_MD_FIELD_OVERFLOW, DTERR_TZDISP_OVERFLOW, errcode(), errdetail(), errhint(), errmsg(), errsave, and generate_unaccent_rules::str.

Referenced by date_in(), DecodeTimezoneName(), do_to_timestamp(), interval_in(), parse_datetime(), pg_timezone_abbrevs(), time_in(), timestamp_in(), timestamptz_in(), timetz_in(), and to_timestamp().

◆ DecodeDateTime()

int DecodeDateTime ( char **  field,
int *  ftype,
int  nf,
int *  dtype,
struct pg_tm tm,
fsec_t fsec,
int *  tzp,
DateTimeErrorExtra extra 
)

Definition at line 980 of file datetime.c.

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 }
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits, struct pg_tm *tm)
Definition: datetime.c:2389
static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2903
static int ParseFraction(char *cp, double *frac)
Definition: datetime.c:682
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
int DecodeTimezoneAbbrev(int field, const char *lowtoken, int *ftype, int *offset, pg_tz **tz, DateTimeErrorExtra *extra)
Definition: datetime.c:3082
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2663
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
int DecodeTimezone(const char *str, int *tzp)
Definition: datetime.c:2998
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:389
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1748
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1803
#define USECS_PER_DAY
Definition: timestamp.h:130
#define HOURS_PER_DAY
Definition: timestamp.h:117
bool time_overflows(int hour, int min, int sec, fsec_t fsec)
Definition: date.c:1426
#define ERROR
Definition: elog.h:39
#define DTK_TOMORROW
Definition: datetime.h:156
#define DTK_EPOCH
Definition: datetime.h:152
#define DTK_SPECIAL
Definition: datetime.h:149
#define AMPM
Definition: datetime.h:99
#define DTK_TIME
Definition: datetime.h:145
#define UNKNOWN_FIELD
Definition: datetime.h:124
#define PM
Definition: datetime.h:72
#define DTK_NUMBER
Definition: datetime.h:141
#define DTK_STRING
Definition: datetime.h:142
#define DTK_JULIAN
Definition: datetime.h:173
#define MONTH
Definition: datetime.h:91
#define IGNORE_DTF
Definition: datetime.h:98
#define DTK_TIME_M
Definition: datetime.h:192
#define DTK_M(t)
Definition: datetime.h:187
#define DAY
Definition: datetime.h:93
#define ADBC
Definition: datetime.h:108
#define DTK_LATE
Definition: datetime.h:151
#define DTK_DATE
Definition: datetime.h:144
#define RESERV
Definition: datetime.h:90
#define BC
Definition: datetime.h:76
#define HR24
Definition: datetime.h:73
#define DTK_DATE_M
Definition: datetime.h:191
#define DTK_EARLY
Definition: datetime.h:150
#define DTZMOD
Definition: datetime.h:122
#define DTK_TZ
Definition: datetime.h:146
#define DOW
Definition: datetime.h:106
#define ISOTIME
Definition: datetime.h:115
#define AM
Definition: datetime.h:71
#define DTK_YESTERDAY
Definition: datetime.h:154
#define DTK_ZULU
Definition: datetime.h:157
#define UNITS
Definition: datetime.h:107
#define DTK_TODAY
Definition: datetime.h:155
#define DTK_NOW
Definition: datetime.h:153
long val
Definition: informix.c:664
static struct @148 value
static struct pg_tm tm
Definition: localtime.c:104
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
pg_tz * pg_tzset(const char *tzname)
Definition: pgtz.c:234
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:51
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_wday
Definition: pgtime.h:42
int tm_sec
Definition: pgtime.h:36
int tm_isdst
Definition: pgtime.h:44
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:66
#define INTERVAL_FULL_RANGE
Definition: timestamp.h:76
const char * type

References ADBC, AM, AMPM, BC, date2j(), DAY, DecodeDate(), DecodeNumber(), DecodeNumberField(), DecodeSpecial(), DecodeTime(), DecodeTimezone(), DecodeTimezoneAbbrev(), DetermineTimeZoneAbbrevOffset(), DetermineTimeZoneOffset(), DOW, dt2time(), DateTimeErrorExtra::dtee_timezone, DTERR_BAD_FORMAT, DTERR_BAD_TIMEZONE, DTERR_FIELD_OVERFLOW, DTK_DATE, DTK_DATE_M, DTK_EARLY, DTK_EPOCH, DTK_JULIAN, DTK_LATE, DTK_M, DTK_NOW, DTK_NUMBER, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TIME_M, DTK_TODAY, DTK_TOMORROW, DTK_TZ, DTK_YESTERDAY, DTK_ZULU, DTZ, DTZMOD, DYNTZ, elog(), ERROR, GetCurrentDateTime(), GetCurrentTimeUsec(), HOURS_PER_DAY, HR24, i, IGNORE_DTF, INTERVAL_FULL_RANGE, ISOTIME, j2date(), MONTH, ParseFraction(), pg_tzset(), PM, RESERV, session_timezone, strtoint(), time_overflows(), tm, pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_wday, pg_tm::tm_year, type, TZ, UNITS, UNKNOWN_FIELD, USECS_PER_DAY, val, ValidateDate(), and value.

Referenced by check_recovery_target_time(), date_in(), pg_logdir_ls_internal(), PGTYPESdate_from_asc(), PGTYPEStimestamp_from_asc(), timestamp_in(), and timestamptz_in().

◆ DecodeInterval()

int DecodeInterval ( char **  field,
int *  ftype,
int  nf,
int  range,
int *  dtype,
struct pg_itm_in itm_in 
)

Definition at line 3276 of file datetime.c.

3278 {
3279  bool force_negative = false;
3280  bool is_before = false;
3281  bool parsing_unit_val = false;
3282  char *cp;
3283  int fmask = 0,
3284  tmask,
3285  type,
3286  uval;
3287  int i;
3288  int dterr;
3289  int64 val;
3290  double fval;
3291 
3292  *dtype = DTK_DELTA;
3293  type = IGNORE_DTF;
3294  ClearPgItmIn(itm_in);
3295 
3296  /*----------
3297  * The SQL standard defines the interval literal
3298  * '-1 1:00:00'
3299  * to mean "negative 1 days and negative 1 hours", while Postgres
3300  * traditionally treats this as meaning "negative 1 days and positive
3301  * 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
3302  * to all fields if there are no other explicit signs.
3303  *
3304  * We leave the signs alone if there are additional explicit signs.
3305  * This protects us against misinterpreting postgres-style dump output,
3306  * since the postgres-style output code has always put an explicit sign on
3307  * all fields following a negative field. But note that SQL-spec output
3308  * is ambiguous and can be misinterpreted on load! (So it's best practice
3309  * to dump in postgres style, not SQL style.)
3310  *----------
3311  */
3312  if (IntervalStyle == INTSTYLE_SQL_STANDARD && nf > 0 && *field[0] == '-')
3313  {
3314  force_negative = true;
3315  /* Check for additional explicit signs */
3316  for (i = 1; i < nf; i++)
3317  {
3318  if (*field[i] == '-' || *field[i] == '+')
3319  {
3320  force_negative = false;
3321  break;
3322  }
3323  }
3324  }
3325 
3326  /* read through list backwards to pick up units before values */
3327  for (i = nf - 1; i >= 0; i--)
3328  {
3329  switch (ftype[i])
3330  {
3331  case DTK_TIME:
3332  dterr = DecodeTimeForInterval(field[i], fmask, range,
3333  &tmask, itm_in);
3334  if (dterr)
3335  return dterr;
3336  if (force_negative &&
3337  itm_in->tm_usec > 0)
3338  itm_in->tm_usec = -itm_in->tm_usec;
3339  type = DTK_DAY;
3340  parsing_unit_val = false;
3341  break;
3342 
3343  case DTK_TZ:
3344 
3345  /*
3346  * Timezone means a token with a leading sign character and at
3347  * least one digit; there could be ':', '.', '-' embedded in
3348  * it as well.
3349  */
3350  Assert(*field[i] == '-' || *field[i] == '+');
3351 
3352  /*
3353  * Check for signed hh:mm or hh:mm:ss. If so, process exactly
3354  * like DTK_TIME case above, plus handling the sign.
3355  */
3356  if (strchr(field[i] + 1, ':') != NULL &&
3357  DecodeTimeForInterval(field[i] + 1, fmask, range,
3358  &tmask, itm_in) == 0)
3359  {
3360  if (*field[i] == '-')
3361  {
3362  /* flip the sign on time field */
3363  if (itm_in->tm_usec == PG_INT64_MIN)
3364  return DTERR_FIELD_OVERFLOW;
3365  itm_in->tm_usec = -itm_in->tm_usec;
3366  }
3367 
3368  if (force_negative &&
3369  itm_in->tm_usec > 0)
3370  itm_in->tm_usec = -itm_in->tm_usec;
3371 
3372  /*
3373  * Set the next type to be a day, if units are not
3374  * specified. This handles the case of '1 +02:03' since we
3375  * are reading right to left.
3376  */
3377  type = DTK_DAY;
3378  parsing_unit_val = false;
3379  break;
3380  }
3381 
3382  /*
3383  * Otherwise, fall through to DTK_NUMBER case, which can
3384  * handle signed float numbers and signed year-month values.
3385  */
3386 
3387  /* FALLTHROUGH */
3388 
3389  case DTK_DATE:
3390  case DTK_NUMBER:
3391  if (type == IGNORE_DTF)
3392  {
3393  /* use typmod to decide what rightmost field is */
3394  switch (range)
3395  {
3396  case INTERVAL_MASK(YEAR):
3397  type = DTK_YEAR;
3398  break;
3399  case INTERVAL_MASK(MONTH):
3401  type = DTK_MONTH;
3402  break;
3403  case INTERVAL_MASK(DAY):
3404  type = DTK_DAY;
3405  break;
3406  case INTERVAL_MASK(HOUR):
3408  type = DTK_HOUR;
3409  break;
3410  case INTERVAL_MASK(MINUTE):
3413  type = DTK_MINUTE;
3414  break;
3415  case INTERVAL_MASK(SECOND):
3419  type = DTK_SECOND;
3420  break;
3421  default:
3422  type = DTK_SECOND;
3423  break;
3424  }
3425  }
3426 
3427  errno = 0;
3428  val = strtoi64(field[i], &cp, 10);
3429  if (errno == ERANGE)
3430  return DTERR_FIELD_OVERFLOW;
3431 
3432  if (*cp == '-')
3433  {
3434  /* SQL "years-months" syntax */
3435  int val2;
3436 
3437  val2 = strtoint(cp + 1, &cp, 10);
3438  if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
3439  return DTERR_FIELD_OVERFLOW;
3440  if (*cp != '\0')
3441  return DTERR_BAD_FORMAT;
3442  type = DTK_MONTH;
3443  if (*field[i] == '-')
3444  val2 = -val2;
3446  return DTERR_FIELD_OVERFLOW;
3447  if (pg_add_s64_overflow(val, val2, &val))
3448  return DTERR_FIELD_OVERFLOW;
3449  fval = 0;
3450  }
3451  else if (*cp == '.')
3452  {
3453  dterr = ParseFraction(cp, &fval);
3454  if (dterr)
3455  return dterr;
3456  if (*field[i] == '-')
3457  fval = -fval;
3458  }
3459  else if (*cp == '\0')
3460  fval = 0;
3461  else
3462  return DTERR_BAD_FORMAT;
3463 
3464  tmask = 0; /* DTK_M(type); */
3465 
3466  if (force_negative)
3467  {
3468  /* val and fval should be of same sign, but test anyway */
3469  if (val > 0)
3470  val = -val;
3471  if (fval > 0)
3472  fval = -fval;
3473  }
3474 
3475  switch (type)
3476  {
3477  case DTK_MICROSEC:
3478  if (!AdjustMicroseconds(val, fval, 1, itm_in))
3479  return DTERR_FIELD_OVERFLOW;
3480  tmask = DTK_M(MICROSECOND);
3481  break;
3482 
3483  case DTK_MILLISEC:
3484  if (!AdjustMicroseconds(val, fval, 1000, itm_in))
3485  return DTERR_FIELD_OVERFLOW;
3486  tmask = DTK_M(MILLISECOND);
3487  break;
3488 
3489  case DTK_SECOND:
3490  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3491  return DTERR_FIELD_OVERFLOW;
3492 
3493  /*
3494  * If any subseconds were specified, consider this
3495  * microsecond and millisecond input as well.
3496  */
3497  if (fval == 0)
3498  tmask = DTK_M(SECOND);
3499  else
3500  tmask = DTK_ALL_SECS_M;
3501  break;
3502 
3503  case DTK_MINUTE:
3504  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3505  return DTERR_FIELD_OVERFLOW;
3506  tmask = DTK_M(MINUTE);
3507  break;
3508 
3509  case DTK_HOUR:
3510  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3511  return DTERR_FIELD_OVERFLOW;
3512  tmask = DTK_M(HOUR);
3513  type = DTK_DAY; /* set for next field */
3514  break;
3515 
3516  case DTK_DAY:
3517  if (!AdjustDays(val, 1, itm_in) ||
3518  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3519  return DTERR_FIELD_OVERFLOW;
3520  tmask = DTK_M(DAY);
3521  break;
3522 
3523  case DTK_WEEK:
3524  if (!AdjustDays(val, 7, itm_in) ||
3525  !AdjustFractDays(fval, 7, itm_in))
3526  return DTERR_FIELD_OVERFLOW;
3527  tmask = DTK_M(WEEK);
3528  break;
3529 
3530  case DTK_MONTH:
3531  if (!AdjustMonths(val, itm_in) ||
3532  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3533  return DTERR_FIELD_OVERFLOW;
3534  tmask = DTK_M(MONTH);
3535  break;
3536 
3537  case DTK_YEAR:
3538  if (!AdjustYears(val, 1, itm_in) ||
3539  !AdjustFractYears(fval, 1, itm_in))
3540  return DTERR_FIELD_OVERFLOW;
3541  tmask = DTK_M(YEAR);
3542  break;
3543 
3544  case DTK_DECADE:
3545  if (!AdjustYears(val, 10, itm_in) ||
3546  !AdjustFractYears(fval, 10, itm_in))
3547  return DTERR_FIELD_OVERFLOW;
3548  tmask = DTK_M(DECADE);
3549  break;
3550 
3551  case DTK_CENTURY:
3552  if (!AdjustYears(val, 100, itm_in) ||
3553  !AdjustFractYears(fval, 100, itm_in))
3554  return DTERR_FIELD_OVERFLOW;
3555  tmask = DTK_M(CENTURY);
3556  break;
3557 
3558  case DTK_MILLENNIUM:
3559  if (!AdjustYears(val, 1000, itm_in) ||
3560  !AdjustFractYears(fval, 1000, itm_in))
3561  return DTERR_FIELD_OVERFLOW;
3562  tmask = DTK_M(MILLENNIUM);
3563  break;
3564 
3565  default:
3566  return DTERR_BAD_FORMAT;
3567  }
3568  parsing_unit_val = false;
3569  break;
3570 
3571  case DTK_STRING:
3572  case DTK_SPECIAL:
3573  /* reject consecutive unhandled units */
3574  if (parsing_unit_val)
3575  return DTERR_BAD_FORMAT;
3576  type = DecodeUnits(i, field[i], &uval);
3577  if (type == IGNORE_DTF)
3578  continue;
3579 
3580  tmask = 0; /* DTK_M(type); */
3581  switch (type)
3582  {
3583  case UNITS:
3584  type = uval;
3585  parsing_unit_val = true;
3586  break;
3587 
3588  case AGO:
3589 
3590  /*
3591  * "ago" is only allowed to appear at the end of the
3592  * interval.
3593  */
3594  if (i != nf - 1)
3595  return DTERR_BAD_FORMAT;
3596  is_before = true;
3597  type = uval;
3598  break;
3599 
3600  default:
3601  return DTERR_BAD_FORMAT;
3602  }
3603  break;
3604 
3605  default:
3606  return DTERR_BAD_FORMAT;
3607  }
3608 
3609  if (tmask & fmask)
3610  return DTERR_BAD_FORMAT;
3611  fmask |= tmask;
3612  }
3613 
3614  /* ensure that at least one time field has been found */
3615  if (fmask == 0)
3616  return DTERR_BAD_FORMAT;
3617 
3618  /* reject if unit appeared and was never handled */
3619  if (parsing_unit_val)
3620  return DTERR_BAD_FORMAT;
3621 
3622  /* finally, AGO negates everything */
3623  if (is_before)
3624  {
3625  if (itm_in->tm_usec == PG_INT64_MIN ||
3626  itm_in->tm_mday == INT_MIN ||
3627  itm_in->tm_mon == INT_MIN ||
3628  itm_in->tm_year == INT_MIN)
3629  return DTERR_FIELD_OVERFLOW;
3630 
3631  itm_in->tm_usec = -itm_in->tm_usec;
3632  itm_in->tm_mday = -itm_in->tm_mday;
3633  itm_in->tm_mon = -itm_in->tm_mon;
3634  itm_in->tm_year = -itm_in->tm_year;
3635  }
3636 
3637  return 0;
3638 }
int DecodeUnits(int field, const char *lowtoken, int *val)
Definition: datetime.c:3936
static bool AdjustDays(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:635
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 DecodeTimeForInterval(char *str, int fmask, int range, int *tmask, struct pg_itm_in *itm_in)
Definition: datetime.c:2692
static bool AdjustFractMicroseconds(double frac, int64 scale, struct pg_itm_in *itm_in)
Definition: datetime.c:539
static bool AdjustYears(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:663
static bool AdjustMonths(int64 val, struct pg_itm_in *itm_in)
Definition: datetime.c:651
static bool AdjustFractDays(double frac, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:571
static void ClearPgItmIn(struct pg_itm_in *itm_in)
Definition: datetime.c:3255
#define strtoi64(str, endptr, base)
Definition: c.h:1307
#define PG_INT64_MIN
Definition: c.h:580
#define USECS_PER_HOUR
Definition: timestamp.h:131
#define MONTHS_PER_YEAR
Definition: timestamp.h:108
#define USECS_PER_SEC
Definition: timestamp.h:133
#define USECS_PER_MINUTE
Definition: timestamp.h:132
#define DAYS_PER_MONTH
Definition: timestamp.h:116
int IntervalStyle
Definition: globals.c:121
#define MILLENNIUM
Definition: datetime.h:120
#define DTK_DECADE
Definition: datetime.h:168
#define DTK_SECOND
Definition: datetime.h:160
#define DTK_DELTA
Definition: datetime.h:159
#define MICROSECOND
Definition: datetime.h:104
#define HOUR
Definition: datetime.h:100
#define WEEK
Definition: datetime.h:117
#define DECADE
Definition: datetime.h:118
#define YEAR
Definition: datetime.h:92
#define DTK_CENTURY
Definition: datetime.h:169
#define MILLISECOND
Definition: datetime.h:103
#define DTK_DAY
Definition: datetime.h:163
#define CENTURY
Definition: datetime.h:119
#define DTK_MILLENNIUM
Definition: datetime.h:170
#define SECOND
Definition: datetime.h:102
#define DTK_ALL_SECS_M
Definition: datetime.h:190
#define DTK_HOUR
Definition: datetime.h:162
#define DTK_WEEK
Definition: datetime.h:164
#define MINUTE
Definition: datetime.h:101
#define DTK_MICROSEC
Definition: datetime.h:172
#define DTK_YEAR
Definition: datetime.h:167
#define AGO
Definition: datetime.h:110
#define DTK_MILLISEC
Definition: datetime.h:171
#define DTK_MONTH
Definition: datetime.h:165
#define DTK_MINUTE
Definition: datetime.h:161
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:161
#define INTSTYLE_SQL_STANDARD
Definition: miscadmin.h:252
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
int tm_mon
Definition: timestamp.h:86
int tm_year
Definition: timestamp.h:87
int tm_mday
Definition: timestamp.h:85
int64 tm_usec
Definition: timestamp.h:84
#define INTERVAL_MASK(b)
Definition: timestamp.h:73

References AdjustDays(), AdjustFractDays(), AdjustFractMicroseconds(), AdjustFractYears(), AdjustMicroseconds(), AdjustMonths(), AdjustYears(), AGO, Assert(), CENTURY, ClearPgItmIn(), DAY, DAYS_PER_MONTH, DECADE, DecodeTimeForInterval(), DecodeUnits(), DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTK_ALL_SECS_M, DTK_CENTURY, DTK_DATE, DTK_DAY, DTK_DECADE, DTK_DELTA, DTK_HOUR, DTK_M, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_NUMBER, DTK_SECOND, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TZ, DTK_WEEK, DTK_YEAR, HOUR, i, IGNORE_DTF, INTERVAL_MASK, IntervalStyle, INTSTYLE_SQL_STANDARD, MICROSECOND, MILLENNIUM, MILLISECOND, MINUTE, MONTH, MONTHS_PER_YEAR, ParseFraction(), pg_add_s64_overflow(), PG_INT64_MIN, pg_mul_s64_overflow(), range(), SECOND, strtoi64, strtoint(), pg_itm_in::tm_mday, pg_itm_in::tm_mon, pg_itm_in::tm_usec, pg_itm_in::tm_year, type, UNITS, USECS_PER_DAY, USECS_PER_HOUR, USECS_PER_MINUTE, USECS_PER_SEC, val, WEEK, and YEAR.

Referenced by interval_in().

◆ DecodeISO8601Interval()

int DecodeISO8601Interval ( char *  str,
int *  dtype,
struct pg_itm_in itm_in 
)

Definition at line 3718 of file datetime.c.

3720 {
3721  bool datepart = true;
3722  bool havefield = false;
3723 
3724  *dtype = DTK_DELTA;
3725  ClearPgItmIn(itm_in);
3726 
3727  if (strlen(str) < 2 || str[0] != 'P')
3728  return DTERR_BAD_FORMAT;
3729 
3730  str++;
3731  while (*str)
3732  {
3733  char *fieldstart;
3734  int64 val;
3735  double fval;
3736  char unit;
3737  int dterr;
3738 
3739  if (*str == 'T') /* T indicates the beginning of the time part */
3740  {
3741  datepart = false;
3742  havefield = false;
3743  str++;
3744  continue;
3745  }
3746 
3747  fieldstart = str;
3748  dterr = ParseISO8601Number(str, &str, &val, &fval);
3749  if (dterr)
3750  return dterr;
3751 
3752  /*
3753  * Note: we could step off the end of the string here. Code below
3754  * *must* exit the loop if unit == '\0'.
3755  */
3756  unit = *str++;
3757 
3758  if (datepart)
3759  {
3760  switch (unit) /* before T: Y M W D */
3761  {
3762  case 'Y':
3763  if (!AdjustYears(val, 1, itm_in) ||
3764  !AdjustFractYears(fval, 1, itm_in))
3765  return DTERR_FIELD_OVERFLOW;
3766  break;
3767  case 'M':
3768  if (!AdjustMonths(val, itm_in) ||
3769  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3770  return DTERR_FIELD_OVERFLOW;
3771  break;
3772  case 'W':
3773  if (!AdjustDays(val, 7, itm_in) ||
3774  !AdjustFractDays(fval, 7, itm_in))
3775  return DTERR_FIELD_OVERFLOW;
3776  break;
3777  case 'D':
3778  if (!AdjustDays(val, 1, itm_in) ||
3779  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3780  return DTERR_FIELD_OVERFLOW;
3781  break;
3782  case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
3783  case '\0':
3784  if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
3785  {
3786  if (!AdjustYears(val / 10000, 1, itm_in) ||
3787  !AdjustMonths((val / 100) % 100, itm_in) ||
3788  !AdjustDays(val % 100, 1, itm_in) ||
3789  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3790  return DTERR_FIELD_OVERFLOW;
3791  if (unit == '\0')
3792  return 0;
3793  datepart = false;
3794  havefield = false;
3795  continue;
3796  }
3797  /* Else fall through to extended alternative format */
3798  /* FALLTHROUGH */
3799  case '-': /* ISO 8601 4.4.3.3 Alternative Format,
3800  * Extended */
3801  if (havefield)
3802  return DTERR_BAD_FORMAT;
3803 
3804  if (!AdjustYears(val, 1, itm_in) ||
3805  !AdjustFractYears(fval, 1, itm_in))
3806  return DTERR_FIELD_OVERFLOW;
3807  if (unit == '\0')
3808  return 0;
3809  if (unit == 'T')
3810  {
3811  datepart = false;
3812  havefield = false;
3813  continue;
3814  }
3815 
3816  dterr = ParseISO8601Number(str, &str, &val, &fval);
3817  if (dterr)
3818  return dterr;
3819  if (!AdjustMonths(val, itm_in) ||
3820  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3821  return DTERR_FIELD_OVERFLOW;
3822  if (*str == '\0')
3823  return 0;
3824  if (*str == 'T')
3825  {
3826  datepart = false;
3827  havefield = false;
3828  continue;
3829  }
3830  if (*str != '-')
3831  return DTERR_BAD_FORMAT;
3832  str++;
3833 
3834  dterr = ParseISO8601Number(str, &str, &val, &fval);
3835  if (dterr)
3836  return dterr;
3837  if (!AdjustDays(val, 1, itm_in) ||
3838  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3839  return DTERR_FIELD_OVERFLOW;
3840  if (*str == '\0')
3841  return 0;
3842  if (*str == 'T')
3843  {
3844  datepart = false;
3845  havefield = false;
3846  continue;
3847  }
3848  return DTERR_BAD_FORMAT;
3849  default:
3850  /* not a valid date unit suffix */
3851  return DTERR_BAD_FORMAT;
3852  }
3853  }
3854  else
3855  {
3856  switch (unit) /* after T: H M S */
3857  {
3858  case 'H':
3859  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3860  return DTERR_FIELD_OVERFLOW;
3861  break;
3862  case 'M':
3863  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3864  return DTERR_FIELD_OVERFLOW;
3865  break;
3866  case 'S':
3867  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3868  return DTERR_FIELD_OVERFLOW;
3869  break;
3870  case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
3871  if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
3872  {
3873  if (!AdjustMicroseconds(val / 10000, 0, USECS_PER_HOUR, itm_in) ||
3874  !AdjustMicroseconds((val / 100) % 100, 0, USECS_PER_MINUTE, itm_in) ||
3875  !AdjustMicroseconds(val % 100, 0, USECS_PER_SEC, itm_in) ||
3876  !AdjustFractMicroseconds(fval, 1, itm_in))
3877  return DTERR_FIELD_OVERFLOW;
3878  return 0;
3879  }
3880  /* Else fall through to extended alternative format */
3881  /* FALLTHROUGH */
3882  case ':': /* ISO 8601 4.4.3.3 Alternative Format,
3883  * Extended */
3884  if (havefield)
3885  return DTERR_BAD_FORMAT;
3886 
3887  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3888  return DTERR_FIELD_OVERFLOW;
3889  if (unit == '\0')
3890  return 0;
3891 
3892  dterr = ParseISO8601Number(str, &str, &val, &fval);
3893  if (dterr)
3894  return dterr;
3895  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3896  return DTERR_FIELD_OVERFLOW;
3897  if (*str == '\0')
3898  return 0;
3899  if (*str != ':')
3900  return DTERR_BAD_FORMAT;
3901  str++;
3902 
3903  dterr = ParseISO8601Number(str, &str, &val, &fval);
3904  if (dterr)
3905  return dterr;
3906  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3907  return DTERR_FIELD_OVERFLOW;
3908  if (*str == '\0')
3909  return 0;
3910  return DTERR_BAD_FORMAT;
3911 
3912  default:
3913  /* not a valid time unit suffix */
3914  return DTERR_BAD_FORMAT;
3915  }
3916  }
3917 
3918  havefield = true;
3919  }
3920 
3921  return 0;
3922 }
static int ISO8601IntegerWidth(char *fieldstart)
Definition: datetime.c:3691
static int ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
Definition: datetime.c:3649

References AdjustDays(), AdjustFractDays(), AdjustFractMicroseconds(), AdjustFractYears(), AdjustMicroseconds(), AdjustMonths(), AdjustYears(), ClearPgItmIn(), DAYS_PER_MONTH, DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTK_DELTA, ISO8601IntegerWidth(), ParseISO8601Number(), generate_unaccent_rules::str, USECS_PER_DAY, USECS_PER_HOUR, USECS_PER_MINUTE, USECS_PER_SEC, and val.

Referenced by interval_in().

◆ DecodeSpecial()

int DecodeSpecial ( int  field,
const char *  lowtoken,
int *  val 
)

Definition at line 3139 of file datetime.c.

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 }
static const datetkn * datecache[MAXDATEFIELDS]
Definition: datetime.c:260
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:4042

References datebsearch(), datecache, datetktbl, szdatetktbl, datetkn::token, TOKMAXLEN, type, datetkn::type, UNKNOWN_FIELD, val, and datetkn::value.

Referenced by DecodeDate(), DecodeDateTime(), DecodeTimeOnly(), extract_date(), interval_part_common(), time_part_common(), timestamp_part_common(), timestamptz_part_common(), and timetz_part_common().

◆ DecodeTimeOnly()

int DecodeTimeOnly ( char **  field,
int *  ftype,
int  nf,
int *  dtype,
struct pg_tm tm,
fsec_t fsec,
int *  tzp,
DateTimeErrorExtra extra 
)

Definition at line 1866 of file datetime.c.

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 }
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c:1851

References ADBC, AM, AMPM, BC, DecodeDate(), DecodeNumber(), DecodeNumberField(), DecodeSpecial(), DecodeTime(), DecodeTimezone(), DecodeTimezoneAbbrev(), DetermineTimeZoneAbbrevOffset(), DetermineTimeZoneOffset(), dt2time(), DateTimeErrorExtra::dtee_timezone, DTERR_BAD_FORMAT, DTERR_BAD_TIMEZONE, DTERR_FIELD_OVERFLOW, DTK_DATE, DTK_DATE_M, DTK_JULIAN, DTK_M, DTK_NOW, DTK_NUMBER, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TIME_M, DTK_TZ, DTK_ZULU, DTZ, DTZMOD, DYNTZ, GetCurrentDateTime(), GetCurrentTimeUsec(), HOURS_PER_DAY, HR24, i, IGNORE_DTF, INTERVAL_FULL_RANGE, ISOTIME, j2date(), ParseFraction(), pg_get_timezone_offset(), pg_tzset(), PM, RESERV, session_timezone, strtoint(), time_overflows(), tm, pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, type, TZ, UNITS, UNKNOWN_FIELD, USECS_PER_DAY, val, ValidateDate(), and value.

Referenced by time_in(), and timetz_in().

◆ DecodeTimezone()

int DecodeTimezone ( const char *  str,
int *  tzp 
)

Definition at line 2998 of file datetime.c.

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 }
#define MAX_TZDISP_HOUR
Definition: timestamp.h:142
#define MINS_PER_HOUR
Definition: timestamp.h:128
#define SECS_PER_MINUTE
Definition: timestamp.h:127

References DTERR_BAD_FORMAT, DTERR_TZDISP_OVERFLOW, MAX_TZDISP_HOUR, MINS_PER_HOUR, SECS_PER_MINUTE, generate_unaccent_rules::str, and strtoint().

Referenced by DecodeDateTime(), DecodeTimeOnly(), parse_datetime(), parse_sane_timezone(), and to_timestamp().

◆ DecodeTimezoneAbbrev()

int DecodeTimezoneAbbrev ( int  field,
const char *  lowtoken,
int *  ftype,
int *  offset,
pg_tz **  tz,
DateTimeErrorExtra extra 
)

Definition at line 3082 of file datetime.c.

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 }
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:264
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:256
static pg_tz * FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp, DateTimeErrorExtra *extra)
Definition: datetime.c:4859

References abbrevcache, TimeZoneAbbrevTable::abbrevs, datebsearch(), DTERR_BAD_ZONE_ABBREV, DYNTZ, FetchDynamicTimeZone(), TimeZoneAbbrevTable::numabbrevs, datetkn::token, TOKMAXLEN, datetkn::type, UNKNOWN_FIELD, datetkn::value, and zoneabbrevtbl.

Referenced by DecodeDateTime(), DecodeTimeOnly(), and DecodeTimezoneName().

◆ DecodeTimezoneName()

int DecodeTimezoneName ( const char *  tzname,
int *  offset,
pg_tz **  tz 
)

Definition at line 3181 of file datetime.c.

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 }
void DateTimeParseError(int dterr, DateTimeErrorExtra *extra, const char *str, const char *datatype, Node *escontext)
Definition: datetime.c:3981
#define ereport(elevel,...)
Definition: elog.h:149
#define TZNAME_ZONE
Definition: datetime.h:301
#define TZNAME_FIXED_OFFSET
Definition: datetime.h:299
#define TZNAME_DYNTZ
Definition: datetime.h:300
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37

References DateTimeParseError(), DecodeTimezoneAbbrev(), downcase_truncate_identifier(), DTZ, DYNTZ, ereport, errcode(), errmsg(), ERROR, pg_tzset(), type, TZ, TZNAME_DYNTZ, TZNAME_FIXED_OFFSET, and TZNAME_ZONE.

Referenced by DecodeTimezoneNameToTz(), parse_sane_timezone(), timestamp_zone(), timestamptz_zone(), and timetz_zone().

◆ DecodeTimezoneNameToTz()

pg_tz* DecodeTimezoneNameToTz ( const char *  tzname)

Definition at line 3236 of file datetime.c.

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 }
int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz)
Definition: datetime.c:3181
pg_tz * pg_tzset_offset(long gmtoffset)
Definition: pgtz.c:320

References DecodeTimezoneName(), pg_tzset_offset(), and TZNAME_FIXED_OFFSET.

Referenced by lookup_timezone().

◆ DecodeUnits()

int DecodeUnits ( int  field,
const char *  lowtoken,
int *  val 
)

Definition at line 3936 of file datetime.c.

3937 {
3938  int type;
3939  const datetkn *tp;
3940 
3941  tp = deltacache[field];
3942  /* use strncmp so that we match truncated tokens */
3943  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3944  {
3945  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3946  }
3947  if (tp == NULL)
3948  {
3949  type = UNKNOWN_FIELD;
3950  *val = 0;
3951  }
3952  else
3953  {
3954  deltacache[field] = tp;
3955  type = tp->type;
3956  *val = tp->value;
3957  }
3958 
3959  return type;
3960 } /* DecodeUnits() */
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:262

References datebsearch(), deltacache, deltatktbl, szdeltatktbl, datetkn::token, TOKMAXLEN, type, datetkn::type, UNKNOWN_FIELD, val, and datetkn::value.

Referenced by DecodeInterval(), extract_date(), interval_part_common(), interval_trunc(), time_part_common(), timestamp_part_common(), timestamp_trunc(), timestamptz_part_common(), timestamptz_trunc_internal(), and timetz_part_common().

◆ DetermineTimeZoneAbbrevOffset()

int DetermineTimeZoneAbbrevOffset ( struct pg_tm tm,
const char *  abbr,
pg_tz tzp 
)

Definition at line 1748 of file datetime.c.

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 }
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
Definition: datetime.c:1609
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1823
int64 pg_time_t
Definition: pgtime.h:23

References DetermineTimeZoneAbbrevOffsetInternal(), DetermineTimeZoneOffsetInternal(), tm, and pg_tm::tm_isdst.

Referenced by DecodeDateTime(), DecodeTimeOnly(), parse_sane_timezone(), and timestamp_zone().

◆ DetermineTimeZoneAbbrevOffsetTS()

int DetermineTimeZoneAbbrevOffsetTS ( TimestampTz  ts,
const char *  abbr,
pg_tz tzp,
int *  isdst 
)

Definition at line 1786 of file datetime.c.

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 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1762
int32 fsec_t
Definition: timestamp.h:41

References DetermineTimeZoneAbbrevOffsetInternal(), DetermineTimeZoneOffset(), ereport, errcode(), errmsg(), ERROR, timestamp2tm(), timestamptz_to_time_t(), tm, and pg_tm::tm_isdst.

Referenced by pg_timezone_abbrevs(), timestamptz_zone(), and timetz_zone().

◆ DetermineTimeZoneOffset()

◆ EncodeDateOnly()

void EncodeDateOnly ( struct pg_tm tm,
int  style,
char *  str 
)

Definition at line 4116 of file datetime.c.

4117 {
4118  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4119 
4120  switch (style)
4121  {
4122  case USE_ISO_DATES:
4123  case USE_XSD_DATES:
4124  /* compatible with ISO date formats */
4126  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4127  *str++ = '-';
4129  *str++ = '-';
4131  break;
4132 
4133  case USE_SQL_DATES:
4134  /* compatible with Oracle/Ingres date formats */
4135  if (DateOrder == DATEORDER_DMY)
4136  {
4138  *str++ = '/';
4140  }
4141  else
4142  {
4144  *str++ = '/';
4146  }
4147  *str++ = '/';
4149  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4150  break;
4151 
4152  case USE_GERMAN_DATES:
4153  /* German-style date format */
4155  *str++ = '.';
4157  *str++ = '.';
4159  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4160  break;
4161 
4162  case USE_POSTGRES_DATES:
4163  default:
4164  /* traditional date-only style for Postgres */
4165  if (DateOrder == DATEORDER_DMY)
4166  {
4168  *str++ = '-';
4170  }
4171  else
4172  {
4174  *str++ = '-';
4176  }
4177  *str++ = '-';
4179  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4180  break;
4181  }
4182 
4183  if (tm->tm_year <= 0)
4184  {
4185  memcpy(str, " BC", 3); /* Don't copy NUL */
4186  str += 3;
4187  }
4188  *str = '\0';
4189 }
int DateOrder
Definition: globals.c:120
#define USE_SQL_DATES
Definition: miscadmin.h:231
#define USE_POSTGRES_DATES
Definition: miscadmin.h:229
#define USE_ISO_DATES
Definition: miscadmin.h:230
#define DATEORDER_DMY
Definition: miscadmin.h:237
#define USE_XSD_DATES
Definition: miscadmin.h:233
#define USE_GERMAN_DATES
Definition: miscadmin.h:232
char * pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth)
Definition: numutils.c:1270

References Assert(), DateOrder, DATEORDER_DMY, MONTHS_PER_YEAR, pg_ultostr_zeropad(), generate_unaccent_rules::str, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, USE_GERMAN_DATES, USE_ISO_DATES, USE_POSTGRES_DATES, USE_SQL_DATES, and USE_XSD_DATES.

Referenced by date_out(), JsonEncodeDateTime(), map_sql_value_to_xml_value(), and PGTYPESdate_to_asc().

◆ EncodeDateTime()

void EncodeDateTime ( struct pg_tm tm,
fsec_t  fsec,
bool  print_tz,
int  tz,
const char *  tzn,
int  style,
char *  str 
)

Definition at line 4231 of file datetime.c.

4232 {
4233  int day;
4234 
4235  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4236 
4237  /*
4238  * Negative tm_isdst means we have no valid time zone translation.
4239  */
4240  if (tm->tm_isdst < 0)
4241  print_tz = false;
4242 
4243  switch (style)
4244  {
4245  case USE_ISO_DATES:
4246  case USE_XSD_DATES:
4247  /* Compatible with ISO-8601 date formats */
4249  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4250  *str++ = '-';
4252  *str++ = '-';
4254  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4256  *str++ = ':';
4258  *str++ = ':';
4259  str = AppendTimestampSeconds(str, tm, fsec);
4260  if (print_tz)
4261  str = EncodeTimezone(str, tz, style);
4262  break;
4263 
4264  case USE_SQL_DATES:
4265  /* Compatible with Oracle/Ingres date formats */
4266  if (DateOrder == DATEORDER_DMY)
4267  {
4269  *str++ = '/';
4271  }
4272  else
4273  {
4275  *str++ = '/';
4277  }
4278  *str++ = '/';
4280  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4281  *str++ = ' ';
4283  *str++ = ':';
4285  *str++ = ':';
4286  str = AppendTimestampSeconds(str, tm, fsec);
4287 
4288  /*
4289  * Note: the uses of %.*s in this function would be risky if the
4290  * timezone names ever contain non-ASCII characters, since we are
4291  * not being careful to do encoding-aware clipping. However, all
4292  * TZ abbreviations in the IANA database are plain ASCII.
4293  */
4294  if (print_tz)
4295  {
4296  if (tzn)
4297  {
4298  sprintf(str, " %.*s", MAXTZLEN, tzn);
4299  str += strlen(str);
4300  }
4301  else
4302  str = EncodeTimezone(str, tz, style);
4303  }
4304  break;
4305 
4306  case USE_GERMAN_DATES:
4307  /* German variant on European style */
4309  *str++ = '.';
4311  *str++ = '.';
4313  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4314  *str++ = ' ';
4316  *str++ = ':';
4318  *str++ = ':';
4319  str = AppendTimestampSeconds(str, tm, fsec);
4320 
4321  if (print_tz)
4322  {
4323  if (tzn)
4324  {
4325  sprintf(str, " %.*s", MAXTZLEN, tzn);
4326  str += strlen(str);
4327  }
4328  else
4329  str = EncodeTimezone(str, tz, style);
4330  }
4331  break;
4332 
4333  case USE_POSTGRES_DATES:
4334  default:
4335  /* Backward-compatible with traditional Postgres abstime dates */
4336  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4337  tm->tm_wday = j2day(day);
4338  memcpy(str, days[tm->tm_wday], 3);
4339  str += 3;
4340  *str++ = ' ';
4341  if (DateOrder == DATEORDER_DMY)
4342  {
4344  *str++ = ' ';
4345  memcpy(str, months[tm->tm_mon - 1], 3);
4346  str += 3;
4347  }
4348  else
4349  {
4350  memcpy(str, months[tm->tm_mon - 1], 3);
4351  str += 3;
4352  *str++ = ' ';
4354  }
4355  *str++ = ' ';
4357  *str++ = ':';
4359  *str++ = ':';
4360  str = AppendTimestampSeconds(str, tm, fsec);
4361  *str++ = ' ';
4363  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4364 
4365  if (print_tz)
4366  {
4367  if (tzn)
4368  {
4369  sprintf(str, " %.*s", MAXTZLEN, tzn);
4370  str += strlen(str);
4371  }
4372  else
4373  {
4374  /*
4375  * We have a time zone, but no string version. Use the
4376  * numeric form, but be sure to include a leading space to
4377  * avoid formatting something which would be rejected by
4378  * the date/time parser later. - thomas 2001-10-19
4379  */
4380  *str++ = ' ';
4381  str = EncodeTimezone(str, tz, style);
4382  }
4383  }
4384  break;
4385  }
4386 
4387  if (tm->tm_year <= 0)
4388  {
4389  memcpy(str, " BC", 3); /* Don't copy NUL */
4390  str += 3;
4391  }
4392  *str = '\0';
4393 }
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:4078
int j2day(int date)
Definition: datetime.c:346
const char *const months[]
Definition: datetime.c:83
static char * AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
Definition: datetime.c:513
const char *const days[]
Definition: datetime.c:86
#define MAXTZLEN
Definition: miscadmin.h:257
#define sprintf
Definition: port.h:240

References AppendTimestampSeconds(), Assert(), date2j(), DateOrder, DATEORDER_DMY, days, EncodeTimezone(), j2day(), MAXTZLEN, months, MONTHS_PER_YEAR, pg_ultostr_zeropad(), sprintf, generate_unaccent_rules::str, tm, pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_wday, pg_tm::tm_year, USE_GERMAN_DATES, USE_ISO_DATES, USE_POSTGRES_DATES, USE_SQL_DATES, and USE_XSD_DATES.

Referenced by JsonEncodeDateTime(), map_sql_value_to_xml_value(), PGTYPEStimestamp_to_asc(), timestamp_out(), timestamptz_out(), and timestamptz_to_str().

◆ EncodeInterval()

void EncodeInterval ( struct pg_itm itm,
int  style,
char *  str 
)

Definition at line 4474 of file datetime.c.

4475 {
4476  char *cp = str;
4477  int year = itm->tm_year;
4478  int mon = itm->tm_mon;
4479  int64 mday = itm->tm_mday; /* tm_mday could be INT_MIN */
4480  int64 hour = itm->tm_hour;
4481  int min = itm->tm_min;
4482  int sec = itm->tm_sec;
4483  int fsec = itm->tm_usec;
4484  bool is_before = false;
4485  bool is_zero = true;
4486 
4487  /*
4488  * The sign of year and month are guaranteed to match, since they are
4489  * stored internally as "month". But we'll need to check for is_before and
4490  * is_zero when determining the signs of day and hour/minute/seconds
4491  * fields.
4492  */
4493  switch (style)
4494  {
4495  /* SQL Standard interval format */
4496  case INTSTYLE_SQL_STANDARD:
4497  {
4498  bool has_negative = year < 0 || mon < 0 ||
4499  mday < 0 || hour < 0 ||
4500  min < 0 || sec < 0 || fsec < 0;
4501  bool has_positive = year > 0 || mon > 0 ||
4502  mday > 0 || hour > 0 ||
4503  min > 0 || sec > 0 || fsec > 0;
4504  bool has_year_month = year != 0 || mon != 0;
4505  bool has_day_time = mday != 0 || hour != 0 ||
4506  min != 0 || sec != 0 || fsec != 0;
4507  bool has_day = mday != 0;
4508  bool sql_standard_value = !(has_negative && has_positive) &&
4509  !(has_year_month && has_day_time);
4510 
4511  /*
4512  * SQL Standard wants only 1 "<sign>" preceding the whole
4513  * interval ... but can't do that if mixed signs.
4514  */
4515  if (has_negative && sql_standard_value)
4516  {
4517  *cp++ = '-';
4518  year = -year;
4519  mon = -mon;
4520  mday = -mday;
4521  hour = -hour;
4522  min = -min;
4523  sec = -sec;
4524  fsec = -fsec;
4525  }
4526 
4527  if (!has_negative && !has_positive)
4528  {
4529  sprintf(cp, "0");
4530  }
4531  else if (!sql_standard_value)
4532  {
4533  /*
4534  * For non sql-standard interval values, force outputting
4535  * the signs to avoid ambiguities with intervals with
4536  * mixed sign components.
4537  */
4538  char year_sign = (year < 0 || mon < 0) ? '-' : '+';
4539  char day_sign = (mday < 0) ? '-' : '+';
4540  char sec_sign = (hour < 0 || min < 0 ||
4541  sec < 0 || fsec < 0) ? '-' : '+';
4542 
4543  sprintf(cp, "%c%d-%d %c%lld %c%lld:%02d:",
4544  year_sign, abs(year), abs(mon),
4545  day_sign, (long long) i64abs(mday),
4546  sec_sign, (long long) i64abs(hour), abs(min));
4547  cp += strlen(cp);
4548  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4549  *cp = '\0';
4550  }
4551  else if (has_year_month)
4552  {
4553  sprintf(cp, "%d-%d", year, mon);
4554  }
4555  else if (has_day)
4556  {
4557  sprintf(cp, "%lld %lld:%02d:",
4558  (long long) mday, (long long) hour, min);
4559  cp += strlen(cp);
4560  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4561  *cp = '\0';
4562  }
4563  else
4564  {
4565  sprintf(cp, "%lld:%02d:", (long long) hour, min);
4566  cp += strlen(cp);
4567  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4568  *cp = '\0';
4569  }
4570  }
4571  break;
4572 
4573  /* ISO 8601 "time-intervals by duration only" */
4574  case INTSTYLE_ISO_8601:
4575  /* special-case zero to avoid printing nothing */
4576  if (year == 0 && mon == 0 && mday == 0 &&
4577  hour == 0 && min == 0 && sec == 0 && fsec == 0)
4578  {
4579  sprintf(cp, "PT0S");
4580  break;
4581  }
4582  *cp++ = 'P';
4583  cp = AddISO8601IntPart(cp, year, 'Y');
4584  cp = AddISO8601IntPart(cp, mon, 'M');
4585  cp = AddISO8601IntPart(cp, mday, 'D');
4586  if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
4587  *cp++ = 'T';
4588  cp = AddISO8601IntPart(cp, hour, 'H');
4589  cp = AddISO8601IntPart(cp, min, 'M');
4590  if (sec != 0 || fsec != 0)
4591  {
4592  if (sec < 0 || fsec < 0)
4593  *cp++ = '-';
4594  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4595  *cp++ = 'S';
4596  *cp++ = '\0';
4597  }
4598  break;
4599 
4600  /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
4601  case INTSTYLE_POSTGRES:
4602  cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
4603 
4604  /*
4605  * Ideally we should spell out "month" like we do for "year" and
4606  * "day". However, for backward compatibility, we can't easily
4607  * fix this. bjm 2011-05-24
4608  */
4609  cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
4610  cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
4611  if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
4612  {
4613  bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
4614 
4615  sprintf(cp, "%s%s%02lld:%02d:",
4616  is_zero ? "" : " ",
4617  (minus ? "-" : (is_before ? "+" : "")),
4618  (long long) i64abs(hour), abs(min));
4619  cp += strlen(cp);
4620  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4621  *cp = '\0';
4622  }
4623  break;
4624 
4625  /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
4627  default:
4628  strcpy(cp, "@");
4629  cp++;
4630  cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
4631  cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
4632  cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
4633  cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
4634  cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
4635  if (sec != 0 || fsec != 0)
4636  {
4637  *cp++ = ' ';
4638  if (sec < 0 || (sec == 0 && fsec < 0))
4639  {
4640  if (is_zero)
4641  is_before = true;
4642  else if (!is_before)
4643  *cp++ = '-';
4644  }
4645  else if (is_before)
4646  *cp++ = '-';
4647  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4648  /* We output "ago", not negatives, so use abs(). */
4649  sprintf(cp, " sec%s",
4650  (abs(sec) != 1 || fsec != 0) ? "s" : "");
4651  is_zero = false;
4652  }
4653  /* identically zero? then put in a unitless zero... */
4654  if (is_zero)
4655  strcat(cp, " 0");
4656  if (is_before)
4657  strcat(cp, " ago");
4658  break;
4659  }
4660 }
static char * AddVerboseIntPart(char *cp, int64 value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4435
static char * AddPostgresIntPart(char *cp, int64 value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4412
static char * AddISO8601IntPart(char *cp, int64 value, char units)
Definition: datetime.c:4402
static char * AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Definition: datetime.c:450
#define i64abs(i)
Definition: c.h:1317
#define MAX_INTERVAL_PRECISION
Definition: timestamp.h:93
#define INTSTYLE_POSTGRES_VERBOSE
Definition: miscadmin.h:251
#define INTSTYLE_ISO_8601
Definition: miscadmin.h:253
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:250
int64 tm_hour
Definition: timestamp.h:70
int tm_year
Definition: timestamp.h:73
int tm_mon
Definition: timestamp.h:72
int tm_mday
Definition: timestamp.h:71
int tm_sec
Definition: timestamp.h:68
int tm_min
Definition: timestamp.h:69
int tm_usec
Definition: timestamp.h:67

References AddISO8601IntPart(), AddPostgresIntPart(), AddVerboseIntPart(), AppendSeconds(), i64abs, INTSTYLE_ISO_8601, INTSTYLE_POSTGRES, INTSTYLE_POSTGRES_VERBOSE, INTSTYLE_SQL_STANDARD, MAX_INTERVAL_PRECISION, sprintf, generate_unaccent_rules::str, pg_itm::tm_hour, pg_itm::tm_mday, pg_itm::tm_min, pg_itm::tm_mon, pg_itm::tm_sec, pg_itm::tm_usec, and pg_itm::tm_year.

Referenced by interval_out().

◆ EncodeSpecialTimestamp()

void EncodeSpecialTimestamp ( Timestamp  dt,
char *  str 
)

Definition at line 1536 of file timestamp.c.

1537 {
1538  if (TIMESTAMP_IS_NOBEGIN(dt))
1539  strcpy(str, EARLY);
1540  else if (TIMESTAMP_IS_NOEND(dt))
1541  strcpy(str, LATE);
1542  else /* shouldn't happen */
1543  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1544 }
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:166
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:161
#define EARLY
Definition: datetime.h:39
#define LATE
Definition: datetime.h:40

References EARLY, elog(), ERROR, LATE, generate_unaccent_rules::str, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

Referenced by JsonEncodeDateTime(), PGTYPEStimestamp_to_asc(), timestamp_out(), timestamptz_out(), and timestamptz_to_str().

◆ EncodeTimeOnly()

void EncodeTimeOnly ( struct pg_tm tm,
fsec_t  fsec,
bool  print_tz,
int  tz,
int  style,
char *  str 
)

Definition at line 4201 of file datetime.c.

4202 {
4204  *str++ = ':';
4206  *str++ = ':';
4207  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
4208  if (print_tz)
4209  str = EncodeTimezone(str, tz, style);
4210  *str = '\0';
4211 }
#define MAX_TIME_PRECISION
Definition: date.h:45

References AppendSeconds(), EncodeTimezone(), MAX_TIME_PRECISION, pg_ultostr_zeropad(), generate_unaccent_rules::str, tm, pg_tm::tm_hour, pg_tm::tm_min, and pg_tm::tm_sec.

Referenced by JsonEncodeDateTime(), time_out(), and timetz_out().

◆ GetCurrentDateTime()

void GetCurrentDateTime ( struct pg_tm tm)

Definition at line 368 of file datetime.c.

369 {
370  fsec_t fsec;
371 
372  GetCurrentTimeUsec(tm, &fsec, NULL);
373 }

References GetCurrentTimeUsec(), and tm.

Referenced by DecodeDateTime(), DecodeTimeOnly(), GetSQLCurrentDate(), PGTYPESdate_today(), PGTYPEStimestamp_current(), and time_timetz().

◆ GetCurrentTimeUsec()

void GetCurrentTimeUsec ( struct pg_tm tm,
fsec_t fsec,
int *  tzp 
)

Definition at line 389 of file datetime.c.

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 }
int64 TimestampTz
Definition: timestamp.h:39
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:855

References ereport, errcode(), errmsg(), ERROR, GetCurrentTransactionStartTimestamp(), session_timezone, timestamp2tm(), and tm.

Referenced by DecodeDateTime(), DecodeTimeOnly(), GetCurrentDateTime(), GetSQLCurrentTime(), and GetSQLLocalTime().

◆ InstallTimeZoneAbbrevs()

void InstallTimeZoneAbbrevs ( TimeZoneAbbrevTable tbl)

Definition at line 4846 of file datetime.c.

4847 {
4848  zoneabbrevtbl = tbl;
4849  /* reset abbrevcache, which may contain pointers into old table */
4850  memset(abbrevcache, 0, sizeof(abbrevcache));
4851 }

References abbrevcache, and zoneabbrevtbl.

Referenced by assign_timezone_abbreviations().

◆ j2date()

void j2date ( int  jd,
int *  year,
int *  month,
int *  day 
)

Definition at line 313 of file datetime.c.

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() */
int y
Definition: isn.c:72

◆ j2day()

int j2day ( int  date)

Definition at line 346 of file datetime.c.

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() */
long date
Definition: pgtypes_date.h:9

Referenced by date2isoweek(), date2isoyear(), EncodeDateTime(), extract_date(), isoweek2j(), timestamp_part_common(), and timestamptz_part_common().

◆ ParseDateTime()

int ParseDateTime ( const char *  timestr,
char *  workbuf,
size_t  buflen,
char **  field,
int *  ftype,
int  maxfields,
int *  numfields 
)

Definition at line 756 of file datetime.c.

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 }
#define APPEND_CHAR(bufptr, end, newchar)
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122

References APPEND_CHAR, datebsearch(), datetktbl, DTERR_BAD_FORMAT, DTK_DATE, DTK_NUMBER, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TZ, pg_tolower(), and szdatetktbl.

Referenced by check_recovery_target_time(), date_in(), interval_in(), pg_logdir_ls_internal(), PGTYPESdate_from_asc(), PGTYPESinterval_from_asc(), PGTYPEStimestamp_from_asc(), time_in(), timestamp_in(), timestamptz_in(), and timetz_in().

◆ TemporalSimplify()

struct Node* TemporalSimplify ( int32  max_precis,
struct Node node 
)

Definition at line 4729 of file datetime.c.

4730 {
4731  FuncExpr *expr = castNode(FuncExpr, node);
4732  Node *ret = NULL;
4733  Node *typmod;
4734 
4735  Assert(list_length(expr->args) >= 2);
4736 
4737  typmod = (Node *) lsecond(expr->args);
4738 
4739  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
4740  {
4741  Node *source = (Node *) linitial(expr->args);
4742  int32 old_precis = exprTypmod(source);
4743  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4744 
4745  if (new_precis < 0 || new_precis == max_precis ||
4746  (old_precis >= 0 && new_precis >= old_precis))
4747  ret = relabel_to_typmod(source, new_precis);
4748  }
4749 
4750  return ret;
4751 }
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:282
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:654
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static rewind_source * source
Definition: pg_rewind.c:89
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
List * args
Definition: primnodes.h:695
Definition: nodes.h:129

References FuncExpr::args, Assert(), castNode, DatumGetInt32(), exprTypmod(), IsA, linitial, list_length(), lsecond, relabel_to_typmod(), and source.

Referenced by time_support(), and timestamp_support().

◆ ValidateDate()

int ValidateDate ( int  fmask,
bool  isjulian,
bool  is2digits,
bool  bc,
struct pg_tm tm 
)

Definition at line 2499 of file datetime.c.

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 }
const int day_tab[2][13]
Definition: datetime.c:77
#define isleap(y)
Definition: datetime.h:271
#define DOY
Definition: datetime.h:105
int tm_yday
Definition: pgtime.h:43

References date2j(), DAY, day_tab, DOY, DTERR_FIELD_OVERFLOW, DTERR_MD_FIELD_OVERFLOW, DTK_DATE_M, DTK_M, isleap, j2date(), MONTH, MONTHS_PER_YEAR, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_yday, pg_tm::tm_year, and YEAR.

Referenced by DecodeDateTime(), DecodeTimeOnly(), do_to_timestamp(), make_date(), and make_timestamp_internal().

Variable Documentation

◆ day_tab

PGDLLIMPORT const int day_tab[2][13]
extern

Definition at line 77 of file datetime.c.

◆ days

PGDLLIMPORT const char* const days[]
extern

Definition at line 86 of file datetime.c.

◆ months

PGDLLIMPORT const char* const months[]
extern

Definition at line 83 of file datetime.c.