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 349 of file timestamp.c.

350 {
351  static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
352  INT64CONST(1000000),
353  INT64CONST(100000),
354  INT64CONST(10000),
355  INT64CONST(1000),
356  INT64CONST(100),
357  INT64CONST(10),
358  INT64CONST(1)
359  };
360 
361  static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
362  INT64CONST(500000),
363  INT64CONST(50000),
364  INT64CONST(5000),
365  INT64CONST(500),
366  INT64CONST(50),
367  INT64CONST(5),
368  INT64CONST(0)
369  };
370 
371  if (!TIMESTAMP_NOT_FINITE(*time)
372  && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
373  {
374  if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
375  ereturn(escontext, false,
376  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
377  errmsg("timestamp(%d) precision must be between %d and %d",
378  typmod, 0, MAX_TIMESTAMP_PRECISION)));
379 
380  if (*time >= INT64CONST(0))
381  {
382  *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
383  TimestampScales[typmod];
384  }
385  else
386  {
387  *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
388  * TimestampScales[typmod]);
389  }
390  }
391 
392  return true;
393 }
#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 current_timestamp(), parse_datetime(), sql_localtimestamp(), timestamp_in(), timestamp_recv(), timestamp_scale(), timestamptz_in(), timestamptz_recv(), timestamptz_scale(), and to_timestamp().

◆ CheckDateTokenTables()

bool CheckDateTokenTables ( void  )

Definition at line 4686 of file datetime.c.

4687 {
4688  bool ok = true;
4689 
4690  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4691  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4692 
4693  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4694  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4695  return ok;
4696 }
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4654
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 4748 of file datetime.c.

4749 {
4750  TimeZoneAbbrevTable *tbl;
4751  Size tbl_size;
4752  int i;
4753 
4754  /* Space for fixed fields and datetkn array */
4755  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4756  n * sizeof(datetkn);
4757  tbl_size = MAXALIGN(tbl_size);
4758  /* Count up space for dynamic abbreviations */
4759  for (i = 0; i < n; i++)
4760  {
4761  struct tzEntry *abbr = abbrevs + i;
4762 
4763  if (abbr->zone != NULL)
4764  {
4765  Size dsize;
4766 
4767  dsize = offsetof(DynamicZoneAbbrev, zone) +
4768  strlen(abbr->zone) + 1;
4769  tbl_size += MAXALIGN(dsize);
4770  }
4771  }
4772 
4773  /* Alloc the result ... */
4774  tbl = guc_malloc(LOG, tbl_size);
4775  if (!tbl)
4776  return NULL;
4777 
4778  /* ... and fill it in */
4779  tbl->tblsize = tbl_size;
4780  tbl->numabbrevs = n;
4781  /* in this loop, tbl_size reprises the space calculation above */
4782  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4783  n * sizeof(datetkn);
4784  tbl_size = MAXALIGN(tbl_size);
4785  for (i = 0; i < n; i++)
4786  {
4787  struct tzEntry *abbr = abbrevs + i;
4788  datetkn *dtoken = tbl->abbrevs + i;
4789 
4790  /* use strlcpy to truncate name if necessary */
4791  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4792  if (abbr->zone != NULL)
4793  {
4794  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4795  DynamicZoneAbbrev *dtza;
4796  Size dsize;
4797 
4798  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4799  dtza->tz = NULL;
4800  strcpy(dtza->zone, abbr->zone);
4801 
4802  dtoken->type = DYNTZ;
4803  /* value is offset from table start to DynamicZoneAbbrev */
4804  dtoken->value = (int32) tbl_size;
4805 
4806  dsize = offsetof(DynamicZoneAbbrev, zone) +
4807  strlen(abbr->zone) + 1;
4808  tbl_size += MAXALIGN(dsize);
4809  }
4810  else
4811  {
4812  dtoken->type = abbr->is_dst ? DTZ : TZ;
4813  dtoken->value = abbr->offset;
4814  }
4815  }
4816 
4817  /* Assert the two loops above agreed on size calculations */
4818  Assert(tbl->tblsize == tbl_size);
4819 
4820  /* Check the ordering, if testing */
4821  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4822 
4823  return tbl;
4824 }
#define MAXALIGN(LEN)
Definition: c.h:795
signed int int32
Definition: c.h:478
size_t Size
Definition: c.h:589
#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 3967 of file datetime.c.

