PostgreSQL Source Code  git master
datetime.h File Reference
#include "nodes/nodes.h"
#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
 

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)
 

Typedefs

typedef struct TimeZoneAbbrevTable TimeZoneAbbrevTable
 
typedef struct DynamicZoneAbbrev DynamicZoneAbbrev
 

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)
 
int DecodeTimezone (char *str, int *tzp)
 
int DecodeTimeOnly (char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
 
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, const char *str, const char *datatype) pg_attribute_noreturn()
 
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, char *lowtoken, int *offset, pg_tz **tz)
 
int DecodeSpecial (int field, char *lowtoken, int *val)
 
int DecodeUnits (int field, char *lowtoken, int *val)
 
int j2day (int jd)
 
NodeTemporalSimplify (int32 max_precis, Node *node)
 
bool CheckDateTokenTables (void)
 
TimeZoneAbbrevTableConvertTimeZoneAbbrevs (struct tzEntry *abbrevs, int n)
 
void InstallTimeZoneAbbrevs (TimeZoneAbbrevTable *tbl)
 
void AdjustTimestampForTypmod (Timestamp *time, int32 typmod)
 
bool AdjustTimestampForTypmodError (Timestamp *time, int32 typmod, bool *error)
 

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 113 of file datetime.h.

◆ ABS_BEFORE

#define ABS_BEFORE   20

Definition at line 112 of file datetime.h.

◆ AD

#define AD   0

Definition at line 76 of file datetime.h.

◆ ADBC

#define ADBC   18

Definition at line 109 of file datetime.h.

◆ AGO

#define AGO   19

Definition at line 111 of file datetime.h.

◆ AM

#define AM   0

Definition at line 72 of file datetime.h.

◆ AMPM

#define AMPM   9

Definition at line 100 of file datetime.h.

◆ BC

#define BC   1

Definition at line 77 of file datetime.h.

◆ CENTURY

#define CENTURY   26

Definition at line 120 of file datetime.h.

◆ DA_D

#define DA_D   "ad"

Definition at line 61 of file datetime.h.

◆ DAGO

#define DAGO   "ago"

Definition at line 36 of file datetime.h.

◆ DAY

#define DAY   3

Definition at line 94 of file datetime.h.

◆ DB_C

#define DB_C   "bc"

Definition at line 62 of file datetime.h.

◆ DCENTURY

#define DCENTURY   "century"

Definition at line 59 of file datetime.h.

◆ DCURRENT

#define DCURRENT   "current"

Definition at line 37 of file datetime.h.

◆ DDAY

#define DDAY   "day"

Definition at line 53 of file datetime.h.

◆ DDECADE

#define DDECADE   "decade"

Definition at line 58 of file datetime.h.

◆ DECADE

#define DECADE   25

Definition at line 119 of file datetime.h.

◆ DHOUR

#define DHOUR   "hour"

Definition at line 52 of file datetime.h.

◆ DMICROSEC

#define DMICROSEC   "usecond"

Definition at line 48 of file datetime.h.

◆ DMILLENNIUM

#define DMILLENNIUM   "millennium"

Definition at line 60 of file datetime.h.

◆ DMILLISEC

#define DMILLISEC   "msecond"

Definition at line 49 of file datetime.h.

◆ DMINUTE

#define DMINUTE   "minute"

Definition at line 51 of file datetime.h.

◆ DMONTH

#define DMONTH   "month"

Definition at line 55 of file datetime.h.

◆ DOW

#define DOW   16

Definition at line 107 of file datetime.h.

◆ DOY

#define DOY   15

Definition at line 106 of file datetime.h.

◆ DQUARTER

#define DQUARTER   "quarter"

Definition at line 56 of file datetime.h.

◆ DSECOND

#define DSECOND   "second"

Definition at line 50 of file datetime.h.

◆ DTERR_BAD_FORMAT

#define DTERR_BAD_FORMAT   (-1)

Definition at line 281 of file datetime.h.

◆ DTERR_FIELD_OVERFLOW

#define DTERR_FIELD_OVERFLOW   (-2)

Definition at line 282 of file datetime.h.

◆ DTERR_INTERVAL_OVERFLOW

#define DTERR_INTERVAL_OVERFLOW   (-4)

Definition at line 284 of file datetime.h.

◆ DTERR_MD_FIELD_OVERFLOW

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

Definition at line 283 of file datetime.h.

◆ DTERR_TZDISP_OVERFLOW

#define DTERR_TZDISP_OVERFLOW   (-5)

Definition at line 285 of file datetime.h.

◆ DTIMEZONE

#define DTIMEZONE   "timezone"

Definition at line 63 of file datetime.h.

◆ DTK_AGO

#define DTK_AGO   5

Definition at line 148 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 191 of file datetime.h.

◆ DTK_CENTURY

#define DTK_CENTURY   27

Definition at line 170 of file datetime.h.

◆ DTK_DATE

#define DTK_DATE   2

Definition at line 145 of file datetime.h.

◆ DTK_DATE_M

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

Definition at line 192 of file datetime.h.

◆ DTK_DAY

#define DTK_DAY   21

Definition at line 164 of file datetime.h.

◆ DTK_DECADE

#define DTK_DECADE   26

Definition at line 169 of file datetime.h.

◆ DTK_DELTA

#define DTK_DELTA   17

Definition at line 160 of file datetime.h.

◆ DTK_DOW

#define DTK_DOW   32

Definition at line 176 of file datetime.h.

◆ DTK_DOY

#define DTK_DOY   33

Definition at line 177 of file datetime.h.

◆ DTK_EARLY

#define DTK_EARLY   9

Definition at line 151 of file datetime.h.

◆ DTK_EPOCH

#define DTK_EPOCH   11

Definition at line 153 of file datetime.h.

◆ DTK_HOUR

#define DTK_HOUR   20

Definition at line 163 of file datetime.h.

◆ DTK_ISODOW

#define DTK_ISODOW   37

Definition at line 181 of file datetime.h.

◆ DTK_ISOYEAR

#define DTK_ISOYEAR   36

Definition at line 180 of file datetime.h.

◆ DTK_JULIAN

#define DTK_JULIAN   31

Definition at line 174 of file datetime.h.

◆ DTK_LATE

#define DTK_LATE   10

Definition at line 152 of file datetime.h.

◆ DTK_M

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

Definition at line 188 of file datetime.h.

◆ DTK_MICROSEC

#define DTK_MICROSEC   30

Definition at line 173 of file datetime.h.

◆ DTK_MILLENNIUM

#define DTK_MILLENNIUM   28

Definition at line 171 of file datetime.h.

◆ DTK_MILLISEC

#define DTK_MILLISEC   29

Definition at line 172 of file datetime.h.

◆ DTK_MINUTE

#define DTK_MINUTE   19

Definition at line 162 of file datetime.h.

◆ DTK_MONTH

#define DTK_MONTH   23

Definition at line 166 of file datetime.h.

◆ DTK_NOW

#define DTK_NOW   12

Definition at line 154 of file datetime.h.

◆ DTK_NUMBER

#define DTK_NUMBER   0

Definition at line 142 of file datetime.h.

◆ DTK_QUARTER

#define DTK_QUARTER   24

Definition at line 167 of file datetime.h.

◆ DTK_SECOND

#define DTK_SECOND   18

Definition at line 161 of file datetime.h.

◆ DTK_SPECIAL

#define DTK_SPECIAL   6

Definition at line 150 of file datetime.h.

◆ DTK_STRING

#define DTK_STRING   1

Definition at line 143 of file datetime.h.

◆ DTK_TIME

#define DTK_TIME   3

Definition at line 146 of file datetime.h.

◆ DTK_TIME_M

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

Definition at line 193 of file datetime.h.

◆ DTK_TODAY

#define DTK_TODAY   14

Definition at line 156 of file datetime.h.

◆ DTK_TOMORROW

#define DTK_TOMORROW   15

Definition at line 157 of file datetime.h.

◆ DTK_TZ

#define DTK_TZ   4

Definition at line 147 of file datetime.h.

◆ DTK_TZ_HOUR

#define DTK_TZ_HOUR   34

Definition at line 178 of file datetime.h.

◆ DTK_TZ_MINUTE

#define DTK_TZ_MINUTE   35

Definition at line 179 of file datetime.h.

◆ DTK_WEEK

#define DTK_WEEK   22

Definition at line 165 of file datetime.h.

◆ DTK_YEAR

#define DTK_YEAR   25

Definition at line 168 of file datetime.h.

◆ DTK_YESTERDAY

#define DTK_YESTERDAY   13

Definition at line 155 of file datetime.h.

◆ DTK_ZULU

#define DTK_ZULU   16

Definition at line 158 of file datetime.h.

◆ DTZ

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

Definition at line 97 of file datetime.h.

◆ DTZMOD

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

Definition at line 123 of file datetime.h.

◆ DWEEK

#define DWEEK   "week"

Definition at line 54 of file datetime.h.

◆ DYEAR

#define DYEAR   "year"

Definition at line 57 of file datetime.h.

◆ DYNTZ

#define DYNTZ   7 /* dynamic timezone abbreviation */

Definition at line 98 of file datetime.h.

◆ EARLY

#define EARLY   "-infinity"

Definition at line 40 of file datetime.h.

◆ EPOCH

#define EPOCH   "epoch"

Definition at line 38 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 238 of file datetime.h.

◆ HOUR

#define HOUR   10

Definition at line 101 of file datetime.h.

◆ HR24

#define HR24   2

Definition at line 74 of file datetime.h.

◆ IGNORE_DTF

#define IGNORE_DTF   8

Definition at line 99 of file datetime.h.

◆ INVALID

#define INVALID   "invalid"

Definition at line 39 of file datetime.h.

◆ isleap

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

Definition at line 272 of file datetime.h.

◆ ISODATE

#define ISODATE   22

Definition at line 115 of file datetime.h.

◆ ISOTIME

#define ISOTIME   23

Definition at line 116 of file datetime.h.

◆ JULIAN

#define JULIAN   4

Definition at line 95 of file datetime.h.

◆ LATE

#define LATE   "infinity"

Definition at line 41 of file datetime.h.

◆ MAXDATEFIELDS

#define MAXDATEFIELDS   25

Definition at line 203 of file datetime.h.

◆ MAXDATELEN

#define MAXDATELEN   128

Definition at line 201 of file datetime.h.

◆ MICROSECOND

#define MICROSECOND   14

Definition at line 105 of file datetime.h.

◆ MILLENNIUM

#define MILLENNIUM   27

Definition at line 121 of file datetime.h.

◆ MILLISECOND

#define MILLISECOND   13

Definition at line 104 of file datetime.h.

◆ MINUTE

#define MINUTE   11

Definition at line 102 of file datetime.h.

◆ MONTH

#define MONTH   1

Definition at line 92 of file datetime.h.

◆ NOW

#define NOW   "now"

Definition at line 42 of file datetime.h.

◆ PM

#define PM   1

Definition at line 73 of file datetime.h.

◆ RESERV

#define RESERV   0

Definition at line 91 of file datetime.h.

◆ SECOND

#define SECOND   12

Definition at line 103 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 249 of file datetime.h.

◆ TODAY

#define TODAY   "today"

Definition at line 43 of file datetime.h.

◆ TOKMAXLEN

#define TOKMAXLEN   10

Definition at line 205 of file datetime.h.

◆ TOMORROW

#define TOMORROW   "tomorrow"

Definition at line 44 of file datetime.h.

◆ TZ

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

Definition at line 96 of file datetime.h.

◆ UNITS

#define UNITS   17

Definition at line 108 of file datetime.h.

◆ UNKNOWN_FIELD

#define UNKNOWN_FIELD   31

Definition at line 125 of file datetime.h.

◆ WEEK

#define WEEK   24

Definition at line 118 of file datetime.h.

◆ YEAR

#define YEAR   2

Definition at line 93 of file datetime.h.

◆ YESTERDAY

#define YESTERDAY   "yesterday"

Definition at line 45 of file datetime.h.

◆ ZULU

#define ZULU   "zulu"

Definition at line 46 of file datetime.h.

Typedef Documentation

◆ DynamicZoneAbbrev

◆ TimeZoneAbbrevTable

Function Documentation

◆ AdjustTimestampForTypmod()

void AdjustTimestampForTypmod ( Timestamp time,
int32  typmod 
)

Definition at line 395 of file timestamp.c.

396 {
397  (void) AdjustTimestampForTypmodError(time, typmod, NULL);
398 }
bool AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
Definition: timestamp.c:340

References AdjustTimestampForTypmodError().

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

◆ AdjustTimestampForTypmodError()

bool AdjustTimestampForTypmodError ( Timestamp time,
int32  typmod,
bool error 
)

Definition at line 340 of file timestamp.c.

341 {
342  static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
343  INT64CONST(1000000),
344  INT64CONST(100000),
345  INT64CONST(10000),
346  INT64CONST(1000),
347  INT64CONST(100),
348  INT64CONST(10),
349  INT64CONST(1)
350  };
351 
352  static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
353  INT64CONST(500000),
354  INT64CONST(50000),
355  INT64CONST(5000),
356  INT64CONST(500),
357  INT64CONST(50),
358  INT64CONST(5),
359  INT64CONST(0)
360  };
361 
362  if (!TIMESTAMP_NOT_FINITE(*time)
363  && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
364  {
365  if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
366  {
367  if (error)
368  {
369  *error = true;
370  return false;
371  }
372 
373  ereport(ERROR,
374  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
375  errmsg("timestamp(%d) precision must be between %d and %d",
376  typmod, 0, MAX_TIMESTAMP_PRECISION)));
377  }
378 
379  if (*time >= INT64CONST(0))
380  {
381  *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
382  TimestampScales[typmod];
383  }
384  else
385  {
386  *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
387  * TimestampScales[typmod]);
388  }
389  }
390 
391  return true;
392 }
#define MAX_TIMESTAMP_PRECISION
Definition: timestamp.h:92
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:161
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
static void error(void)
Definition: sql-dyntest.c:147

References ereport, errcode(), errmsg(), ERROR, error(), MAX_TIMESTAMP_PRECISION, and TIMESTAMP_NOT_FINITE.

Referenced by AdjustTimestampForTypmod().

◆ CheckDateTokenTables()

bool CheckDateTokenTables ( void  )

Definition at line 4727 of file datetime.c.

4728 {
4729  bool ok = true;
4730 
4731  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4732  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4733 
4734  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4735  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4736  return ok;
4737 }
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4695
static const datetkn datetktbl[]
Definition: datetime.c:104
int date2j(int y, int m, int d)
Definition: datetime.c:284
static const int szdeltatktbl
Definition: datetime.c:250
static const int szdatetktbl
Definition: datetime.c:179
static const datetkn deltatktbl[]
Definition: datetime.c:185
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:201
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:202
Assert(fmt[strlen(fmt) - 1] !='\n')

◆ ConvertTimeZoneAbbrevs()

TimeZoneAbbrevTable* ConvertTimeZoneAbbrevs ( struct tzEntry abbrevs,
int  n 
)

Definition at line 4789 of file datetime.c.

4790 {
4791  TimeZoneAbbrevTable *tbl;
4792  Size tbl_size;
4793  int i;
4794 
4795  /* Space for fixed fields and datetkn array */
4796  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4797  n * sizeof(datetkn);
4798  tbl_size = MAXALIGN(tbl_size);
4799  /* Count up space for dynamic abbreviations */
4800  for (i = 0; i < n; i++)
4801  {
4802  struct tzEntry *abbr = abbrevs + i;
4803 
4804  if (abbr->zone != NULL)
4805  {
4806  Size dsize;
4807 
4808  dsize = offsetof(DynamicZoneAbbrev, zone) +
4809  strlen(abbr->zone) + 1;
4810  tbl_size += MAXALIGN(dsize);
4811  }
4812  }
4813 
4814  /* Alloc the result ... */
4815  tbl = malloc(tbl_size);
4816  if (!tbl)
4817  return NULL;
4818 
4819  /* ... and fill it in */
4820  tbl->tblsize = tbl_size;
4821  tbl->numabbrevs = n;
4822  /* in this loop, tbl_size reprises the space calculation above */
4823  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4824  n * sizeof(datetkn);
4825  tbl_size = MAXALIGN(tbl_size);
4826  for (i = 0; i < n; i++)
4827  {
4828  struct tzEntry *abbr = abbrevs + i;
4829  datetkn *dtoken = tbl->abbrevs + i;
4830 
4831  /* use strlcpy to truncate name if necessary */
4832  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4833  if (abbr->zone != NULL)
4834  {
4835  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4836  DynamicZoneAbbrev *dtza;
4837  Size dsize;
4838 
4839  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4840  dtza->tz = NULL;
4841  strcpy(dtza->zone, abbr->zone);
4842 
4843  dtoken->type = DYNTZ;
4844  /* value is offset from table start to DynamicZoneAbbrev */
4845  dtoken->value = (int32) tbl_size;
4846 
4847  dsize = offsetof(DynamicZoneAbbrev, zone) +
4848  strlen(abbr->zone) + 1;
4849  tbl_size += MAXALIGN(dsize);
4850  }
4851  else
4852  {
4853  dtoken->type = abbr->is_dst ? DTZ : TZ;
4854  dtoken->value = abbr->offset;
4855  }
4856  }
4857 
4858  /* Assert the two loops above agreed on size calculations */
4859  Assert(tbl->tblsize == tbl_size);
4860 
4861  /* Check the ordering, if testing */
4862  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4863 
4864  return tbl;
4865 }
#define MAXALIGN(LEN)
Definition: c.h:757
#define offsetof(type, field)
Definition: c.h:727
signed int int32
Definition: c.h:429
size_t Size
Definition: c.h:540
#define malloc(a)
Definition: header.h:50
#define TZ
Definition: datetime.h:96
#define DTZ
Definition: datetime.h:97
#define TOKMAXLEN
Definition: datetime.h:205
#define DYNTZ
Definition: datetime.h:98
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:228
datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:220
char token[TOKMAXLEN+1]
Definition: datetime.h:210
int32 value
Definition: datetime.h:212
char type
Definition: datetime.h:211
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, i, tzEntry::is_dst, malloc, MAXALIGN, TimeZoneAbbrevTable::numabbrevs, tzEntry::offset, offsetof, 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 284 of file datetime.c.

285 {
286  int julian;
287  int century;
288 
289  if (m > 2)
290  {
291  m += 1;
292  y += 4800;
293  }
294  else
295  {
296  m += 13;
297  y += 4799;
298  }
299 
300  century = y / 100;
301  julian = y * 365 - 32167;
302  julian += y / 4 - century + century / 4;
303  julian += 7834 * m / 256 + d;
304 
305  return julian;
306 } /* date2j() */
int y
Definition: isn.c:72

◆ DateTimeParseError()

void DateTimeParseError ( int  dterr,
const char *  str,
const char *  datatype 
)

Definition at line 4024 of file datetime.c.

4025 {
4026  switch (dterr)
4027  {
4028  case DTERR_FIELD_OVERFLOW:
4029  ereport(ERROR,
4030  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
4031  errmsg("date/time field value out of range: \"%s\"",
4032  str)));
4033  break;
4035  /* <nanny>same as above, but add hint about DateStyle</nanny> */
4036  ereport(ERROR,
4037  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
4038  errmsg("date/time field value out of range: \"%s\"",
4039  str),
4040  errhint("Perhaps you need a different \"datestyle\" setting.")));
4041  break;
4043  ereport(ERROR,
4044  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
4045  errmsg("interval field value out of range: \"%s\"",
4046  str)));
4047  break;
4048  case DTERR_TZDISP_OVERFLOW:
4049  ereport(ERROR,
4050  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
4051  errmsg("time zone displacement out of range: \"%s\"",
4052  str)));
4053  break;
4054  case DTERR_BAD_FORMAT:
4055  default:
4056  ereport(ERROR,
4057  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
4058  errmsg("invalid input syntax for type %s: \"%s\"",
4059  datatype, str)));
4060  break;
4061  }
4062 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:284
#define DTERR_BAD_FORMAT
Definition: datetime.h:281
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:285
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:282
#define DTERR_MD_FIELD_OVERFLOW
Definition: datetime.h:283

References DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTERR_INTERVAL_OVERFLOW, DTERR_MD_FIELD_OVERFLOW, DTERR_TZDISP_OVERFLOW, ereport, errcode(), errhint(), errmsg(), ERROR, and generate_unaccent_rules::str.

Referenced by date_in(), do_to_timestamp(), interval_in(), parse_datetime(), 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 
)

Definition at line 973 of file datetime.c.