3970 {
3971  switch (dterr)
3972  {
3973  case DTERR_FIELD_OVERFLOW:
3974  errsave(escontext,
3975  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3976  errmsg("date/time field value out of range: \"%s\"",
3977  str)));
3978  break;
3980  /* <nanny>same as above, but add hint about DateStyle</nanny> */
3981  errsave(escontext,
3982  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3983  errmsg("date/time field value out of range: \"%s\"",
3984  str),
3985  errhint("Perhaps you need a different \"datestyle\" setting.")));
3986  break;
3988  errsave(escontext,
3989  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
3990  errmsg("interval field value out of range: \"%s\"",
3991  str)));
3992  break;
3993  case DTERR_TZDISP_OVERFLOW:
3994  errsave(escontext,
3995  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
3996  errmsg("time zone displacement out of range: \"%s\"",
3997  str)));
3998  break;
3999  case DTERR_BAD_TIMEZONE:
4000  errsave(escontext,
4001  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4002  errmsg("time zone \"%s\" not recognized",
4003  extra->dtee_timezone)));
4004  break;
4005  case DTERR_BAD_ZONE_ABBREV:
4006  errsave(escontext,
4007  (errcode(ERRCODE_CONFIG_FILE_ERROR),
4008  errmsg("time zone \"%s\" not recognized",
4009  extra->dtee_timezone),
4010  errdetail("This time zone name appears in the configuration file for time zone abbreviation \"%s\".",
4011  extra->dtee_abbrev)));
4012  break;
4013  case DTERR_BAD_FORMAT:
4014  default:
4015  errsave(escontext,
4016  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4017  errmsg("invalid input syntax for type %s: \"%s\"",
4018  datatype, str)));
4019  break;
4020  }
4021 }
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:1811
#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:1435
#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 @146 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

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

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

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:4028

References datebsearch(), datecache, datetktbl, szdatetktbl, datetkn::token, TOKMAXLEN, generate_unaccent_rules::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, generate_unaccent_rules::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:4845

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:3967
#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(), generate_unaccent_rules::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 3922 of file datetime.c.

3923 {
3924  int type;
3925  const datetkn *tp;
3926 
3927  tp = deltacache[field];
3928  /* use strncmp so that we match truncated tokens */
3929  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3930  {
3931  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3932  }
3933  if (tp == NULL)
3934  {
3935  type = UNKNOWN_FIELD;
3936  *val = 0;
3937  }
3938  else
3939  {
3940  deltacache[field] = tp;
3941  type = tp->type;
3942  *val = tp->value;
3943  }
3944 
3945  return type;
3946 } /* DecodeUnits() */
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:262

References datebsearch(), deltacache, deltatktbl, szdeltatktbl, datetkn::token, TOKMAXLEN, generate_unaccent_rules::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:1838
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1770
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 4102 of file datetime.c.

4103 {
4104  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4105 
4106  switch (style)
4107  {
4108  case USE_ISO_DATES:
4109  case USE_XSD_DATES:
4110  /* compatible with ISO date formats */
4112  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4113  *str++ = '-';
4115  *str++ = '-';
4117  break;
4118 
4119  case USE_SQL_DATES:
4120  /* compatible with Oracle/Ingres date formats */
4121  if (DateOrder == DATEORDER_DMY)
4122  {
4124  *str++ = '/';
4126  }
4127  else
4128  {
4130  *str++ = '/';
4132  }
4133  *str++ = '/';
4135  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4136  break;
4137 
4138  case USE_GERMAN_DATES:
4139  /* German-style date format */
4141  *str++ = '.';
4143  *str++ = '.';
4145  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4146  break;
4147 
4148  case USE_POSTGRES_DATES:
4149  default:
4150  /* traditional date-only style for Postgres */
4151  if (DateOrder == DATEORDER_DMY)
4152  {
4154  *str++ = '-';
4156  }
4157  else
4158  {
4160  *str++ = '-';
4162  }
4163  *str++ = '-';
4165  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4166  break;
4167  }
4168 
4169  if (tm->tm_year <= 0)
4170  {
4171  memcpy(str, " BC", 3); /* Don't copy NUL */
4172  str += 3;
4173  }
4174  *str = '\0';
4175 }
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:1018

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 4217 of file datetime.c.