975 {
976  int fmask = 0,
977  tmask,
978  type;
979  int ptype = 0; /* "prefix type" for ISO y2001m02d04 format */
980  int i;
981  int val;
982  int dterr;
983  int mer = HR24;
984  bool haveTextMonth = false;
985  bool isjulian = false;
986  bool is2digits = false;
987  bool bc = false;
988  pg_tz *namedTz = NULL;
989  pg_tz *abbrevTz = NULL;
990  pg_tz *valtz;
991  char *abbrev = NULL;
992  struct pg_tm cur_tm;
993 
994  /*
995  * We'll insist on at least all of the date fields, but initialize the
996  * remaining fields in case they are not set later...
997  */
998  *dtype = DTK_DATE;
999  tm->tm_hour = 0;
1000  tm->tm_min = 0;
1001  tm->tm_sec = 0;
1002  *fsec = 0;
1003  /* don't know daylight savings time status apriori */
1004  tm->tm_isdst = -1;
1005  if (tzp != NULL)
1006  *tzp = 0;
1007 
1008  for (i = 0; i < nf; i++)
1009  {
1010  switch (ftype[i])
1011  {
1012  case DTK_DATE:
1013 
1014  /*
1015  * Integral julian day with attached time zone? All other
1016  * forms with JD will be separated into distinct fields, so we
1017  * handle just this case here.
1018  */
1019  if (ptype == DTK_JULIAN)
1020  {
1021  char *cp;
1022  int val;
1023 
1024  if (tzp == NULL)
1025  return DTERR_BAD_FORMAT;
1026 
1027  errno = 0;
1028  val = strtoint(field[i], &cp, 10);
1029  if (errno == ERANGE || val < 0)
1030  return DTERR_FIELD_OVERFLOW;
1031 
1032  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1033  isjulian = true;
1034 
1035  /* Get the time zone from the end of the string */
1036  dterr = DecodeTimezone(cp, tzp);
1037  if (dterr)
1038  return dterr;
1039 
1040  tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
1041  ptype = 0;
1042  break;
1043  }
1044 
1045  /*
1046  * Already have a date? Then this might be a time zone name
1047  * with embedded punctuation (e.g. "America/New_York") or a
1048  * run-together time with trailing time zone (e.g. hhmmss-zz).
1049  * - thomas 2001-12-25
1050  *
1051  * We consider it a time zone if we already have month & day.
1052  * This is to allow the form "mmm dd hhmmss tz year", which
1053  * we've historically accepted.
1054  */
1055  else if (ptype != 0 ||
1056  ((fmask & (DTK_M(MONTH) | DTK_M(DAY))) ==
1057  (DTK_M(MONTH) | DTK_M(DAY))))
1058  {
1059  /* No time zone accepted? Then quit... */
1060  if (tzp == NULL)
1061  return DTERR_BAD_FORMAT;
1062 
1063  if (isdigit((unsigned char) *field[i]) || ptype != 0)
1064  {
1065  char *cp;
1066 
1067  if (ptype != 0)
1068  {
1069  /* Sanity check; should not fail this test */
1070  if (ptype != DTK_TIME)
1071  return DTERR_BAD_FORMAT;
1072  ptype = 0;
1073  }
1074 
1075  /*
1076  * Starts with a digit but we already have a time
1077  * field? Then we are in trouble with a date and time
1078  * already...
1079  */
1080  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1081  return DTERR_BAD_FORMAT;
1082 
1083  if ((cp = strchr(field[i], '-')) == NULL)
1084  return DTERR_BAD_FORMAT;
1085 
1086  /* Get the time zone from the end of the string */
1087  dterr = DecodeTimezone(cp, tzp);
1088  if (dterr)
1089  return dterr;
1090  *cp = '\0';
1091 
1092  /*
1093  * Then read the rest of the field as a concatenated
1094  * time
1095  */
1096  dterr = DecodeNumberField(strlen(field[i]), field[i],
1097  fmask,
1098  &tmask, tm,
1099  fsec, &is2digits);
1100  if (dterr < 0)
1101  return dterr;
1102 
1103  /*
1104  * modify tmask after returning from
1105  * DecodeNumberField()
1106  */
1107  tmask |= DTK_M(TZ);
1108  }
1109  else
1110  {
1111  namedTz = pg_tzset(field[i]);
1112  if (!namedTz)
1113  {
1114  /*
1115  * We should return an error code instead of
1116  * ereport'ing directly, but then there is no way
1117  * to report the bad time zone name.
1118  */
1119  ereport(ERROR,
1120  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1121  errmsg("time zone \"%s\" not recognized",
1122  field[i])));
1123  }
1124  /* we'll apply the zone setting below */
1125  tmask = DTK_M(TZ);
1126  }
1127  }
1128  else
1129  {
1130  dterr = DecodeDate(field[i], fmask,
1131  &tmask, &is2digits, tm);
1132  if (dterr)
1133  return dterr;
1134  }
1135  break;
1136 
1137  case DTK_TIME:
1138 
1139  /*
1140  * This might be an ISO time following a "t" field.
1141  */
1142  if (ptype != 0)
1143  {
1144  /* Sanity check; should not fail this test */
1145  if (ptype != DTK_TIME)
1146  return DTERR_BAD_FORMAT;
1147  ptype = 0;
1148  }
1149  dterr = DecodeTime(field[i], fmask, INTERVAL_FULL_RANGE,
1150  &tmask, tm, fsec);
1151  if (dterr)
1152  return dterr;
1153 
1154  /* check for time overflow */
1156  *fsec))
1157  return DTERR_FIELD_OVERFLOW;
1158  break;
1159 
1160  case DTK_TZ:
1161  {
1162  int tz;
1163 
1164  if (tzp == NULL)
1165  return DTERR_BAD_FORMAT;
1166 
1167  dterr = DecodeTimezone(field[i], &tz);
1168  if (dterr)
1169  return dterr;
1170  *tzp = tz;
1171  tmask = DTK_M(TZ);
1172  }
1173  break;
1174 
1175  case DTK_NUMBER:
1176 
1177  /*
1178  * Was this an "ISO date" with embedded field labels? An
1179  * example is "y2001m02d04" - thomas 2001-02-04
1180  */
1181  if (ptype != 0)
1182  {
1183  char *cp;
1184  int val;
1185 
1186  errno = 0;
1187  val = strtoint(field[i], &cp, 10);
1188  if (errno == ERANGE)
1189  return DTERR_FIELD_OVERFLOW;
1190 
1191  /*
1192  * only a few kinds are allowed to have an embedded
1193  * decimal
1194  */
1195  if (*cp == '.')
1196  switch (ptype)
1197  {
1198  case DTK_JULIAN:
1199  case DTK_TIME:
1200  case DTK_SECOND:
1201  break;
1202  default:
1203  return DTERR_BAD_FORMAT;
1204  break;
1205  }
1206  else if (*cp != '\0')
1207  return DTERR_BAD_FORMAT;
1208 
1209  switch (ptype)
1210  {
1211  case DTK_YEAR:
1212  tm->tm_year = val;
1213  tmask = DTK_M(YEAR);
1214  break;
1215 
1216  case DTK_MONTH:
1217 
1218  /*
1219  * already have a month and hour? then assume
1220  * minutes
1221  */
1222  if ((fmask & DTK_M(MONTH)) != 0 &&
1223  (fmask & DTK_M(HOUR)) != 0)
1224  {
1225  tm->tm_min = val;
1226  tmask = DTK_M(MINUTE);
1227  }
1228  else
1229  {
1230  tm->tm_mon = val;
1231  tmask = DTK_M(MONTH);
1232  }
1233  break;
1234 
1235  case DTK_DAY:
1236  tm->tm_mday = val;
1237  tmask = DTK_M(DAY);
1238  break;
1239 
1240  case DTK_HOUR:
1241  tm->tm_hour = val;
1242  tmask = DTK_M(HOUR);
1243  break;
1244 
1245  case DTK_MINUTE:
1246  tm->tm_min = val;
1247  tmask = DTK_M(MINUTE);
1248  break;
1249 
1250  case DTK_SECOND:
1251  tm->tm_sec = val;
1252  tmask = DTK_M(SECOND);
1253  if (*cp == '.')
1254  {
1255  dterr = ParseFractionalSecond(cp, fsec);
1256  if (dterr)
1257  return dterr;
1258  tmask = DTK_ALL_SECS_M;
1259  }
1260  break;
1261 
1262  case DTK_TZ:
1263  tmask = DTK_M(TZ);
1264  dterr = DecodeTimezone(field[i], tzp);
1265  if (dterr)
1266  return dterr;
1267  break;
1268 
1269  case DTK_JULIAN:
1270  /* previous field was a label for "julian date" */
1271  if (val < 0)
1272  return DTERR_FIELD_OVERFLOW;
1273  tmask = DTK_DATE_M;
1274  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1275  isjulian = true;
1276 
1277  /* fractional Julian Day? */
1278  if (*cp == '.')
1279  {
1280  double time;
1281 
1282  dterr = ParseFraction(cp, &time);
1283  if (dterr)
1284  return dterr;
1285  time *= USECS_PER_DAY;
1286  dt2time(time,
1287  &tm->tm_hour, &tm->tm_min,
1288  &tm->tm_sec, fsec);
1289  tmask |= DTK_TIME_M;
1290  }
1291  break;
1292 
1293  case DTK_TIME:
1294  /* previous field was "t" for ISO time */
1295  dterr = DecodeNumberField(strlen(field[i]), field[i],
1296  (fmask | DTK_DATE_M),
1297  &tmask, tm,
1298  fsec, &is2digits);
1299  if (dterr < 0)
1300  return dterr;
1301  if (tmask != DTK_TIME_M)
1302  return DTERR_BAD_FORMAT;
1303  break;
1304 
1305  default:
1306  return DTERR_BAD_FORMAT;
1307  break;
1308  }
1309 
1310  ptype = 0;
1311  *dtype = DTK_DATE;
1312  }
1313  else
1314  {
1315  char *cp;
1316  int flen;
1317 
1318  flen = strlen(field[i]);
1319  cp = strchr(field[i], '.');
1320 
1321  /* Embedded decimal and no date yet? */
1322  if (cp != NULL && !(fmask & DTK_DATE_M))
1323  {
1324  dterr = DecodeDate(field[i], fmask,
1325  &tmask, &is2digits, tm);
1326  if (dterr)
1327  return dterr;
1328  }
1329  /* embedded decimal and several digits before? */
1330  else if (cp != NULL && flen - strlen(cp) > 2)
1331  {
1332  /*
1333  * Interpret as a concatenated date or time Set the
1334  * type field to allow decoding other fields later.
1335  * Example: 20011223 or 040506
1336  */
1337  dterr = DecodeNumberField(flen, field[i], fmask,
1338  &tmask, tm,
1339  fsec, &is2digits);
1340  if (dterr < 0)
1341  return dterr;
1342  }
1343 
1344  /*
1345  * Is this a YMD or HMS specification, or a year number?
1346  * YMD and HMS are required to be six digits or more, so
1347  * if it is 5 digits, it is a year. If it is six or more
1348  * digits, we assume it is YMD or HMS unless no date and
1349  * no time values have been specified. This forces 6+
1350  * digit years to be at the end of the string, or to use
1351  * the ISO date specification.
1352  */
1353  else if (flen >= 6 && (!(fmask & DTK_DATE_M) ||
1354  !(fmask & DTK_TIME_M)))
1355  {
1356  dterr = DecodeNumberField(flen, field[i], fmask,
1357  &tmask, tm,
1358  fsec, &is2digits);
1359  if (dterr < 0)
1360  return dterr;
1361  }
1362  /* otherwise it is a single date/time field... */
1363  else
1364  {
1365  dterr = DecodeNumber(flen, field[i],
1366  haveTextMonth, fmask,
1367  &tmask, tm,
1368  fsec, &is2digits);
1369  if (dterr)
1370  return dterr;
1371  }
1372  }
1373  break;
1374 
1375  case DTK_STRING:
1376  case DTK_SPECIAL:
1377  /* timezone abbrevs take precedence over built-in tokens */
1378  type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
1379  if (type == UNKNOWN_FIELD)
1380  type = DecodeSpecial(i, field[i], &val);
1381  if (type == IGNORE_DTF)
1382  continue;
1383 
1384  tmask = DTK_M(type);
1385  switch (type)
1386  {
1387  case RESERV:
1388  switch (val)
1389  {
1390  case DTK_NOW:
1391  tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
1392  *dtype = DTK_DATE;
1393  GetCurrentTimeUsec(tm, fsec, tzp);
1394  break;
1395 
1396  case DTK_YESTERDAY:
1397  tmask = DTK_DATE_M;
1398  *dtype = DTK_DATE;
1399  GetCurrentDateTime(&cur_tm);
1400  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) - 1,
1401  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1402  break;
1403 
1404  case DTK_TODAY:
1405  tmask = DTK_DATE_M;
1406  *dtype = DTK_DATE;
1407  GetCurrentDateTime(&cur_tm);
1408  tm->tm_year = cur_tm.tm_year;
1409  tm->tm_mon = cur_tm.tm_mon;
1410  tm->tm_mday = cur_tm.tm_mday;
1411  break;
1412 
1413  case DTK_TOMORROW:
1414  tmask = DTK_DATE_M;
1415  *dtype = DTK_DATE;
1416  GetCurrentDateTime(&cur_tm);
1417  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) + 1,
1418  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1419  break;
1420 
1421  case DTK_ZULU:
1422  tmask = (DTK_TIME_M | DTK_M(TZ));
1423  *dtype = DTK_DATE;
1424  tm->tm_hour = 0;
1425  tm->tm_min = 0;
1426  tm->tm_sec = 0;
1427  if (tzp != NULL)
1428  *tzp = 0;
1429  break;
1430 
1431  default:
1432  *dtype = val;
1433  }
1434 
1435  break;
1436 
1437  case MONTH:
1438 
1439  /*
1440  * already have a (numeric) month? then see if we can
1441  * substitute...
1442  */
1443  if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
1444  !(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 &&
1445  tm->tm_mon <= 31)
1446  {
1447  tm->tm_mday = tm->tm_mon;
1448  tmask = DTK_M(DAY);
1449  }
1450  haveTextMonth = true;
1451  tm->tm_mon = val;
1452  break;
1453 
1454  case DTZMOD:
1455 
1456  /*
1457  * daylight savings time modifier (solves "MET DST"
1458  * syntax)
1459  */
1460  tmask |= DTK_M(DTZ);
1461  tm->tm_isdst = 1;
1462  if (tzp == NULL)
1463  return DTERR_BAD_FORMAT;
1464  *tzp -= val;
1465  break;
1466 
1467  case DTZ:
1468 
1469  /*
1470  * set mask for TZ here _or_ check for DTZ later when
1471  * getting default timezone
1472  */
1473  tmask |= DTK_M(TZ);
1474  tm->tm_isdst = 1;
1475  if (tzp == NULL)
1476  return DTERR_BAD_FORMAT;
1477  *tzp = -val;
1478  break;
1479 
1480  case TZ:
1481  tm->tm_isdst = 0;
1482  if (tzp == NULL)
1483  return DTERR_BAD_FORMAT;
1484  *tzp = -val;
1485  break;
1486 
1487  case DYNTZ:
1488  tmask |= DTK_M(TZ);
1489  if (tzp == NULL)
1490  return DTERR_BAD_FORMAT;
1491  /* we'll determine the actual offset later */
1492  abbrevTz = valtz;
1493  abbrev = field[i];
1494  break;
1495 
1496  case AMPM:
1497  mer = val;
1498  break;
1499 
1500  case ADBC:
1501  bc = (val == BC);
1502  break;
1503 
1504  case DOW:
1505  tm->tm_wday = val;
1506  break;
1507 
1508  case UNITS:
1509  tmask = 0;
1510  ptype = val;
1511  break;
1512 
1513  case ISOTIME:
1514 
1515  /*
1516  * This is a filler field "t" indicating that the next
1517  * field is time. Try to verify that this is sensible.
1518  */
1519  tmask = 0;
1520 
1521  /* No preceding date? Then quit... */
1522  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1523  return DTERR_BAD_FORMAT;
1524 
1525  /***
1526  * We will need one of the following fields:
1527  * DTK_NUMBER should be hhmmss.fff
1528  * DTK_TIME should be hh:mm:ss.fff
1529  * DTK_DATE should be hhmmss-zz
1530  ***/
1531  if (i >= nf - 1 ||
1532  (ftype[i + 1] != DTK_NUMBER &&
1533  ftype[i + 1] != DTK_TIME &&
1534  ftype[i + 1] != DTK_DATE))
1535  return DTERR_BAD_FORMAT;
1536 
1537  ptype = val;
1538  break;
1539 
1540  case UNKNOWN_FIELD:
1541 
1542  /*
1543  * Before giving up and declaring error, check to see
1544  * if it is an all-alpha timezone name.
1545  */
1546  namedTz = pg_tzset(field[i]);
1547  if (!namedTz)
1548  return DTERR_BAD_FORMAT;
1549  /* we'll apply the zone setting below */
1550  tmask = DTK_M(TZ);
1551  break;
1552 
1553  default:
1554  return DTERR_BAD_FORMAT;
1555  }
1556  break;
1557 
1558  default:
1559  return DTERR_BAD_FORMAT;
1560  }
1561 
1562  if (tmask & fmask)
1563  return DTERR_BAD_FORMAT;
1564  fmask |= tmask;
1565  } /* end loop over fields */
1566 
1567  /* do final checking/adjustment of Y/M/D fields */
1568  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
1569  if (dterr)
1570  return dterr;
1571 
1572  /* handle AM/PM */
1573  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
1574  return DTERR_FIELD_OVERFLOW;
1575  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
1576  tm->tm_hour = 0;
1577  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
1578  tm->tm_hour += HOURS_PER_DAY / 2;
1579 
1580  /* do additional checking for full date specs... */
1581  if (*dtype == DTK_DATE)
1582  {
1583  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1584  {
1585  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1586  return 1;
1587  return DTERR_BAD_FORMAT;
1588  }
1589 
1590  /*
1591  * If we had a full timezone spec, compute the offset (we could not do
1592  * it before, because we need the date to resolve DST status).
1593  */
1594  if (namedTz != NULL)
1595  {
1596  /* daylight savings time modifier disallowed with full TZ */
1597  if (fmask & DTK_M(DTZMOD))
1598  return DTERR_BAD_FORMAT;
1599 
1600  *tzp = DetermineTimeZoneOffset(tm, namedTz);
1601  }
1602 
1603  /*
1604  * Likewise, if we had a dynamic timezone abbreviation, resolve it
1605  * now.
1606  */
1607  if (abbrevTz != NULL)
1608  {
1609  /* daylight savings time modifier disallowed with dynamic TZ */
1610  if (fmask & DTK_M(DTZMOD))
1611  return DTERR_BAD_FORMAT;
1612 
1613  *tzp = DetermineTimeZoneAbbrevOffset(tm, abbrev, abbrevTz);
1614  }
1615 
1616  /* timezone not specified? then use session timezone */
1617  if (tzp != NULL && !(fmask & DTK_M(TZ)))
1618  {
1619  /*
1620  * daylight savings time modifier but no standard timezone? then
1621  * error
1622  */
1623  if (fmask & DTK_M(DTZMOD))
1624  return DTERR_BAD_FORMAT;
1625 
1627  }
1628  }
1629 
1630  return 0;
1631 }
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits, struct pg_tm *tm)
Definition: datetime.c:2538
static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:3052
int DecodeTimezoneAbbrev(int field, char *lowtoken, int *offset, pg_tz **tz)
Definition: datetime.c:3225
int DecodeTimezone(char *str, int *tzp)
Definition: datetime.c:3147
static int ParseFraction(char *cp, double *frac)
Definition: datetime.c:678
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1647
static int ParseFractionalSecond(char *cp, fsec_t *fsec)
Definition: datetime.c:707
int DecodeSpecial(int field, char *lowtoken, int *val)
Definition: datetime.c:3280
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2812
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2648
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:309
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:364
static int DecodeNumber(int flen, char *field, bool haveTextMonth, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2867
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:385
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1808
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1789
#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:1415
#define DTK_TOMORROW
Definition: datetime.h:157
#define DTK_SPECIAL
Definition: datetime.h:150
#define AMPM
Definition: datetime.h:100
#define DTK_TIME
Definition: datetime.h:146
#define UNKNOWN_FIELD
Definition: datetime.h:125
#define DTK_SECOND
Definition: datetime.h:161
#define PM
Definition: datetime.h:73
#define DTK_NUMBER
Definition: datetime.h:142
#define DTK_STRING
Definition: datetime.h:143
#define DTK_JULIAN
Definition: datetime.h:174
#define MONTH
Definition: datetime.h:92
#define IGNORE_DTF
Definition: datetime.h:99
#define DTK_TIME_M
Definition: datetime.h:193
#define DTK_M(t)
Definition: datetime.h:188
#define HOUR
Definition: datetime.h:101
#define DAY
Definition: datetime.h:94
#define ADBC
Definition: datetime.h:109
#define YEAR
Definition: datetime.h:93
#define DTK_DATE
Definition: datetime.h:145
#define DTK_DAY
Definition: datetime.h:164
#define RESERV
Definition: datetime.h:91
#define BC
Definition: datetime.h:77
#define HR24
Definition: datetime.h:74
#define DTK_DATE_M
Definition: datetime.h:192
#define SECOND
Definition: datetime.h:103
#define DTK_ALL_SECS_M
Definition: datetime.h:191
#define DTZMOD
Definition: datetime.h:123
#define DTK_TZ
Definition: datetime.h:147
#define DOW
Definition: datetime.h:107
#define ISOTIME
Definition: datetime.h:116
#define DTK_HOUR
Definition: datetime.h:163
#define MINUTE
Definition: datetime.h:102
#define DTK_YEAR
Definition: datetime.h:168
#define AM
Definition: datetime.h:72
#define DTK_MONTH
Definition: datetime.h:166
#define DTK_YESTERDAY
Definition: datetime.h:155
#define DTK_ZULU
Definition: datetime.h:158
#define DTK_MINUTE
Definition: datetime.h:162
#define UNITS
Definition: datetime.h:108
#define DTK_TODAY
Definition: datetime.h:156
#define DTK_NOW
Definition: datetime.h:154
long val
Definition: informix.c:664
static struct pg_tm tm
Definition: localtime.c:102
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:50
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:48

References ADBC, AM, AMPM, BC, date2j(), DAY, DecodeDate(), DecodeNumber(), DecodeNumberField(), DecodeSpecial(), DecodeTime(), DecodeTimezone(), DecodeTimezoneAbbrev(), DetermineTimeZoneAbbrevOffset(), DetermineTimeZoneOffset(), DOW, dt2time(), DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTK_ALL_SECS_M, DTK_DATE, DTK_DATE_M, DTK_DAY, DTK_HOUR, DTK_JULIAN, DTK_M, DTK_MINUTE, DTK_MONTH, DTK_NOW, DTK_NUMBER, DTK_SECOND, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TIME_M, DTK_TODAY, DTK_TOMORROW, DTK_TZ, DTK_YEAR, DTK_YESTERDAY, DTK_ZULU, DTZ, DTZMOD, DYNTZ, ereport, errcode(), errmsg(), ERROR, GetCurrentDateTime(), GetCurrentTimeUsec(), HOUR, HOURS_PER_DAY, HR24, i, IGNORE_DTF, INTERVAL_FULL_RANGE, ISOTIME, j2date(), MINUTE, MONTH, ParseFraction(), ParseFractionalSecond(), pg_tzset(), PM, RESERV, SECOND, 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 YEAR.

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

3335 {
3336  bool force_negative = false;
3337  bool is_before = false;
3338  char *cp;
3339  int fmask = 0,
3340  tmask,
3341  type,
3342  uval;
3343  int i;
3344  int dterr;
3345  int64 val;
3346  double fval;
3347 
3348  *dtype = DTK_DELTA;
3349  type = IGNORE_DTF;
3350  ClearPgItmIn(itm_in);
3351 
3352  /*----------
3353  * The SQL standard defines the interval literal
3354  * '-1 1:00:00'
3355  * to mean "negative 1 days and negative 1 hours", while Postgres
3356  * traditionally treats this as meaning "negative 1 days and positive
3357  * 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
3358  * to all fields if there are no other explicit signs.
3359  *
3360  * We leave the signs alone if there are additional explicit signs.
3361  * This protects us against misinterpreting postgres-style dump output,
3362  * since the postgres-style output code has always put an explicit sign on
3363  * all fields following a negative field. But note that SQL-spec output
3364  * is ambiguous and can be misinterpreted on load! (So it's best practice
3365  * to dump in postgres style, not SQL style.)
3366  *----------
3367  */
3368  if (IntervalStyle == INTSTYLE_SQL_STANDARD && *field[0] == '-')
3369  {
3370  force_negative = true;
3371  /* Check for additional explicit signs */
3372  for (i = 1; i < nf; i++)
3373  {
3374  if (*field[i] == '-' || *field[i] == '+')
3375  {
3376  force_negative = false;
3377  break;
3378  }
3379  }
3380  }
3381 
3382  /* read through list backwards to pick up units before values */
3383  for (i = nf - 1; i >= 0; i--)
3384  {
3385  switch (ftype[i])
3386  {
3387  case DTK_TIME:
3388  dterr = DecodeTimeForInterval(field[i], fmask, range,
3389  &tmask, itm_in);
3390  if (dterr)
3391  return dterr;
3392  if (force_negative &&
3393  itm_in->tm_usec > 0)
3394  itm_in->tm_usec = -itm_in->tm_usec;
3395  type = DTK_DAY;
3396  break;
3397 
3398  case DTK_TZ:
3399 
3400  /*
3401  * Timezone means a token with a leading sign character and at
3402  * least one digit; there could be ':', '.', '-' embedded in
3403  * it as well.
3404  */
3405  Assert(*field[i] == '-' || *field[i] == '+');
3406 
3407  /*
3408  * Check for signed hh:mm or hh:mm:ss. If so, process exactly
3409  * like DTK_TIME case above, plus handling the sign.
3410  */
3411  if (strchr(field[i] + 1, ':') != NULL &&
3412  DecodeTimeForInterval(field[i] + 1, fmask, range,
3413  &tmask, itm_in) == 0)
3414  {
3415  if (*field[i] == '-')
3416  {
3417  /* flip the sign on time field */
3418  if (itm_in->tm_usec == PG_INT64_MIN)
3419  return DTERR_FIELD_OVERFLOW;
3420  itm_in->tm_usec = -itm_in->tm_usec;
3421  }
3422 
3423  if (force_negative &&
3424  itm_in->tm_usec > 0)
3425  itm_in->tm_usec = -itm_in->tm_usec;
3426 
3427  /*
3428  * Set the next type to be a day, if units are not
3429  * specified. This handles the case of '1 +02:03' since we
3430  * are reading right to left.
3431  */
3432  type = DTK_DAY;
3433  break;
3434  }
3435 
3436  /*
3437  * Otherwise, fall through to DTK_NUMBER case, which can
3438  * handle signed float numbers and signed year-month values.
3439  */
3440 
3441  /* FALLTHROUGH */
3442 
3443  case DTK_DATE:
3444  case DTK_NUMBER:
3445  if (type == IGNORE_DTF)
3446  {
3447  /* use typmod to decide what rightmost field is */
3448  switch (range)
3449  {
3450  case INTERVAL_MASK(YEAR):
3451  type = DTK_YEAR;
3452  break;
3453  case INTERVAL_MASK(MONTH):
3455  type = DTK_MONTH;
3456  break;
3457  case INTERVAL_MASK(DAY):
3458  type = DTK_DAY;
3459  break;
3460  case INTERVAL_MASK(HOUR):
3462  type = DTK_HOUR;
3463  break;
3464  case INTERVAL_MASK(MINUTE):
3467  type = DTK_MINUTE;
3468  break;
3469  case INTERVAL_MASK(SECOND):
3473  type = DTK_SECOND;
3474  break;
3475  default:
3476  type = DTK_SECOND;
3477  break;
3478  }
3479  }
3480 
3481  errno = 0;
3482  val = strtoi64(field[i], &cp, 10);
3483  if (errno == ERANGE)
3484  return DTERR_FIELD_OVERFLOW;
3485 
3486  if (*cp == '-')
3487  {
3488  /* SQL "years-months" syntax */
3489  int val2;
3490 
3491  val2 = strtoint(cp + 1, &cp, 10);
3492  if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
3493  return DTERR_FIELD_OVERFLOW;
3494  if (*cp != '\0')
3495  return DTERR_BAD_FORMAT;
3496  type = DTK_MONTH;
3497  if (*field[i] == '-')
3498  val2 = -val2;
3500  return DTERR_FIELD_OVERFLOW;
3501  if (pg_add_s64_overflow(val, val2, &val))
3502  return DTERR_FIELD_OVERFLOW;
3503  fval = 0;
3504  }
3505  else if (*cp == '.')
3506  {
3507  dterr = ParseFraction(cp, &fval);
3508  if (dterr)
3509  return dterr;
3510  if (*field[i] == '-')
3511  fval = -fval;
3512  }
3513  else if (*cp == '\0')
3514  fval = 0;
3515  else
3516  return DTERR_BAD_FORMAT;
3517 
3518  tmask = 0; /* DTK_M(type); */
3519 
3520  if (force_negative)
3521  {
3522  /* val and fval should be of same sign, but test anyway */
3523  if (val > 0)
3524  val = -val;
3525  if (fval > 0)
3526  fval = -fval;
3527  }
3528 
3529  switch (type)
3530  {
3531  case DTK_MICROSEC:
3532  if (!AdjustMicroseconds(val, fval, 1, itm_in))
3533  return DTERR_FIELD_OVERFLOW;
3534  tmask = DTK_M(MICROSECOND);
3535  break;
3536 
3537  case DTK_MILLISEC:
3538  if (!AdjustMicroseconds(val, fval, 1000, itm_in))
3539  return DTERR_FIELD_OVERFLOW;
3540  tmask = DTK_M(MILLISECOND);
3541  break;
3542 
3543  case DTK_SECOND:
3544  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3545  return DTERR_FIELD_OVERFLOW;
3546 
3547  /*
3548  * If any subseconds were specified, consider this
3549  * microsecond and millisecond input as well.
3550  */
3551  if (fval == 0)
3552  tmask = DTK_M(SECOND);
3553  else
3554  tmask = DTK_ALL_SECS_M;
3555  break;
3556 
3557  case DTK_MINUTE:
3558  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3559  return DTERR_FIELD_OVERFLOW;
3560  tmask = DTK_M(MINUTE);
3561  break;
3562 
3563  case DTK_HOUR:
3564  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3565  return DTERR_FIELD_OVERFLOW;
3566  tmask = DTK_M(HOUR);
3567  type = DTK_DAY; /* set for next field */
3568  break;
3569 
3570  case DTK_DAY:
3571  if (!AdjustDays(val, 1, itm_in) ||
3572  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3573  return DTERR_FIELD_OVERFLOW;
3574  tmask = DTK_M(DAY);
3575  break;
3576 
3577  case DTK_WEEK:
3578  if (!AdjustDays(val, 7, itm_in) ||
3579  !AdjustFractDays(fval, 7, itm_in))
3580  return DTERR_FIELD_OVERFLOW;
3581  tmask = DTK_M(WEEK);
3582  break;
3583 
3584  case DTK_MONTH:
3585  if (!AdjustMonths(val, itm_in) ||
3586  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3587  return DTERR_FIELD_OVERFLOW;
3588  tmask = DTK_M(MONTH);
3589  break;
3590 
3591  case DTK_YEAR:
3592  if (!AdjustYears(val, 1, itm_in) ||
3593  !AdjustFractYears(fval, 1, itm_in))
3594  return DTERR_FIELD_OVERFLOW;
3595  tmask = DTK_M(YEAR);
3596  break;
3597 
3598  case DTK_DECADE:
3599  if (!AdjustYears(val, 10, itm_in) ||
3600  !AdjustFractYears(fval, 10, itm_in))
3601  return DTERR_FIELD_OVERFLOW;
3602  tmask = DTK_M(DECADE);
3603  break;
3604 
3605  case DTK_CENTURY:
3606  if (!AdjustYears(val, 100, itm_in) ||
3607  !AdjustFractYears(fval, 100, itm_in))
3608  return DTERR_FIELD_OVERFLOW;
3609  tmask = DTK_M(CENTURY);
3610  break;
3611 
3612  case DTK_MILLENNIUM:
3613  if (!AdjustYears(val, 1000, itm_in) ||
3614  !AdjustFractYears(fval, 1000, itm_in))
3615  return DTERR_FIELD_OVERFLOW;
3616  tmask = DTK_M(MILLENNIUM);
3617  break;
3618 
3619  default:
3620  return DTERR_BAD_FORMAT;
3621  }
3622  break;
3623 
3624  case DTK_STRING:
3625  case DTK_SPECIAL:
3626  type = DecodeUnits(i, field[i], &uval);
3627  if (type == IGNORE_DTF)
3628  continue;
3629 
3630  tmask = 0; /* DTK_M(type); */
3631  switch (type)
3632  {
3633  case UNITS:
3634  type = uval;
3635  break;
3636 
3637  case AGO:
3638  is_before = true;
3639  type = uval;
3640  break;
3641 
3642  case RESERV:
3643  tmask = (DTK_DATE_M | DTK_TIME_M);
3644  *dtype = uval;
3645  break;
3646 
3647  default:
3648  return DTERR_BAD_FORMAT;
3649  }
3650  break;
3651 
3652  default:
3653  return DTERR_BAD_FORMAT;
3654  }
3655 
3656  if (tmask & fmask)
3657  return DTERR_BAD_FORMAT;
3658  fmask |= tmask;
3659  }
3660 
3661  /* ensure that at least one time field has been found */
3662  if (fmask == 0)
3663  return DTERR_BAD_FORMAT;
3664 
3665  /* finally, AGO negates everything */
3666  if (is_before)
3667  {
3668  if (itm_in->tm_usec == PG_INT64_MIN ||
3669  itm_in->tm_mday == INT_MIN ||
3670  itm_in->tm_mon == INT_MIN ||
3671  itm_in->tm_year == INT_MIN)
3672  return DTERR_FIELD_OVERFLOW;
3673 
3674  itm_in->tm_usec = -itm_in->tm_usec;
3675  itm_in->tm_mday = -itm_in->tm_mday;
3676  itm_in->tm_mon = -itm_in->tm_mon;
3677  itm_in->tm_year = -itm_in->tm_year;
3678  }
3679 
3680  return 0;
3681 }
static bool AdjustDays(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:631
static bool AdjustFractYears(double frac, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:599
static bool AdjustMicroseconds(int64 val, double fval, int64 scale, struct pg_itm_in *itm_in)
Definition: datetime.c:616
static int DecodeTimeForInterval(char *str, int fmask, int range, int *tmask, struct pg_itm_in *itm_in)
Definition: datetime.c:2841
static bool AdjustFractMicroseconds(double frac, int64 scale, struct pg_itm_in *itm_in)
Definition: datetime.c:535
static bool AdjustYears(int64 val, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:659
static bool AdjustMonths(int64 val, struct pg_itm_in *itm_in)
Definition: datetime.c:647
int DecodeUnits(int field, char *lowtoken, int *val)
Definition: datetime.c:3987
static bool AdjustFractDays(double frac, int scale, struct pg_itm_in *itm_in)
Definition: datetime.c:567
static void ClearPgItmIn(struct pg_itm_in *itm_in)
Definition: datetime.c:3312
#define strtoi64(str, endptr, base)
Definition: c.h:1321
#define PG_INT64_MIN
Definition: c.h:526
#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:121
#define DTK_DECADE
Definition: datetime.h:169
#define DTK_DELTA
Definition: datetime.h:160
#define MICROSECOND
Definition: datetime.h:105
#define WEEK
Definition: datetime.h:118
#define DECADE
Definition: datetime.h:119
#define DTK_CENTURY
Definition: datetime.h:170
#define MILLISECOND
Definition: datetime.h:104
#define CENTURY
Definition: datetime.h:120
#define DTK_MILLENNIUM
Definition: datetime.h:171
#define DTK_WEEK
Definition: datetime.h:165
#define DTK_MICROSEC
Definition: datetime.h:173
#define AGO
Definition: datetime.h:111
#define DTK_MILLISEC
Definition: datetime.h:172
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:45

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

3771 {
3772  bool datepart = true;
3773  bool havefield = false;
3774 
3775  *dtype = DTK_DELTA;
3776  ClearPgItmIn(itm_in);
3777 
3778  if (strlen(str) < 2 || str[0] != 'P')
3779  return DTERR_BAD_FORMAT;
3780 
3781  str++;
3782  while (*str)
3783  {
3784  char *fieldstart;
3785  int64 val;
3786  double fval;
3787  char unit;
3788  int dterr;
3789 
3790  if (*str == 'T') /* T indicates the beginning of the time part */
3791  {
3792  datepart = false;
3793  havefield = false;
3794  str++;
3795  continue;
3796  }
3797 
3798  fieldstart = str;
3799  dterr = ParseISO8601Number(str, &str, &val, &fval);
3800  if (dterr)
3801  return dterr;
3802 
3803  /*
3804  * Note: we could step off the end of the string here. Code below
3805  * *must* exit the loop if unit == '\0'.
3806  */
3807  unit = *str++;
3808 
3809  if (datepart)
3810  {
3811  switch (unit) /* before T: Y M W D */
3812  {
3813  case 'Y':
3814  if (!AdjustYears(val, 1, itm_in) ||
3815  !AdjustFractYears(fval, 1, itm_in))
3816  return DTERR_FIELD_OVERFLOW;
3817  break;
3818  case 'M':
3819  if (!AdjustMonths(val, itm_in) ||
3820  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3821  return DTERR_FIELD_OVERFLOW;
3822  break;
3823  case 'W':
3824  if (!AdjustDays(val, 7, itm_in) ||
3825  !AdjustFractDays(fval, 7, itm_in))
3826  return DTERR_FIELD_OVERFLOW;
3827  break;
3828  case 'D':
3829  if (!AdjustDays(val, 1, itm_in) ||
3830  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3831  return DTERR_FIELD_OVERFLOW;
3832  break;
3833  case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
3834  case '\0':
3835  if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
3836  {
3837  if (!AdjustYears(val / 10000, 1, itm_in) ||
3838  !AdjustMonths((val / 100) % 100, itm_in) ||
3839  !AdjustDays(val % 100, 1, itm_in) ||
3840  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3841  return DTERR_FIELD_OVERFLOW;
3842  if (unit == '\0')
3843  return 0;
3844  datepart = false;
3845  havefield = false;
3846  continue;
3847  }
3848  /* Else fall through to extended alternative format */
3849  /* FALLTHROUGH */
3850  case '-': /* ISO 8601 4.4.3.3 Alternative Format,
3851  * Extended */
3852  if (havefield)
3853  return DTERR_BAD_FORMAT;
3854 
3855  if (!AdjustYears(val, 1, itm_in) ||
3856  !AdjustFractYears(fval, 1, itm_in))
3857  return DTERR_FIELD_OVERFLOW;
3858  if (unit == '\0')
3859  return 0;
3860  if (unit == 'T')
3861  {
3862  datepart = false;
3863  havefield = false;
3864  continue;
3865  }
3866 
3867  dterr = ParseISO8601Number(str, &str, &val, &fval);
3868  if (dterr)
3869  return dterr;
3870  if (!AdjustMonths(val, itm_in) ||
3871  !AdjustFractDays(fval, DAYS_PER_MONTH, itm_in))
3872  return DTERR_FIELD_OVERFLOW;
3873  if (*str == '\0')
3874  return 0;
3875  if (*str == 'T')
3876  {
3877  datepart = false;
3878  havefield = false;
3879  continue;
3880  }
3881  if (*str != '-')
3882  return DTERR_BAD_FORMAT;
3883  str++;
3884 
3885  dterr = ParseISO8601Number(str, &str, &val, &fval);
3886  if (dterr)
3887  return dterr;
3888  if (!AdjustDays(val, 1, itm_in) ||
3889  !AdjustFractMicroseconds(fval, USECS_PER_DAY, itm_in))
3890  return DTERR_FIELD_OVERFLOW;
3891  if (*str == '\0')
3892  return 0;
3893  if (*str == 'T')
3894  {
3895  datepart = false;
3896  havefield = false;
3897  continue;
3898  }
3899  return DTERR_BAD_FORMAT;
3900  default:
3901  /* not a valid date unit suffix */
3902  return DTERR_BAD_FORMAT;
3903  }
3904  }
3905  else
3906  {
3907  switch (unit) /* after T: H M S */
3908  {
3909  case 'H':
3910  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3911  return DTERR_FIELD_OVERFLOW;
3912  break;
3913  case 'M':
3914  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3915  return DTERR_FIELD_OVERFLOW;
3916  break;
3917  case 'S':
3918  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3919  return DTERR_FIELD_OVERFLOW;
3920  break;
3921  case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
3922  if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
3923  {
3924  if (!AdjustMicroseconds(val / 10000, 0, USECS_PER_HOUR, itm_in) ||
3925  !AdjustMicroseconds((val / 100) % 100, 0, USECS_PER_MINUTE, itm_in) ||
3926  !AdjustMicroseconds(val % 100, 0, USECS_PER_SEC, itm_in) ||
3927  !AdjustFractMicroseconds(fval, 1, itm_in))
3928  return DTERR_FIELD_OVERFLOW;
3929  return 0;
3930  }
3931  /* Else fall through to extended alternative format */
3932  /* FALLTHROUGH */
3933  case ':': /* ISO 8601 4.4.3.3 Alternative Format,
3934  * Extended */
3935  if (havefield)
3936  return DTERR_BAD_FORMAT;
3937 
3938  if (!AdjustMicroseconds(val, fval, USECS_PER_HOUR, itm_in))
3939  return DTERR_FIELD_OVERFLOW;
3940  if (unit == '\0')
3941  return 0;
3942 
3943  dterr = ParseISO8601Number(str, &str, &val, &fval);
3944  if (dterr)
3945  return dterr;
3946  if (!AdjustMicroseconds(val, fval, USECS_PER_MINUTE, itm_in))
3947  return DTERR_FIELD_OVERFLOW;
3948  if (*str == '\0')
3949  return 0;
3950  if (*str != ':')
3951  return DTERR_BAD_FORMAT;
3952  str++;
3953 
3954  dterr = ParseISO8601Number(str, &str, &val, &fval);
3955  if (dterr)
3956  return dterr;
3957  if (!AdjustMicroseconds(val, fval, USECS_PER_SEC, itm_in))
3958  return DTERR_FIELD_OVERFLOW;
3959  if (*str == '\0')
3960  return 0;
3961  return DTERR_BAD_FORMAT;
3962 
3963  default:
3964  /* not a valid time unit suffix */
3965  return DTERR_BAD_FORMAT;
3966  }
3967  }
3968 
3969  havefield = true;
3970  }
3971 
3972  return 0;
3973 }
static int ISO8601IntegerWidth(char *fieldstart)
Definition: datetime.c:3742
static int ParseISO8601Number(char *str, char **endptr, int64 *ipart, double *fpart)
Definition: datetime.c:3692

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,
char *  lowtoken,
int *  val 
)

Definition at line 3280 of file datetime.c.

3281 {
3282  int type;
3283  const datetkn *tp;
3284 
3285  tp = datecache[field];
3286  /* use strncmp so that we match truncated tokens */
3287  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3288  {
3289  tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
3290  }
3291  if (tp == NULL)
3292  {
3293  type = UNKNOWN_FIELD;
3294  *val = 0;
3295  }
3296  else
3297  {
3298  datecache[field] = tp;
3299  type = tp->type;
3300  *val = tp->value;
3301  }
3302 
3303  return type;
3304 }
static const datetkn * datecache[MAXDATEFIELDS]
Definition: datetime.c:256
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:4069

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 
)

Definition at line 1923 of file datetime.c.

1925 {
1926  int fmask = 0,
1927  tmask,
1928  type;
1929  int ptype = 0; /* "prefix type" for ISO h04mm05s06 format */
1930  int i;
1931  int val;
1932  int dterr;
1933  bool isjulian = false;
1934  bool is2digits = false;
1935  bool bc = false;
1936  int mer = HR24;
1937  pg_tz *namedTz = NULL;
1938  pg_tz *abbrevTz = NULL;
1939  char *abbrev = NULL;
1940  pg_tz *valtz;
1941 
1942  *dtype = DTK_TIME;
1943  tm->tm_hour = 0;
1944  tm->tm_min = 0;
1945  tm->tm_sec = 0;
1946  *fsec = 0;
1947  /* don't know daylight savings time status apriori */
1948  tm->tm_isdst = -1;
1949 
1950  if (tzp != NULL)
1951  *tzp = 0;
1952 
1953  for (i = 0; i < nf; i++)
1954  {
1955  switch (ftype[i])
1956  {
1957  case DTK_DATE:
1958 
1959  /*
1960  * Time zone not allowed? Then should not accept dates or time
1961  * zones no matter what else!
1962  */
1963  if (tzp == NULL)
1964  return DTERR_BAD_FORMAT;
1965 
1966  /* Under limited circumstances, we will accept a date... */
1967  if (i == 0 && nf >= 2 &&
1968  (ftype[nf - 1] == DTK_DATE || ftype[1] == DTK_TIME))
1969  {
1970  dterr = DecodeDate(field[i], fmask,
1971  &tmask, &is2digits, tm);
1972  if (dterr)
1973  return dterr;
1974  }
1975  /* otherwise, this is a time and/or time zone */
1976  else
1977  {
1978  if (isdigit((unsigned char) *field[i]))
1979  {
1980  char *cp;
1981 
1982  /*
1983  * Starts with a digit but we already have a time
1984  * field? Then we are in trouble with time already...
1985  */
1986  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1987  return DTERR_BAD_FORMAT;
1988 
1989  /*
1990  * Should not get here and fail. Sanity check only...
1991  */
1992  if ((cp = strchr(field[i], '-')) == NULL)
1993  return DTERR_BAD_FORMAT;
1994 
1995  /* Get the time zone from the end of the string */
1996  dterr = DecodeTimezone(cp, tzp);
1997  if (dterr)
1998  return dterr;
1999  *cp = '\0';
2000 
2001  /*
2002  * Then read the rest of the field as a concatenated
2003  * time
2004  */
2005  dterr = DecodeNumberField(strlen(field[i]), field[i],
2006  (fmask | DTK_DATE_M),
2007  &tmask, tm,
2008  fsec, &is2digits);
2009  if (dterr < 0)
2010  return dterr;
2011  ftype[i] = dterr;
2012 
2013  tmask |= DTK_M(TZ);
2014  }
2015  else
2016  {
2017  namedTz = pg_tzset(field[i]);
2018  if (!namedTz)
2019  {
2020  /*
2021  * We should return an error code instead of
2022  * ereport'ing directly, but then there is no way
2023  * to report the bad time zone name.
2024  */
2025  ereport(ERROR,
2026  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2027  errmsg("time zone \"%s\" not recognized",
2028  field[i])));
2029  }
2030  /* we'll apply the zone setting below */
2031  ftype[i] = DTK_TZ;
2032  tmask = DTK_M(TZ);
2033  }
2034  }
2035  break;
2036 
2037  case DTK_TIME:
2038  dterr = DecodeTime(field[i], (fmask | DTK_DATE_M),
2040  &tmask, tm, fsec);
2041  if (dterr)
2042  return dterr;
2043  break;
2044 
2045  case DTK_TZ:
2046  {
2047  int tz;
2048 
2049  if (tzp == NULL)
2050  return DTERR_BAD_FORMAT;
2051 
2052  dterr = DecodeTimezone(field[i], &tz);
2053  if (dterr)
2054  return dterr;
2055  *tzp = tz;
2056  tmask = DTK_M(TZ);
2057  }
2058  break;
2059 
2060  case DTK_NUMBER:
2061 
2062  /*
2063  * Was this an "ISO time" with embedded field labels? An
2064  * example is "h04mm05s06" - thomas 2001-02-04
2065  */
2066  if (ptype != 0)
2067  {
2068  char *cp;
2069  int val;
2070 
2071  /* Only accept a date under limited circumstances */
2072  switch (ptype)
2073  {
2074  case DTK_JULIAN:
2075  case DTK_YEAR:
2076  case DTK_MONTH:
2077  case DTK_DAY:
2078  if (tzp == NULL)
2079  return DTERR_BAD_FORMAT;
2080  default:
2081  break;
2082  }
2083 
2084  errno = 0;
2085  val = strtoint(field[i], &cp, 10);
2086  if (errno == ERANGE)
2087  return DTERR_FIELD_OVERFLOW;
2088 
2089  /*
2090  * only a few kinds are allowed to have an embedded
2091  * decimal
2092  */
2093  if (*cp == '.')
2094  switch (ptype)
2095  {
2096  case DTK_JULIAN:
2097  case DTK_TIME:
2098  case DTK_SECOND:
2099  break;
2100  default:
2101  return DTERR_BAD_FORMAT;
2102  break;
2103  }
2104  else if (*cp != '\0')
2105  return DTERR_BAD_FORMAT;
2106 
2107  switch (ptype)
2108  {
2109  case DTK_YEAR:
2110  tm->tm_year = val;
2111  tmask = DTK_M(YEAR);
2112  break;
2113 
2114  case DTK_MONTH:
2115 
2116  /*
2117  * already have a month and hour? then assume
2118  * minutes
2119  */
2120  if ((fmask & DTK_M(MONTH)) != 0 &&
2121  (fmask & DTK_M(HOUR)) != 0)
2122  {
2123  tm->tm_min = val;
2124  tmask = DTK_M(MINUTE);
2125  }
2126  else
2127  {
2128  tm->tm_mon = val;
2129  tmask = DTK_M(MONTH);
2130  }
2131  break;
2132 
2133  case DTK_DAY:
2134  tm->tm_mday = val;
2135  tmask = DTK_M(DAY);
2136  break;
2137 
2138  case DTK_HOUR:
2139  tm->tm_hour = val;
2140  tmask = DTK_M(HOUR);
2141  break;
2142 
2143  case DTK_MINUTE:
2144  tm->tm_min = val;
2145  tmask = DTK_M(MINUTE);
2146  break;
2147 
2148  case DTK_SECOND:
2149  tm->tm_sec = val;
2150  tmask = DTK_M(SECOND);
2151  if (*cp == '.')
2152  {
2153  dterr = ParseFractionalSecond(cp, fsec);
2154  if (dterr)
2155  return dterr;
2156  tmask = DTK_ALL_SECS_M;
2157  }
2158  break;
2159 
2160  case DTK_TZ:
2161  tmask = DTK_M(TZ);
2162  dterr = DecodeTimezone(field[i], tzp);
2163  if (dterr)
2164  return dterr;
2165  break;
2166 
2167  case DTK_JULIAN:
2168  /* previous field was a label for "julian date" */
2169  if (val < 0)
2170  return DTERR_FIELD_OVERFLOW;
2171  tmask = DTK_DATE_M;
2172  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2173  isjulian = true;
2174 
2175  if (*cp == '.')
2176  {
2177  double time;
2178 
2179  dterr = ParseFraction(cp, &time);
2180  if (dterr)
2181  return dterr;
2182  time *= USECS_PER_DAY;
2183  dt2time(time,
2184  &tm->tm_hour, &tm->tm_min,
2185  &tm->tm_sec, fsec);
2186  tmask |= DTK_TIME_M;
2187  }
2188  break;
2189 
2190  case DTK_TIME:
2191  /* previous field was "t" for ISO time */
2192  dterr = DecodeNumberField(strlen(field[i]), field[i],
2193  (fmask | DTK_DATE_M),
2194  &tmask, tm,
2195  fsec, &is2digits);
2196  if (dterr < 0)
2197  return dterr;
2198  ftype[i] = dterr;
2199 
2200  if (tmask != DTK_TIME_M)
2201  return DTERR_BAD_FORMAT;
2202  break;
2203 
2204  default:
2205  return DTERR_BAD_FORMAT;
2206  break;
2207  }
2208 
2209  ptype = 0;
2210  *dtype = DTK_DATE;
2211  }
2212  else
2213  {
2214  char *cp;
2215  int flen;
2216 
2217  flen = strlen(field[i]);
2218  cp = strchr(field[i], '.');
2219 
2220  /* Embedded decimal? */
2221  if (cp != NULL)
2222  {
2223  /*
2224  * Under limited circumstances, we will accept a
2225  * date...
2226  */
2227  if (i == 0 && nf >= 2 && ftype[nf - 1] == DTK_DATE)
2228  {
2229  dterr = DecodeDate(field[i], fmask,
2230  &tmask, &is2digits, tm);
2231  if (dterr)
2232  return dterr;
2233  }
2234  /* embedded decimal and several digits before? */
2235  else if (flen - strlen(cp) > 2)
2236  {
2237  /*
2238  * Interpret as a concatenated date or time Set
2239  * the type field to allow decoding other fields
2240  * later. Example: 20011223 or 040506
2241  */
2242  dterr = DecodeNumberField(flen, field[i],
2243  (fmask | DTK_DATE_M),
2244  &tmask, tm,
2245  fsec, &is2digits);
2246  if (dterr < 0)
2247  return dterr;
2248  ftype[i] = dterr;
2249  }
2250  else
2251  return DTERR_BAD_FORMAT;
2252  }
2253  else if (flen > 4)
2254  {
2255  dterr = DecodeNumberField(flen, field[i],
2256  (fmask | DTK_DATE_M),
2257  &tmask, tm,
2258  fsec, &is2digits);
2259  if (dterr < 0)
2260  return dterr;
2261  ftype[i] = dterr;
2262  }
2263  /* otherwise it is a single date/time field... */
2264  else
2265  {
2266  dterr = DecodeNumber(flen, field[i],
2267  false,
2268  (fmask | DTK_DATE_M),
2269  &tmask, tm,
2270  fsec, &is2digits);
2271  if (dterr)
2272  return dterr;
2273  }
2274  }
2275  break;
2276 
2277  case DTK_STRING:
2278  case DTK_SPECIAL:
2279  /* timezone abbrevs take precedence over built-in tokens */
2280  type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
2281  if (type == UNKNOWN_FIELD)
2282  type = DecodeSpecial(i, field[i], &val);
2283  if (type == IGNORE_DTF)
2284  continue;
2285 
2286  tmask = DTK_M(type);
2287  switch (type)
2288  {
2289  case RESERV:
2290  switch (val)
2291  {
2292  case DTK_NOW:
2293  tmask = DTK_TIME_M;
2294  *dtype = DTK_TIME;
2295  GetCurrentTimeUsec(tm, fsec, NULL);
2296  break;
2297 
2298  case DTK_ZULU:
2299  tmask = (DTK_TIME_M | DTK_M(TZ));
2300  *dtype = DTK_TIME;
2301  tm->tm_hour = 0;
2302  tm->tm_min = 0;
2303  tm->tm_sec = 0;
2304  tm->tm_isdst = 0;
2305  break;
2306 
2307  default:
2308  return DTERR_BAD_FORMAT;
2309  }
2310 
2311  break;
2312 
2313  case DTZMOD:
2314 
2315  /*
2316  * daylight savings time modifier (solves "MET DST"
2317  * syntax)
2318  */
2319  tmask |= DTK_M(DTZ);
2320  tm->tm_isdst = 1;
2321  if (tzp == NULL)
2322  return DTERR_BAD_FORMAT;
2323  *tzp -= val;
2324  break;
2325 
2326  case DTZ:
2327 
2328  /*
2329  * set mask for TZ here _or_ check for DTZ later when
2330  * getting default timezone
2331  */
2332  tmask |= DTK_M(TZ);
2333  tm->tm_isdst = 1;
2334  if (tzp == NULL)
2335  return DTERR_BAD_FORMAT;
2336  *tzp = -val;
2337  ftype[i] = DTK_TZ;
2338  break;
2339 
2340  case TZ:
2341  tm->tm_isdst = 0;
2342  if (tzp == NULL)
2343  return DTERR_BAD_FORMAT;
2344  *tzp = -val;
2345  ftype[i] = DTK_TZ;
2346  break;
2347 
2348  case DYNTZ:
2349  tmask |= DTK_M(TZ);
2350  if (tzp == NULL)
2351  return DTERR_BAD_FORMAT;
2352  /* we'll determine the actual offset later */
2353  abbrevTz = valtz;
2354  abbrev = field[i];
2355  ftype[i] = DTK_TZ;
2356  break;
2357 
2358  case AMPM:
2359  mer = val;
2360  break;
2361 
2362  case ADBC:
2363  bc = (val == BC);
2364  break;
2365 
2366  case UNITS:
2367  tmask = 0;
2368  ptype = val;
2369  break;
2370 
2371  case ISOTIME:
2372  tmask = 0;
2373 
2374  /***
2375  * We will need one of the following fields:
2376  * DTK_NUMBER should be hhmmss.fff
2377  * DTK_TIME should be hh:mm:ss.fff
2378  * DTK_DATE should be hhmmss-zz
2379  ***/
2380  if (i >= nf - 1 ||
2381  (ftype[i + 1] != DTK_NUMBER &&
2382  ftype[i + 1] != DTK_TIME &&
2383  ftype[i + 1] != DTK_DATE))
2384  return DTERR_BAD_FORMAT;
2385 
2386  ptype = val;
2387  break;
2388 
2389  case UNKNOWN_FIELD:
2390 
2391  /*
2392  * Before giving up and declaring error, check to see
2393  * if it is an all-alpha timezone name.
2394  */
2395  namedTz = pg_tzset(field[i]);
2396  if (!namedTz)
2397  return DTERR_BAD_FORMAT;
2398  /* we'll apply the zone setting below */
2399  tmask = DTK_M(TZ);
2400  break;
2401 
2402  default:
2403  return DTERR_BAD_FORMAT;
2404  }
2405  break;
2406 
2407  default:
2408  return DTERR_BAD_FORMAT;
2409  }
2410 
2411  if (tmask & fmask)
2412  return DTERR_BAD_FORMAT;
2413  fmask |= tmask;
2414  } /* end loop over fields */
2415 
2416  /* do final checking/adjustment of Y/M/D fields */
2417  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
2418  if (dterr)
2419  return dterr;
2420 
2421  /* handle AM/PM */
2422  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
2423  return DTERR_FIELD_OVERFLOW;
2424  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
2425  tm->tm_hour = 0;
2426  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
2427  tm->tm_hour += HOURS_PER_DAY / 2;
2428 
2429  /* check for time overflow */
2430  if (time_overflows(tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec))
2431  return DTERR_FIELD_OVERFLOW;
2432 
2433  if ((fmask & DTK_TIME_M) != DTK_TIME_M)
2434  return DTERR_BAD_FORMAT;
2435 
2436  /*
2437  * If we had a full timezone spec, compute the offset (we could not do it
2438  * before, because we may need the date to resolve DST status).
2439  */
2440  if (namedTz != NULL)
2441  {
2442  long int gmtoff;
2443 
2444  /* daylight savings time modifier disallowed with full TZ */
2445  if (fmask & DTK_M(DTZMOD))
2446  return DTERR_BAD_FORMAT;
2447 
2448  /* if non-DST zone, we do not need to know the date */
2449  if (pg_get_timezone_offset(namedTz, &gmtoff))
2450  {
2451  *tzp = -(int) gmtoff;
2452  }
2453  else
2454  {
2455  /* a date has to be specified */
2456  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2457  return DTERR_BAD_FORMAT;
2458  *tzp = DetermineTimeZoneOffset(tm, namedTz);
2459  }
2460  }
2461 
2462  /*
2463  * Likewise, if we had a dynamic timezone abbreviation, resolve it now.
2464  */
2465  if (abbrevTz != NULL)
2466  {
2467  struct pg_tm tt,
2468  *tmp = &tt;
2469 
2470  /*
2471  * daylight savings time modifier but no standard timezone? then error
2472  */
2473  if (fmask & DTK_M(DTZMOD))
2474  return DTERR_BAD_FORMAT;
2475 
2476  if ((fmask & DTK_DATE_M) == 0)
2477  GetCurrentDateTime(tmp);
2478  else
2479  {
2480  /* a date has to be specified */
2481  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2482  return DTERR_BAD_FORMAT;
2483  tmp->tm_year = tm->tm_year;
2484  tmp->tm_mon = tm->tm_mon;
2485  tmp->tm_mday = tm->tm_mday;
2486  }
2487  tmp->tm_hour = tm->tm_hour;
2488  tmp->tm_min = tm->tm_min;
2489  tmp->tm_sec = tm->tm_sec;
2490  *tzp = DetermineTimeZoneAbbrevOffset(tmp, abbrev, abbrevTz);
2491  tm->tm_isdst = tmp->tm_isdst;
2492  }
2493 
2494  /* timezone not specified? then use session timezone */
2495  if (tzp != NULL && !(fmask & DTK_M(TZ)))
2496  {
2497  struct pg_tm tt,
2498  *tmp = &tt;
2499 
2500  /*
2501  * daylight savings time modifier but no standard timezone? then error
2502  */
2503  if (fmask & DTK_M(DTZMOD))
2504  return DTERR_BAD_FORMAT;
2505 
2506  if ((fmask & DTK_DATE_M) == 0)
2507  GetCurrentDateTime(tmp);
2508  else
2509  {
2510  /* a date has to be specified */
2511  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2512  return DTERR_BAD_FORMAT;
2513  tmp->tm_year = tm->tm_year;
2514  tmp->tm_mon = tm->tm_mon;
2515  tmp->tm_mday = tm->tm_mday;
2516  }
2517  tmp->tm_hour = tm->tm_hour;
2518  tmp->tm_min = tm->tm_min;
2519  tmp->tm_sec = tm->tm_sec;
2521  tm->tm_isdst = tmp->tm_isdst;
2522  }
2523 
2524  return 0;
2525 }
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c:1849

References ADBC, AM, AMPM, BC, DAY, DecodeDate(), DecodeNumber(), DecodeNumberField(), DecodeSpecial(), DecodeTime(), DecodeTimezone(), DecodeTimezoneAbbrev(), DetermineTimeZoneAbbrevOffset(), DetermineTimeZoneOffset(), dt2time(), DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTK_ALL_SECS_M, DTK_DATE, DTK_DATE_M, DTK_DAY, DTK_HOUR, DTK_JULIAN, DTK_M, DTK_MINUTE, DTK_MONTH, DTK_NOW, DTK_NUMBER, DTK_SECOND, DTK_SPECIAL, DTK_STRING, DTK_TIME, DTK_TIME_M, DTK_TZ, DTK_YEAR, DTK_ZULU, DTZ, DTZMOD, DYNTZ, ereport, errcode(), errmsg(), ERROR, GetCurrentDateTime(), GetCurrentTimeUsec(), HOUR, HOURS_PER_DAY, HR24, i, IGNORE_DTF, INTERVAL_FULL_RANGE, ISOTIME, j2date(), MINUTE, MONTH, ParseFraction(), ParseFractionalSecond(), pg_get_timezone_offset(), pg_tzset(), PM, RESERV, SECOND, 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 YEAR.

Referenced by time_in(), and timetz_in().

◆ DecodeTimezone()

int DecodeTimezone ( char *  str,
int *  tzp 
)

Definition at line 3147 of file datetime.c.

3148 {
3149  int tz;
3150  int hr,
3151  min,
3152  sec = 0;
3153  char *cp;
3154 
3155  /* leading character must be "+" or "-" */
3156  if (*str != '+' && *str != '-')
3157  return DTERR_BAD_FORMAT;
3158 
3159  errno = 0;
3160  hr = strtoint(str + 1, &cp, 10);
3161  if (errno == ERANGE)
3162  return DTERR_TZDISP_OVERFLOW;
3163 
3164  /* explicit delimiter? */
3165  if (*cp == ':')
3166  {
3167  errno = 0;
3168  min = strtoint(cp + 1, &cp, 10);
3169  if (errno == ERANGE)
3170  return DTERR_TZDISP_OVERFLOW;
3171  if (*cp == ':')
3172  {
3173  errno = 0;
3174  sec = strtoint(cp + 1, &cp, 10);
3175  if (errno == ERANGE)
3176  return DTERR_TZDISP_OVERFLOW;
3177  }
3178  }
3179  /* otherwise, might have run things together... */
3180  else if (*cp == '\0' && strlen(str) > 3)
3181  {
3182  min = hr % 100;
3183  hr = hr / 100;
3184  /* we could, but don't, support a run-together hhmmss format */
3185  }
3186  else
3187  min = 0;
3188 
3189  /* Range-check the values; see notes in datatype/timestamp.h */
3190  if (hr < 0 || hr > MAX_TZDISP_HOUR)
3191  return DTERR_TZDISP_OVERFLOW;
3192  if (min < 0 || min >= MINS_PER_HOUR)
3193  return DTERR_TZDISP_OVERFLOW;
3194  if (sec < 0 || sec >= SECS_PER_MINUTE)
3195  return DTERR_TZDISP_OVERFLOW;
3196 
3197  tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
3198  if (*str == '-')
3199  tz = -tz;
3200 
3201  *tzp = -tz;
3202 
3203  if (*cp != '\0')
3204  return DTERR_BAD_FORMAT;
3205 
3206  return 0;
3207 }
#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,
char *  lowtoken,
int *  offset,
pg_tz **  tz 
)

Definition at line 3225 of file datetime.c.

3227 {
3228  int type;
3229  const datetkn *tp;
3230 
3231  tp = abbrevcache[field];
3232  /* use strncmp so that we match truncated tokens */
3233  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3234  {
3235  if (zoneabbrevtbl)
3236  tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
3238  else
3239  tp = NULL;
3240  }
3241  if (tp == NULL)
3242  {
3243  type = UNKNOWN_FIELD;
3244  *offset = 0;
3245  *tz = NULL;
3246  }
3247  else
3248  {
3249  abbrevcache[field] = tp;
3250  type = tp->type;
3251  if (type == DYNTZ)
3252  {
3253  *offset = 0;
3255  }
3256  else
3257  {
3258  *offset = tp->value;
3259  *tz = NULL;
3260  }
3261  }
3262 
3263  return type;
3264 }
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:260
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:252
static pg_tz * FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp)
Definition: datetime.c:4884

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

Referenced by DecodeDateTime(), DecodeTimeOnly(), parse_sane_timezone(), timestamp_zone(), timestamptz_trunc_zone(), timestamptz_zone(), and timetz_zone().

◆ DecodeUnits()

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

Definition at line 3987 of file datetime.c.

3988 {
3989  int type;
3990  const datetkn *tp;
3991 
3992  tp = deltacache[field];
3993  /* use strncmp so that we match truncated tokens */
3994  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3995  {
3996  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3997  }
3998  if (tp == NULL)
3999  {
4000  type = UNKNOWN_FIELD;
4001  *val = 0;
4002  }
4003  else
4004  {
4005  deltacache[field] = tp;
4006  type = tp->type;
4007  *val = tp->value;
4008  }
4009 
4010  return type;
4011 } /* DecodeUnits() */
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:258

◆ DetermineTimeZoneAbbrevOffset()

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

Definition at line 1808 of file datetime.c.

1809 {
1810  pg_time_t t;
1811  int zone_offset;
1812  int abbr_offset;
1813  int abbr_isdst;
1814 
1815  /*
1816  * Compute the UTC time we want to probe at. (In event of overflow, we'll
1817  * probe at the epoch, which is a bit random but probably doesn't matter.)
1818  */
1819  zone_offset = DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1820 
1821  /*
1822  * Try to match the abbreviation to something in the zone definition.
1823  */
1824  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1825  &abbr_offset, &abbr_isdst))
1826  {
1827  /* Success, so use the abbrev-specific answers. */
1828  tm->tm_isdst = abbr_isdst;
1829  return abbr_offset;
1830  }
1831 
1832  /*
1833  * No match, so use the answers we already got from
1834  * DetermineTimeZoneOffsetInternal.
1835  */
1836  return zone_offset;
1837 }
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
Definition: datetime.c:1669
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1883
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 1846 of file datetime.c.

1848 {
1850  int zone_offset;
1851  int abbr_offset;
1852  int tz;
1853  struct pg_tm tm;
1854  fsec_t fsec;
1855 
1856  /*
1857  * If the abbrev matches anything in the zone data, this is pretty easy.
1858  */
1859  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1860  &abbr_offset, isdst))
1861  return abbr_offset;
1862 
1863  /*
1864  * Else, break down the timestamp so we can use DetermineTimeZoneOffset.
1865  */
1866  if (timestamp2tm(ts, &tz, &tm, &fsec, NULL, tzp) != 0)
1867  ereport(ERROR,
1868  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1869  errmsg("timestamp out of range")));
1870 
1871  zone_offset = DetermineTimeZoneOffset(&tm, tzp);
1872  *isdst = tm.tm_isdst;
1873  return zone_offset;
1874 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1816
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1748
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 4143 of file datetime.c.

4144 {
4145  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4146 
4147  switch (style)
4148  {
4149  case USE_ISO_DATES:
4150  case USE_XSD_DATES:
4151  /* compatible with ISO date formats */
4153  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4154  *str++ = '-';
4156  *str++ = '-';
4158  break;
4159 
4160  case USE_SQL_DATES:
4161  /* compatible with Oracle/Ingres date formats */
4162  if (DateOrder == DATEORDER_DMY)
4163  {
4165  *str++ = '/';
4167  }
4168  else
4169  {
4171  *str++ = '/';
4173  }
4174  *str++ = '/';
4176  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4177  break;
4178 
4179  case USE_GERMAN_DATES:
4180  /* German-style date format */
4182  *str++ = '.';
4184  *str++ = '.';
4186  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4187  break;
4188 
4189  case USE_POSTGRES_DATES:
4190  default:
4191  /* traditional date-only style for Postgres */
4192  if (DateOrder == DATEORDER_DMY)
4193  {
4195  *str++ = '-';
4197  }
4198  else
4199  {
4201  *str++ = '-';
4203  }
4204  *str++ = '-';
4206  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4207  break;
4208  }
4209 
4210  if (tm->tm_year <= 0)
4211  {
4212  memcpy(str, " BC", 3); /* Don't copy NUL */
4213  str += 3;
4214  }
4215  *str = '\0';
4216 }
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:559

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