4218 {
4219  int day;
4220 
4221  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4222 
4223  /*
4224  * Negative tm_isdst means we have no valid time zone translation.
4225  */
4226  if (tm->tm_isdst < 0)
4227  print_tz = false;
4228 
4229  switch (style)
4230  {
4231  case USE_ISO_DATES:
4232  case USE_XSD_DATES:
4233  /* Compatible with ISO-8601 date formats */
4235  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4236  *str++ = '-';
4238  *str++ = '-';
4240  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4242  *str++ = ':';
4244  *str++ = ':';
4245  str = AppendTimestampSeconds(str, tm, fsec);
4246  if (print_tz)
4247  str = EncodeTimezone(str, tz, style);
4248  break;
4249 
4250  case USE_SQL_DATES:
4251  /* Compatible with Oracle/Ingres date formats */
4252  if (DateOrder == DATEORDER_DMY)
4253  {
4255  *str++ = '/';
4257  }
4258  else
4259  {
4261  *str++ = '/';
4263  }
4264  *str++ = '/';
4266  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4267  *str++ = ' ';
4269  *str++ = ':';
4271  *str++ = ':';
4272  str = AppendTimestampSeconds(str, tm, fsec);
4273 
4274  /*
4275  * Note: the uses of %.*s in this function would be risky if the
4276  * timezone names ever contain non-ASCII characters, since we are
4277  * not being careful to do encoding-aware clipping. However, all
4278  * TZ abbreviations in the IANA database are plain ASCII.
4279  */
4280  if (print_tz)
4281  {
4282  if (tzn)
4283  {
4284  sprintf(str, " %.*s", MAXTZLEN, tzn);
4285  str += strlen(str);
4286  }
4287  else
4288  str = EncodeTimezone(str, tz, style);
4289  }
4290  break;
4291 
4292  case USE_GERMAN_DATES:
4293  /* German variant on European style */
4295  *str++ = '.';
4297  *str++ = '.';
4299  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4300  *str++ = ' ';
4302  *str++ = ':';
4304  *str++ = ':';
4305  str = AppendTimestampSeconds(str, tm, fsec);
4306 
4307  if (print_tz)
4308  {
4309  if (tzn)
4310  {
4311  sprintf(str, " %.*s", MAXTZLEN, tzn);
4312  str += strlen(str);
4313  }
4314  else
4315  str = EncodeTimezone(str, tz, style);
4316  }
4317  break;
4318 
4319  case USE_POSTGRES_DATES:
4320  default:
4321  /* Backward-compatible with traditional Postgres abstime dates */
4322  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4323  tm->tm_wday = j2day(day);
4324  memcpy(str, days[tm->tm_wday], 3);
4325  str += 3;
4326  *str++ = ' ';
4327  if (DateOrder == DATEORDER_DMY)
4328  {
4330  *str++ = ' ';
4331  memcpy(str, months[tm->tm_mon - 1], 3);
4332  str += 3;
4333  }
4334  else
4335  {
4336  memcpy(str, months[tm->tm_mon - 1], 3);
4337  str += 3;
4338  *str++ = ' ';
4340  }
4341  *str++ = ' ';
4343  *str++ = ':';
4345  *str++ = ':';
4346  str = AppendTimestampSeconds(str, tm, fsec);
4347  *str++ = ' ';
4349  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4350 
4351  if (print_tz)
4352  {
4353  if (tzn)
4354  {
4355  sprintf(str, " %.*s", MAXTZLEN, tzn);
4356  str += strlen(str);
4357  }
4358  else
4359  {
4360  /*
4361  * We have a time zone, but no string version. Use the
4362  * numeric form, but be sure to include a leading space to
4363  * avoid formatting something which would be rejected by
4364  * the date/time parser later. - thomas 2001-10-19
4365  */
4366  *str++ = ' ';
4367  str = EncodeTimezone(str, tz, style);
4368  }
4369  }
4370  break;
4371  }
4372 
4373  if (tm->tm_year <= 0)
4374  {
4375  memcpy(str, " BC", 3); /* Don't copy NUL */
4376  str += 3;
4377  }
4378  *str = '\0';
4379 }
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:4064
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 4460 of file datetime.c.

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

1536 {
1537  if (TIMESTAMP_IS_NOBEGIN(dt))
1538  strcpy(str, EARLY);
1539  else if (TIMESTAMP_IS_NOEND(dt))
1540  strcpy(str, LATE);
1541  else /* shouldn't happen */
1542  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1543 }
#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 4187 of file datetime.c.

4188 {
4190  *str++ = ':';
4192  *str++ = ':';
4193  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
4194  if (print_tz)
4195  str = EncodeTimezone(str, tz, style);
4196  *str = '\0';
4197 }
#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 current_date(), DecodeDateTime(), DecodeTimeOnly(), 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 current_time(), DecodeDateTime(), DecodeTimeOnly(), GetCurrentDateTime(), and sql_localtime().

◆ InstallTimeZoneAbbrevs()

void InstallTimeZoneAbbrevs ( TimeZoneAbbrevTable tbl)

Definition at line 4832 of file datetime.c.

4833 {
4834  zoneabbrevtbl = tbl;
4835  /* reset abbrevcache, which may contain pointers into old table */
4836  memset(abbrevcache, 0, sizeof(abbrevcache));
4837 }

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 4715 of file datetime.c.

4716 {
4717  FuncExpr *expr = castNode(FuncExpr, node);
4718  Node *ret = NULL;
4719  Node *typmod;
4720 
4721  Assert(list_length(expr->args) >= 2);
4722 
4723  typmod = (Node *) lsecond(expr->args);
4724 
4725  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
4726  {
4727  Node *source = (Node *) linitial(expr->args);
4728  int32 old_precis = exprTypmod(source);
4729  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4730 
4731  if (new_precis < 0 || new_precis == max_precis ||
4732  (old_precis >= 0 && new_precis >= old_precis))
4733  ret = relabel_to_typmod(source, new_precis);
4734  }
4735 
4736  return ret;
4737 }
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:281
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:651
#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:87
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.