4259 {
4260  int day;
4261 
4262  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
4263 
4264  /*
4265  * Negative tm_isdst means we have no valid time zone translation.
4266  */
4267  if (tm->tm_isdst < 0)
4268  print_tz = false;
4269 
4270  switch (style)
4271  {
4272  case USE_ISO_DATES:
4273  case USE_XSD_DATES:
4274  /* Compatible with ISO-8601 date formats */
4276  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4277  *str++ = '-';
4279  *str++ = '-';
4281  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4283  *str++ = ':';
4285  *str++ = ':';
4286  str = AppendTimestampSeconds(str, tm, fsec);
4287  if (print_tz)
4288  str = EncodeTimezone(str, tz, style);
4289  break;
4290 
4291  case USE_SQL_DATES:
4292  /* Compatible with Oracle/Ingres date formats */
4293  if (DateOrder == DATEORDER_DMY)
4294  {
4296  *str++ = '/';
4298  }
4299  else
4300  {
4302  *str++ = '/';
4304  }
4305  *str++ = '/';
4307  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4308  *str++ = ' ';
4310  *str++ = ':';
4312  *str++ = ':';
4313  str = AppendTimestampSeconds(str, tm, fsec);
4314 
4315  /*
4316  * Note: the uses of %.*s in this function would be risky if the
4317  * timezone names ever contain non-ASCII characters, since we are
4318  * not being careful to do encoding-aware clipping. However, all
4319  * TZ abbreviations in the IANA database are plain ASCII.
4320  */
4321  if (print_tz)
4322  {
4323  if (tzn)
4324  {
4325  sprintf(str, " %.*s", MAXTZLEN, tzn);
4326  str += strlen(str);
4327  }
4328  else
4329  str = EncodeTimezone(str, tz, style);
4330  }
4331  break;
4332 
4333  case USE_GERMAN_DATES:
4334  /* German variant on European style */
4336  *str++ = '.';
4338  *str++ = '.';
4340  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4341  *str++ = ' ';
4343  *str++ = ':';
4345  *str++ = ':';
4346  str = AppendTimestampSeconds(str, tm, fsec);
4347 
4348  if (print_tz)
4349  {
4350  if (tzn)
4351  {
4352  sprintf(str, " %.*s", MAXTZLEN, tzn);
4353  str += strlen(str);
4354  }
4355  else
4356  str = EncodeTimezone(str, tz, style);
4357  }
4358  break;
4359 
4360  case USE_POSTGRES_DATES:
4361  default:
4362  /* Backward-compatible with traditional Postgres abstime dates */
4363  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4364  tm->tm_wday = j2day(day);
4365  memcpy(str, days[tm->tm_wday], 3);
4366  str += 3;
4367  *str++ = ' ';
4368  if (DateOrder == DATEORDER_DMY)
4369  {
4371  *str++ = ' ';
4372  memcpy(str, months[tm->tm_mon - 1], 3);
4373  str += 3;
4374  }
4375  else
4376  {
4377  memcpy(str, months[tm->tm_mon - 1], 3);
4378  str += 3;
4379  *str++ = ' ';
4381  }
4382  *str++ = ' ';
4384  *str++ = ':';
4386  *str++ = ':';
4387  str = AppendTimestampSeconds(str, tm, fsec);
4388  *str++ = ' ';
4390  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4391 
4392  if (print_tz)
4393  {
4394  if (tzn)
4395  {
4396  sprintf(str, " %.*s", MAXTZLEN, tzn);
4397  str += strlen(str);
4398  }
4399  else
4400  {
4401  /*
4402  * We have a time zone, but no string version. Use the
4403  * numeric form, but be sure to include a leading space to
4404  * avoid formatting something which would be rejected by
4405  * the date/time parser later. - thomas 2001-10-19
4406  */
4407  *str++ = ' ';
4408  str = EncodeTimezone(str, tz, style);
4409  }
4410  }
4411  break;
4412  }
4413 
4414  if (tm->tm_year <= 0)
4415  {
4416  memcpy(str, " BC", 3); /* Don't copy NUL */
4417  str += 3;
4418  }
4419  *str = '\0';
4420 }
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:4105
int j2day(int date)
Definition: datetime.c:342
const char *const months[]
Definition: datetime.c:80
static char * AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
Definition: datetime.c:509
const char *const days[]
Definition: datetime.c:83
#define MAXTZLEN
Definition: miscadmin.h:257
#define sprintf
Definition: port.h:227

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

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

1528 {
1529  if (TIMESTAMP_IS_NOBEGIN(dt))
1530  strcpy(str, EARLY);
1531  else if (TIMESTAMP_IS_NOEND(dt))
1532  strcpy(str, LATE);
1533  else /* shouldn't happen */
1534  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1535 }
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:159
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:154
#define elog(elevel,...)
Definition: elog.h:218
#define EARLY
Definition: datetime.h:40
#define LATE
Definition: datetime.h:41

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

4229 {
4231  *str++ = ':';
4233  *str++ = ':';
4234  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
4235  if (print_tz)
4236  str = EncodeTimezone(str, tz, style);
4237  *str = '\0';
4238 }
#define MAX_TIME_PRECISION
Definition: date.h:51

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

365 {
366  fsec_t fsec;
367 
368  GetCurrentTimeUsec(tm, &fsec, NULL);
369 }

References GetCurrentTimeUsec(), and tm.

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

◆ GetCurrentTimeUsec()

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

Definition at line 385 of file datetime.c.

386 {
388 
389  /*
390  * The cache key must include both current time and current timezone. By
391  * representing the timezone by just a pointer, we're assuming that
392  * distinct timezone settings could never have the same pointer value.
393  * This is true by virtue of the hashtable used inside pg_tzset();
394  * however, it might need another look if we ever allow entries in that
395  * hash to be recycled.
396  */
397  static TimestampTz cache_ts = 0;
398  static pg_tz *cache_timezone = NULL;
399  static struct pg_tm cache_tm;
400  static fsec_t cache_fsec;
401  static int cache_tz;
402 
403  if (cur_ts != cache_ts || session_timezone != cache_timezone)
404  {
405  /*
406  * Make sure cache is marked invalid in case of error after partial
407  * update within timestamp2tm.
408  */
409  cache_timezone = NULL;
410 
411  /*
412  * Perform the computation, storing results into cache. We do not
413  * really expect any error here, since current time surely ought to be
414  * within range, but check just for sanity's sake.
415  */
416  if (timestamp2tm(cur_ts, &cache_tz, &cache_tm, &cache_fsec,
417  NULL, session_timezone) != 0)
418  ereport(ERROR,
419  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
420  errmsg("timestamp out of range")));
421 
422  /* OK, so mark the cache valid. */
423  cache_ts = cur_ts;
424  cache_timezone = session_timezone;
425  }
426 
427  *tm = cache_tm;
428  *fsec = cache_fsec;
429  if (tzp != NULL)
430  *tzp = cache_tz;
431 }
int64 TimestampTz
Definition: timestamp.h:39
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:851

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

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

◆ InstallTimeZoneAbbrevs()

void InstallTimeZoneAbbrevs ( TimeZoneAbbrevTable tbl)

Definition at line 4873 of file datetime.c.

4874 {
4875  zoneabbrevtbl = tbl;
4876  /* reset abbrevcache, which may contain pointers into old table */
4877  memset(abbrevcache, 0, sizeof(abbrevcache));
4878 }

References abbrevcache, and zoneabbrevtbl.

Referenced by assign_timezone_abbreviations().

◆ j2date()

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

Definition at line 309 of file datetime.c.

310 {
311  unsigned int julian;
312  unsigned int quad;
313  unsigned int extra;
314  int y;
315 
316  julian = jd;
317  julian += 32044;
318  quad = julian / 146097;
319  extra = (julian - quad * 146097) * 4 + 3;
320  julian += 60 + quad * 3 + extra / 146097;
321  quad = julian / 1461;
322  julian -= quad * 1461;
323  y = julian * 4 / 1461;
324  julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
325  + 123;
326  y += quad * 4;
327  *year = y - 4800;
328  quad = julian * 2141 / 65536;
329  *day = julian - 7834 * quad / 256;
330  *month = (quad + 10) % MONTHS_PER_YEAR + 1;
331 } /* j2date() */

◆ j2day()

int j2day ( int  jd)

Definition at line 342 of file datetime.c.

343 {
344  date += 1;
345  date %= 7;
346  /* Cope if division truncates towards zero, as it probably does */
347  if (date < 0)
348  date += 7;
349 
350  return date;
351 } /* 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 752 of file datetime.c.

754 {
755  int nf = 0;
756  const char *cp = timestr;
757  char *bufp = workbuf;
758  const char *bufend = workbuf + buflen;
759 
760  /*
761  * Set the character pointed-to by "bufptr" to "newchar", and increment
762  * "bufptr". "end" gives the end of the buffer -- we return an error if
763  * there is no space left to append a character to the buffer. Note that
764  * "bufptr" is evaluated twice.
765  */
766 #define APPEND_CHAR(bufptr, end, newchar) \
767  do \
768  { \
769  if (((bufptr) + 1) >= (end)) \
770  return DTERR_BAD_FORMAT; \
771  *(bufptr)++ = newchar; \
772  } while (0)
773 
774  /* outer loop through fields */
775  while (*cp != '\0')
776  {
777  /* Ignore spaces between fields */
778  if (isspace((unsigned char) *cp))
779  {
780  cp++;
781  continue;
782  }
783 
784  /* Record start of current field */
785  if (nf >= maxfields)
786  return DTERR_BAD_FORMAT;
787  field[nf] = bufp;
788 
789  /* leading digit? then date or time */
790  if (isdigit((unsigned char) *cp))
791  {
792  APPEND_CHAR(bufp, bufend, *cp++);
793  while (isdigit((unsigned char) *cp))
794  APPEND_CHAR(bufp, bufend, *cp++);
795 
796  /* time field? */
797  if (*cp == ':')
798  {
799  ftype[nf] = DTK_TIME;
800  APPEND_CHAR(bufp, bufend, *cp++);
801  while (isdigit((unsigned char) *cp) ||
802  (*cp == ':') || (*cp == '.'))
803  APPEND_CHAR(bufp, bufend, *cp++);
804  }
805  /* date field? allow embedded text month */
806  else if (*cp == '-' || *cp == '/' || *cp == '.')
807  {
808  /* save delimiting character to use later */
809  char delim = *cp;
810 
811  APPEND_CHAR(bufp, bufend, *cp++);
812  /* second field is all digits? then no embedded text month */
813  if (isdigit((unsigned char) *cp))
814  {
815  ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);
816  while (isdigit((unsigned char) *cp))
817  APPEND_CHAR(bufp, bufend, *cp++);
818 
819  /*
820  * insist that the delimiters match to get a three-field
821  * date.
822  */
823  if (*cp == delim)
824  {
825  ftype[nf] = DTK_DATE;
826  APPEND_CHAR(bufp, bufend, *cp++);
827  while (isdigit((unsigned char) *cp) || *cp == delim)
828  APPEND_CHAR(bufp, bufend, *cp++);
829  }
830  }
831  else
832  {
833  ftype[nf] = DTK_DATE;
834  while (isalnum((unsigned char) *cp) || *cp == delim)
835  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
836  }
837  }
838 
839  /*
840  * otherwise, number only and will determine year, month, day, or
841  * concatenated fields later...
842  */
843  else
844  ftype[nf] = DTK_NUMBER;
845  }
846  /* Leading decimal point? Then fractional seconds... */
847  else if (*cp == '.')
848  {
849  APPEND_CHAR(bufp, bufend, *cp++);
850  while (isdigit((unsigned char) *cp))
851  APPEND_CHAR(bufp, bufend, *cp++);
852 
853  ftype[nf] = DTK_NUMBER;
854  }
855 
856  /*
857  * text? then date string, month, day of week, special, or timezone
858  */
859  else if (isalpha((unsigned char) *cp))
860  {
861  bool is_date;
862 
863  ftype[nf] = DTK_STRING;
864  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
865  while (isalpha((unsigned char) *cp))
866  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
867 
868  /*
869  * Dates can have embedded '-', '/', or '.' separators. It could
870  * also be a timezone name containing embedded '/', '+', '-', '_',
871  * or ':' (but '_' or ':' can't be the first punctuation). If the
872  * next character is a digit or '+', we need to check whether what
873  * we have so far is a recognized non-timezone keyword --- if so,
874  * don't believe that this is the start of a timezone.
875  */
876  is_date = false;
877  if (*cp == '-' || *cp == '/' || *cp == '.')
878  is_date = true;
879  else if (*cp == '+' || isdigit((unsigned char) *cp))
880  {
881  *bufp = '\0'; /* null-terminate current field value */
882  /* we need search only the core token table, not TZ names */
883  if (datebsearch(field[nf], datetktbl, szdatetktbl) == NULL)
884  is_date = true;
885  }
886  if (is_date)
887  {
888  ftype[nf] = DTK_DATE;
889  do
890  {
891  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
892  } while (*cp == '+' || *cp == '-' ||
893  *cp == '/' || *cp == '_' ||
894  *cp == '.' || *cp == ':' ||
895  isalnum((unsigned char) *cp));
896  }
897  }
898  /* sign? then special or numeric timezone */
899  else if (*cp == '+' || *cp == '-')
900  {
901  APPEND_CHAR(bufp, bufend, *cp++);
902  /* soak up leading whitespace */
903  while (isspace((unsigned char) *cp))
904  cp++;
905  /* numeric timezone? */
906  /* note that "DTK_TZ" could also be a signed float or yyyy-mm */
907  if (isdigit((unsigned char) *cp))
908  {
909  ftype[nf] = DTK_TZ;
910  APPEND_CHAR(bufp, bufend, *cp++);
911  while (isdigit((unsigned char) *cp) ||
912  *cp == ':' || *cp == '.' || *cp == '-')
913  APPEND_CHAR(bufp, bufend, *cp++);
914  }
915  /* special? */
916  else if (isalpha((unsigned char) *cp))
917  {
918  ftype[nf] = DTK_SPECIAL;
919  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
920  while (isalpha((unsigned char) *cp))
921  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
922  }
923  /* otherwise something wrong... */
924  else
925  return DTERR_BAD_FORMAT;
926  }
927  /* ignore other punctuation but use as delimiter */
928  else if (ispunct((unsigned char) *cp))
929  {
930  cp++;
931  continue;
932  }
933  /* otherwise, something is not right... */
934  else
935  return DTERR_BAD_FORMAT;
936 
937  /* force in a delimiter after each field */
938  *bufp++ = '\0';
939  nf++;
940  }
941 
942  *numfields = nf;
943 
944  return 0;
945 }
#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()

Node* TemporalSimplify ( int32  max_precis,
Node node 
)

Definition at line 4756 of file datetime.c.

4757 {
4758  FuncExpr *expr = castNode(FuncExpr, node);
4759  Node *ret = NULL;
4760  Node *typmod;
4761 
4762  Assert(list_length(expr->args) >= 2);
4763 
4764  typmod = (Node *) lsecond(expr->args);
4765 
4766  if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
4767  {
4768  Node *source = (Node *) linitial(expr->args);
4769  int32 old_precis = exprTypmod(source);
4770  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4771 
4772  if (new_precis < 0 || new_precis == max_precis ||
4773  (old_precis >= 0 && new_precis >= old_precis))
4774  ret = relabel_to_typmod(source, new_precis);
4775  }
4776 
4777  return ret;
4778 }
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:286
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:662
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
static int list_length(const List *l)
Definition: pg_list.h:149
#define linitial(l)
Definition: pg_list.h:174
#define lsecond(l)
Definition: pg_list.h:179
static rewind_source * source
Definition: pg_rewind.c:81
#define DatumGetInt32(X)
Definition: postgres.h:516
List * args
Definition: primnodes.h:512
Definition: nodes.h:574

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

2650 {
2651  if (fmask & DTK_M(YEAR))
2652  {
2653  if (isjulian)
2654  {
2655  /* tm_year is correct and should not be touched */
2656  }
2657  else if (bc)
2658  {
2659  /* there is no year zero in AD/BC notation */
2660  if (tm->tm_year <= 0)
2661  return DTERR_FIELD_OVERFLOW;
2662  /* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
2663  tm->tm_year = -(tm->tm_year - 1);
2664  }
2665  else if (is2digits)
2666  {
2667  /* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
2668  if (tm->tm_year < 0) /* just paranoia */
2669  return DTERR_FIELD_OVERFLOW;
2670  if (tm->tm_year < 70)
2671  tm->tm_year += 2000;
2672  else if (tm->tm_year < 100)
2673  tm->tm_year += 1900;
2674  }
2675  else
2676  {
2677  /* there is no year zero in AD/BC notation */
2678  if (tm->tm_year <= 0)
2679  return DTERR_FIELD_OVERFLOW;
2680  }
2681  }
2682 
2683  /* now that we have correct year, decode DOY */
2684  if (fmask & DTK_M(DOY))
2685  {
2686  j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
2687  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2688  }
2689 
2690  /* check for valid month */
2691  if (fmask & DTK_M(MONTH))
2692  {
2693  if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
2694  return DTERR_MD_FIELD_OVERFLOW;
2695  }
2696 
2697  /* minimal check for valid day */
2698  if (fmask & DTK_M(DAY))
2699  {
2700  if (tm->tm_mday < 1 || tm->tm_mday > 31)
2701  return DTERR_MD_FIELD_OVERFLOW;
2702  }
2703 
2704  if ((fmask & DTK_DATE_M) == DTK_DATE_M)
2705  {
2706  /*
2707  * Check for valid day of month, now that we know for sure the month
2708  * and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
2709  * unlikely that "Feb 29" is a YMD-order error.
2710  */
2711  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
2712  return DTERR_FIELD_OVERFLOW;
2713  }
2714 
2715  return 0;
2716 }
const int day_tab[2][13]
Definition: datetime.c:74
#define isleap(y)
Definition: datetime.h:272
#define DOY
Definition: datetime.h:106
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 74 of file datetime.c.

◆ days

PGDLLIMPORT const char* const days[]
extern

Definition at line 83 of file datetime.c.

◆ months

PGDLLIMPORT const char* const months[]
extern

Definition at line 80 of file datetime.c.