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_INVALID   7
 
#define DTK_CURRENT   8
 
#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_tm *tm, fsec_t *fsec)
 
int DecodeISO8601Interval (char *str, int *dtype, struct pg_tm *tm, fsec_t *fsec)
 
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_tm *tm, fsec_t fsec, 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)
 
NodeTemporalTransform (int32 max_precis, Node *node)
 
bool CheckDateTokenTables (void)
 
TimeZoneAbbrevTableConvertTimeZoneAbbrevs (struct tzEntry *abbrevs, int n)
 
void InstallTimeZoneAbbrevs (TimeZoneAbbrevTable *tbl)
 

Variables

const char *const months []
 
const char *const days []
 
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.

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

◆ AGO

#define AGO   19

Definition at line 111 of file datetime.h.

Referenced by DecodeInterval().

◆ AM

#define AM   0

Definition at line 72 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ AMPM

#define AMPM   9

Definition at line 100 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ BC

#define BC   1

Definition at line 77 of file datetime.h.

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

◆ CENTURY

#define CENTURY   26

Definition at line 120 of file datetime.h.

Referenced by DecodeInterval().

◆ 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

◆ 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.

Referenced by DecodeInterval().

◆ 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.

Referenced by DecodeDateTime().

◆ DOY

#define DOY   15

Definition at line 106 of file datetime.h.

Referenced by DecodeDate(), DecodeNumber(), and ValidateDate().

◆ 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

◆ DTERR_FIELD_OVERFLOW

◆ DTERR_INTERVAL_OVERFLOW

#define DTERR_INTERVAL_OVERFLOW   (-4)

Definition at line 285 of file datetime.h.

Referenced by DateTimeParseError(), interval_in(), and reltimein().

◆ DTERR_MD_FIELD_OVERFLOW

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

Definition at line 284 of file datetime.h.

Referenced by DateTimeParseError(), and ValidateDate().

◆ DTERR_TZDISP_OVERFLOW

#define DTERR_TZDISP_OVERFLOW   (-5)

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

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

◆ DTK_CENTURY

◆ DTK_CURRENT

#define DTK_CURRENT   8

Definition at line 152 of file datetime.h.

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

◆ DTK_DATE

◆ DTK_DATE_M

◆ DTK_DAY

◆ DTK_DECADE

◆ DTK_DELTA

#define DTK_DELTA   17

◆ DTK_DOW

#define DTK_DOW   32

Definition at line 178 of file datetime.h.

Referenced by NonFiniteTimestampTzPart(), timestamp_part(), and timestamptz_part().

◆ DTK_DOY

#define DTK_DOY   33

Definition at line 179 of file datetime.h.

Referenced by NonFiniteTimestampTzPart(), timestamp_part(), and timestamptz_part().

◆ DTK_EARLY

#define DTK_EARLY   9

◆ DTK_EPOCH

◆ DTK_HOUR

◆ DTK_INVALID

#define DTK_INVALID   7

◆ DTK_ISODOW

#define DTK_ISODOW   37

Definition at line 183 of file datetime.h.

Referenced by NonFiniteTimestampTzPart(), timestamp_part(), and timestamptz_part().

◆ DTK_ISOYEAR

#define DTK_ISOYEAR   36

Definition at line 182 of file datetime.h.

Referenced by NonFiniteTimestampTzPart(), time_part(), timestamp_part(), and timestamptz_part().

◆ DTK_JULIAN

#define DTK_JULIAN   31

◆ DTK_LATE

#define DTK_LATE   10

◆ DTK_M

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

◆ DTK_MICROSEC

◆ DTK_MILLENNIUM

◆ DTK_MILLISEC

◆ DTK_MINUTE

◆ DTK_MONTH

◆ DTK_NOW

#define DTK_NOW   12

Definition at line 156 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ DTK_NUMBER

#define DTK_NUMBER   0

Definition at line 142 of file datetime.h.

Referenced by DecodeDateTime(), DecodeInterval(), DecodeTimeOnly(), and ParseDateTime().

◆ DTK_QUARTER

◆ DTK_SECOND

◆ DTK_SPECIAL

#define DTK_SPECIAL   6

Definition at line 150 of file datetime.h.

Referenced by DecodeDateTime(), DecodeInterval(), DecodeTimeOnly(), and ParseDateTime().

◆ DTK_STRING

#define DTK_STRING   1

Definition at line 143 of file datetime.h.

Referenced by DecodeDateTime(), DecodeInterval(), DecodeTimeOnly(), and ParseDateTime().

◆ DTK_TIME

#define DTK_TIME   3

◆ DTK_TIME_M

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

◆ DTK_TODAY

#define DTK_TODAY   14

Definition at line 158 of file datetime.h.

Referenced by DecodeDateTime().

◆ DTK_TOMORROW

#define DTK_TOMORROW   15

Definition at line 159 of file datetime.h.

Referenced by DecodeDateTime().

◆ DTK_TZ

◆ DTK_TZ_HOUR

#define DTK_TZ_HOUR   34

◆ DTK_TZ_MINUTE

#define DTK_TZ_MINUTE   35

◆ DTK_WEEK

◆ DTK_YEAR

◆ DTK_YESTERDAY

#define DTK_YESTERDAY   13

Definition at line 157 of file datetime.h.

Referenced by DecodeDateTime().

◆ DTK_ZULU

#define DTK_ZULU   16

Definition at line 160 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ DTZ

◆ DTZMOD

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

Definition at line 123 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ 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

◆ EARLY

#define EARLY   "-infinity"

Definition at line 40 of file datetime.h.

Referenced by abstimeout(), EncodeSpecialDate(), and EncodeSpecialTimestamp().

◆ 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)
double rint(double x)
Definition: rint.c:22

Definition at line 240 of file datetime.h.

Referenced by reltime2tm(), timestamptz_part(), and timetz_part().

◆ HOUR

◆ HR24

#define HR24   2

Definition at line 74 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ IGNORE_DTF

#define IGNORE_DTF   8

Definition at line 99 of file datetime.h.

Referenced by DecodeDate(), DecodeDateTime(), DecodeInterval(), and DecodeTimeOnly().

◆ 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))

◆ ISODATE

#define ISODATE   22

Definition at line 115 of file datetime.h.

◆ ISOTIME

#define ISOTIME   23

Definition at line 116 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ JULIAN

#define JULIAN   4

Definition at line 95 of file datetime.h.

◆ LATE

#define LATE   "infinity"

Definition at line 41 of file datetime.h.

Referenced by abstimeout(), EncodeSpecialDate(), and EncodeSpecialTimestamp().

◆ MAXDATEFIELDS

◆ MAXDATELEN

◆ MICROSECOND

#define MICROSECOND   14

Definition at line 105 of file datetime.h.

Referenced by DecodeInterval().

◆ MILLENNIUM

#define MILLENNIUM   27

Definition at line 121 of file datetime.h.

Referenced by DecodeInterval().

◆ MILLISECOND

#define MILLISECOND   13

Definition at line 104 of file datetime.h.

Referenced by DecodeInterval().

◆ MINUTE

◆ MONTH

◆ NOW

#define NOW   "now"

Definition at line 42 of file datetime.h.

◆ PM

#define PM   1

Definition at line 73 of file datetime.h.

Referenced by DecodeDateTime(), and DecodeTimeOnly().

◆ RESERV

◆ SECOND

◆ TMODULO

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

Definition at line 251 of file datetime.h.

Referenced by interval_justify_hours(), interval_justify_interval(), and timestamp2tm().

◆ TODAY

#define TODAY   "today"

Definition at line 43 of file datetime.h.

◆ TOKMAXLEN

◆ TOMORROW

#define TOMORROW   "tomorrow"

Definition at line 44 of file datetime.h.

◆ TZ

◆ UNITS

◆ UNKNOWN_FIELD

◆ WEEK

#define WEEK   24

Definition at line 118 of file datetime.h.

Referenced by DecodeInterval().

◆ YEAR

◆ 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

◆ CheckDateTokenTables()

bool CheckDateTokenTables ( void  )

Definition at line 4448 of file datetime.c.

4449 {
4450  bool ok = true;
4451 
4452  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4453  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4454 
4455  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4456  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4457  return ok;
4458 }
static const datetkn datetktbl[]
Definition: datetime.c:91
static int szdatetktbl
Definition: datetime.c:169
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4416
static const datetkn deltatktbl[]
Definition: datetime.c:175
int date2j(int y, int m, int d)
Definition: datetime.c:276
static int szdeltatktbl
Definition: datetime.c:242
#define Assert(condition)
Definition: c.h:699
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:162
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163

◆ ConvertTimeZoneAbbrevs()

TimeZoneAbbrevTable* ConvertTimeZoneAbbrevs ( struct tzEntry abbrevs,
int  n 
)

Definition at line 4503 of file datetime.c.

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, tzEntry::zone, and DynamicZoneAbbrev::zone.

Referenced by load_tzoffsets().

4504 {
4505  TimeZoneAbbrevTable *tbl;
4506  Size tbl_size;
4507  int i;
4508 
4509  /* Space for fixed fields and datetkn array */
4510  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4511  n * sizeof(datetkn);
4512  tbl_size = MAXALIGN(tbl_size);
4513  /* Count up space for dynamic abbreviations */
4514  for (i = 0; i < n; i++)
4515  {
4516  struct tzEntry *abbr = abbrevs + i;
4517 
4518  if (abbr->zone != NULL)
4519  {
4520  Size dsize;
4521 
4522  dsize = offsetof(DynamicZoneAbbrev, zone) +
4523  strlen(abbr->zone) + 1;
4524  tbl_size += MAXALIGN(dsize);
4525  }
4526  }
4527 
4528  /* Alloc the result ... */
4529  tbl = malloc(tbl_size);
4530  if (!tbl)
4531  return NULL;
4532 
4533  /* ... and fill it in */
4534  tbl->tblsize = tbl_size;
4535  tbl->numabbrevs = n;
4536  /* in this loop, tbl_size reprises the space calculation above */
4537  tbl_size = offsetof(TimeZoneAbbrevTable, abbrevs) +
4538  n * sizeof(datetkn);
4539  tbl_size = MAXALIGN(tbl_size);
4540  for (i = 0; i < n; i++)
4541  {
4542  struct tzEntry *abbr = abbrevs + i;
4543  datetkn *dtoken = tbl->abbrevs + i;
4544 
4545  /* use strlcpy to truncate name if necessary */
4546  strlcpy(dtoken->token, abbr->abbrev, TOKMAXLEN + 1);
4547  if (abbr->zone != NULL)
4548  {
4549  /* Allocate a DynamicZoneAbbrev for this abbreviation */
4550  DynamicZoneAbbrev *dtza;
4551  Size dsize;
4552 
4553  dtza = (DynamicZoneAbbrev *) ((char *) tbl + tbl_size);
4554  dtza->tz = NULL;
4555  strcpy(dtza->zone, abbr->zone);
4556 
4557  dtoken->type = DYNTZ;
4558  /* value is offset from table start to DynamicZoneAbbrev */
4559  dtoken->value = (int32) tbl_size;
4560 
4561  dsize = offsetof(DynamicZoneAbbrev, zone) +
4562  strlen(abbr->zone) + 1;
4563  tbl_size += MAXALIGN(dsize);
4564  }
4565  else
4566  {
4567  dtoken->type = abbr->is_dst ? DTZ : TZ;
4568  dtoken->value = abbr->offset;
4569  }
4570  }
4571 
4572  /* Assert the two loops above agreed on size calculations */
4573  Assert(tbl->tblsize == tbl_size);
4574 
4575  /* Check the ordering, if testing */
4576  Assert(CheckDateTokenTable("timezone abbreviations", tbl->abbrevs, n));
4577 
4578  return tbl;
4579 }
int offset
Definition: tzparser.h:29
#define TZ
Definition: datetime.h:96
int32 value
Definition: datetime.h:214
signed int int32
Definition: c.h:313
char * zone
Definition: tzparser.h:27
bool is_dst
Definition: tzparser.h:30
#define malloc(a)
Definition: header.h:50
char token[TOKMAXLEN+1]
Definition: datetime.h:212
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4416
datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:222
char * abbrev
Definition: tzparser.h:26
char zone[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:230
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char type
Definition: datetime.h:213
#define Assert(condition)
Definition: c.h:699
size_t Size
Definition: c.h:433
#define MAXALIGN(LEN)
Definition: c.h:652
#define DTZ
Definition: datetime.h:97
Definition: zic.c:92
#define DYNTZ
Definition: datetime.h:98
int i
#define TOKMAXLEN
Definition: datetime.h:207
#define offsetof(type, field)
Definition: c.h:622

◆ date2j()

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

Definition at line 276 of file datetime.c.

277 {
278  int julian;
279  int century;
280 
281  if (m > 2)
282  {
283  m += 1;
284  y += 4800;
285  }
286  else
287  {
288  m += 13;
289  y += 4799;
290  }
291 
292  century = y / 100;
293  julian = y * 365 - 32167;
294  julian += y / 4 - century + century / 4;
295  julian += 7834 * m / 256 + d;
296 
297  return julian;
298 } /* date2j() */

◆ DateTimeParseError()

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

Definition at line 3749 of file datetime.c.

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

Referenced by abstimein(), date_in(), do_to_timestamp(), interval_in(), reltimein(), time_in(), timestamp_in(), timestamptz_in(), timetz_in(), and to_timestamp().

3750 {
3751  switch (dterr)
3752  {
3753  case DTERR_FIELD_OVERFLOW:
3754  ereport(ERROR,
3755  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3756  errmsg("date/time field value out of range: \"%s\"",
3757  str)));
3758  break;
3760  /* <nanny>same as above, but add hint about DateStyle</nanny> */
3761  ereport(ERROR,
3762  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3763  errmsg("date/time field value out of range: \"%s\"",
3764  str),
3765  errhint("Perhaps you need a different \"datestyle\" setting.")));
3766  break;
3768  ereport(ERROR,
3769  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
3770  errmsg("interval field value out of range: \"%s\"",
3771  str)));
3772  break;
3773  case DTERR_TZDISP_OVERFLOW:
3774  ereport(ERROR,
3775  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
3776  errmsg("time zone displacement out of range: \"%s\"",
3777  str)));
3778  break;
3779  case DTERR_BAD_FORMAT:
3780  default:
3781  ereport(ERROR,
3782  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3783  errmsg("invalid input syntax for type %s: \"%s\"",
3784  datatype, str)));
3785  break;
3786  }
3787 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:285
#define ereport(elevel, rest)
Definition: elog.h:122
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DTERR_MD_FIELD_OVERFLOW
Definition: datetime.h:284

◆ DecodeDateTime()

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

Definition at line 767 of file datetime.c.

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_CURRENT, 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, ParseFractionalSecond(), pg_tzset(), PM, RESERV, SECOND, session_timezone, strtoint(), 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 abstimein(), date_in(), pg_logdir_ls_internal(), PGTYPESdate_from_asc(), PGTYPEStimestamp_from_asc(), timestamp_in(), and timestamptz_in().

769 {
770  int fmask = 0,
771  tmask,
772  type;
773  int ptype = 0; /* "prefix type" for ISO y2001m02d04 format */
774  int i;
775  int val;
776  int dterr;
777  int mer = HR24;
778  bool haveTextMonth = false;
779  bool isjulian = false;
780  bool is2digits = false;
781  bool bc = false;
782  pg_tz *namedTz = NULL;
783  pg_tz *abbrevTz = NULL;
784  pg_tz *valtz;
785  char *abbrev = NULL;
786  struct pg_tm cur_tm;
787 
788  /*
789  * We'll insist on at least all of the date fields, but initialize the
790  * remaining fields in case they are not set later...
791  */
792  *dtype = DTK_DATE;
793  tm->tm_hour = 0;
794  tm->tm_min = 0;
795  tm->tm_sec = 0;
796  *fsec = 0;
797  /* don't know daylight savings time status apriori */
798  tm->tm_isdst = -1;
799  if (tzp != NULL)
800  *tzp = 0;
801 
802  for (i = 0; i < nf; i++)
803  {
804  switch (ftype[i])
805  {
806  case DTK_DATE:
807 
808  /*
809  * Integral julian day with attached time zone? All other
810  * forms with JD will be separated into distinct fields, so we
811  * handle just this case here.
812  */
813  if (ptype == DTK_JULIAN)
814  {
815  char *cp;
816  int val;
817 
818  if (tzp == NULL)
819  return DTERR_BAD_FORMAT;
820 
821  errno = 0;
822  val = strtoint(field[i], &cp, 10);
823  if (errno == ERANGE || val < 0)
824  return DTERR_FIELD_OVERFLOW;
825 
826  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
827  isjulian = true;
828 
829  /* Get the time zone from the end of the string */
830  dterr = DecodeTimezone(cp, tzp);
831  if (dterr)
832  return dterr;
833 
834  tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
835  ptype = 0;
836  break;
837  }
838 
839  /*
840  * Already have a date? Then this might be a time zone name
841  * with embedded punctuation (e.g. "America/New_York") or a
842  * run-together time with trailing time zone (e.g. hhmmss-zz).
843  * - thomas 2001-12-25
844  *
845  * We consider it a time zone if we already have month & day.
846  * This is to allow the form "mmm dd hhmmss tz year", which
847  * we've historically accepted.
848  */
849  else if (ptype != 0 ||
850  ((fmask & (DTK_M(MONTH) | DTK_M(DAY))) ==
851  (DTK_M(MONTH) | DTK_M(DAY))))
852  {
853  /* No time zone accepted? Then quit... */
854  if (tzp == NULL)
855  return DTERR_BAD_FORMAT;
856 
857  if (isdigit((unsigned char) *field[i]) || ptype != 0)
858  {
859  char *cp;
860 
861  if (ptype != 0)
862  {
863  /* Sanity check; should not fail this test */
864  if (ptype != DTK_TIME)
865  return DTERR_BAD_FORMAT;
866  ptype = 0;
867  }
868 
869  /*
870  * Starts with a digit but we already have a time
871  * field? Then we are in trouble with a date and time
872  * already...
873  */
874  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
875  return DTERR_BAD_FORMAT;
876 
877  if ((cp = strchr(field[i], '-')) == NULL)
878  return DTERR_BAD_FORMAT;
879 
880  /* Get the time zone from the end of the string */
881  dterr = DecodeTimezone(cp, tzp);
882  if (dterr)
883  return dterr;
884  *cp = '\0';
885 
886  /*
887  * Then read the rest of the field as a concatenated
888  * time
889  */
890  dterr = DecodeNumberField(strlen(field[i]), field[i],
891  fmask,
892  &tmask, tm,
893  fsec, &is2digits);
894  if (dterr < 0)
895  return dterr;
896 
897  /*
898  * modify tmask after returning from
899  * DecodeNumberField()
900  */
901  tmask |= DTK_M(TZ);
902  }
903  else
904  {
905  namedTz = pg_tzset(field[i]);
906  if (!namedTz)
907  {
908  /*
909  * We should return an error code instead of
910  * ereport'ing directly, but then there is no way
911  * to report the bad time zone name.
912  */
913  ereport(ERROR,
914  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
915  errmsg("time zone \"%s\" not recognized",
916  field[i])));
917  }
918  /* we'll apply the zone setting below */
919  tmask = DTK_M(TZ);
920  }
921  }
922  else
923  {
924  dterr = DecodeDate(field[i], fmask,
925  &tmask, &is2digits, tm);
926  if (dterr)
927  return dterr;
928  }
929  break;
930 
931  case DTK_TIME:
932 
933  /*
934  * This might be an ISO time following a "t" field.
935  */
936  if (ptype != 0)
937  {
938  /* Sanity check; should not fail this test */
939  if (ptype != DTK_TIME)
940  return DTERR_BAD_FORMAT;
941  ptype = 0;
942  }
943  dterr = DecodeTime(field[i], fmask, INTERVAL_FULL_RANGE,
944  &tmask, tm, fsec);
945  if (dterr)
946  return dterr;
947 
948  /*
949  * Check upper limit on hours; other limits checked in
950  * DecodeTime()
951  */
952  /* test for > 24:00:00 */
953  if (tm->tm_hour > HOURS_PER_DAY ||
954  (tm->tm_hour == HOURS_PER_DAY &&
955  (tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)))
956  return DTERR_FIELD_OVERFLOW;
957  break;
958 
959  case DTK_TZ:
960  {
961  int tz;
962 
963  if (tzp == NULL)
964  return DTERR_BAD_FORMAT;
965 
966  dterr = DecodeTimezone(field[i], &tz);
967  if (dterr)
968  return dterr;
969  *tzp = tz;
970  tmask = DTK_M(TZ);
971  }
972  break;
973 
974  case DTK_NUMBER:
975 
976  /*
977  * Was this an "ISO date" with embedded field labels? An
978  * example is "y2001m02d04" - thomas 2001-02-04
979  */
980  if (ptype != 0)
981  {
982  char *cp;
983  int val;
984 
985  errno = 0;
986  val = strtoint(field[i], &cp, 10);
987  if (errno == ERANGE)
988  return DTERR_FIELD_OVERFLOW;
989 
990  /*
991  * only a few kinds are allowed to have an embedded
992  * decimal
993  */
994  if (*cp == '.')
995  switch (ptype)
996  {
997  case DTK_JULIAN:
998  case DTK_TIME:
999  case DTK_SECOND:
1000  break;
1001  default:
1002  return DTERR_BAD_FORMAT;
1003  break;
1004  }
1005  else if (*cp != '\0')
1006  return DTERR_BAD_FORMAT;
1007 
1008  switch (ptype)
1009  {
1010  case DTK_YEAR:
1011  tm->tm_year = val;
1012  tmask = DTK_M(YEAR);
1013  break;
1014 
1015  case DTK_MONTH:
1016 
1017  /*
1018  * already have a month and hour? then assume
1019  * minutes
1020  */
1021  if ((fmask & DTK_M(MONTH)) != 0 &&
1022  (fmask & DTK_M(HOUR)) != 0)
1023  {
1024  tm->tm_min = val;
1025  tmask = DTK_M(MINUTE);
1026  }
1027  else
1028  {
1029  tm->tm_mon = val;
1030  tmask = DTK_M(MONTH);
1031  }
1032  break;
1033 
1034  case DTK_DAY:
1035  tm->tm_mday = val;
1036  tmask = DTK_M(DAY);
1037  break;
1038 
1039  case DTK_HOUR:
1040  tm->tm_hour = val;
1041  tmask = DTK_M(HOUR);
1042  break;
1043 
1044  case DTK_MINUTE:
1045  tm->tm_min = val;
1046  tmask = DTK_M(MINUTE);
1047  break;
1048 
1049  case DTK_SECOND:
1050  tm->tm_sec = val;
1051  tmask = DTK_M(SECOND);
1052  if (*cp == '.')
1053  {
1054  dterr = ParseFractionalSecond(cp, fsec);
1055  if (dterr)
1056  return dterr;
1057  tmask = DTK_ALL_SECS_M;
1058  }
1059  break;
1060 
1061  case DTK_TZ:
1062  tmask = DTK_M(TZ);
1063  dterr = DecodeTimezone(field[i], tzp);
1064  if (dterr)
1065  return dterr;
1066  break;
1067 
1068  case DTK_JULIAN:
1069  /* previous field was a label for "julian date" */
1070  if (val < 0)
1071  return DTERR_FIELD_OVERFLOW;
1072  tmask = DTK_DATE_M;
1073  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1074  isjulian = true;
1075 
1076  /* fractional Julian Day? */
1077  if (*cp == '.')
1078  {
1079  double time;
1080 
1081  errno = 0;
1082  time = strtod(cp, &cp);
1083  if (*cp != '\0' || errno != 0)
1084  return DTERR_BAD_FORMAT;
1085  time *= USECS_PER_DAY;
1086  dt2time(time,
1087  &tm->tm_hour, &tm->tm_min,
1088  &tm->tm_sec, fsec);
1089  tmask |= DTK_TIME_M;
1090  }
1091  break;
1092 
1093  case DTK_TIME:
1094  /* previous field was "t" for ISO time */
1095  dterr = DecodeNumberField(strlen(field[i]), field[i],
1096  (fmask | DTK_DATE_M),
1097  &tmask, tm,
1098  fsec, &is2digits);
1099  if (dterr < 0)
1100  return dterr;
1101  if (tmask != DTK_TIME_M)
1102  return DTERR_BAD_FORMAT;
1103  break;
1104 
1105  default:
1106  return DTERR_BAD_FORMAT;
1107  break;
1108  }
1109 
1110  ptype = 0;
1111  *dtype = DTK_DATE;
1112  }
1113  else
1114  {
1115  char *cp;
1116  int flen;
1117 
1118  flen = strlen(field[i]);
1119  cp = strchr(field[i], '.');
1120 
1121  /* Embedded decimal and no date yet? */
1122  if (cp != NULL && !(fmask & DTK_DATE_M))
1123  {
1124  dterr = DecodeDate(field[i], fmask,
1125  &tmask, &is2digits, tm);
1126  if (dterr)
1127  return dterr;
1128  }
1129  /* embedded decimal and several digits before? */
1130  else if (cp != NULL && flen - strlen(cp) > 2)
1131  {
1132  /*
1133  * Interpret as a concatenated date or time Set the
1134  * type field to allow decoding other fields later.
1135  * Example: 20011223 or 040506
1136  */
1137  dterr = DecodeNumberField(flen, field[i], fmask,
1138  &tmask, tm,
1139  fsec, &is2digits);
1140  if (dterr < 0)
1141  return dterr;
1142  }
1143 
1144  /*
1145  * Is this a YMD or HMS specification, or a year number?
1146  * YMD and HMS are required to be six digits or more, so
1147  * if it is 5 digits, it is a year. If it is six or more
1148  * more digits, we assume it is YMD or HMS unless no date
1149  * and no time values have been specified. This forces 6+
1150  * digit years to be at the end of the string, or to use
1151  * the ISO date specification.
1152  */
1153  else if (flen >= 6 && (!(fmask & DTK_DATE_M) ||
1154  !(fmask & DTK_TIME_M)))
1155  {
1156  dterr = DecodeNumberField(flen, field[i], fmask,
1157  &tmask, tm,
1158  fsec, &is2digits);
1159  if (dterr < 0)
1160  return dterr;
1161  }
1162  /* otherwise it is a single date/time field... */
1163  else
1164  {
1165  dterr = DecodeNumber(flen, field[i],
1166  haveTextMonth, fmask,
1167  &tmask, tm,
1168  fsec, &is2digits);
1169  if (dterr)
1170  return dterr;
1171  }
1172  }
1173  break;
1174 
1175  case DTK_STRING:
1176  case DTK_SPECIAL:
1177  /* timezone abbrevs take precedence over built-in tokens */
1178  type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
1179  if (type == UNKNOWN_FIELD)
1180  type = DecodeSpecial(i, field[i], &val);
1181  if (type == IGNORE_DTF)
1182  continue;
1183 
1184  tmask = DTK_M(type);
1185  switch (type)
1186  {
1187  case RESERV:
1188  switch (val)
1189  {
1190  case DTK_CURRENT:
1191  ereport(ERROR,
1192  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1193  errmsg("date/time value \"current\" is no longer supported")));
1194 
1195  return DTERR_BAD_FORMAT;
1196  break;
1197 
1198  case DTK_NOW:
1199  tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
1200  *dtype = DTK_DATE;
1201  GetCurrentTimeUsec(tm, fsec, tzp);
1202  break;
1203 
1204  case DTK_YESTERDAY:
1205  tmask = DTK_DATE_M;
1206  *dtype = DTK_DATE;
1207  GetCurrentDateTime(&cur_tm);
1208  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) - 1,
1209  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1210  break;
1211 
1212  case DTK_TODAY:
1213  tmask = DTK_DATE_M;
1214  *dtype = DTK_DATE;
1215  GetCurrentDateTime(&cur_tm);
1216  tm->tm_year = cur_tm.tm_year;
1217  tm->tm_mon = cur_tm.tm_mon;
1218  tm->tm_mday = cur_tm.tm_mday;
1219  break;
1220 
1221  case DTK_TOMORROW:
1222  tmask = DTK_DATE_M;
1223  *dtype = DTK_DATE;
1224  GetCurrentDateTime(&cur_tm);
1225  j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) + 1,
1226  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1227  break;
1228 
1229  case DTK_ZULU:
1230  tmask = (DTK_TIME_M | DTK_M(TZ));
1231  *dtype = DTK_DATE;
1232  tm->tm_hour = 0;
1233  tm->tm_min = 0;
1234  tm->tm_sec = 0;
1235  if (tzp != NULL)
1236  *tzp = 0;
1237  break;
1238 
1239  default:
1240  *dtype = val;
1241  }
1242 
1243  break;
1244 
1245  case MONTH:
1246 
1247  /*
1248  * already have a (numeric) month? then see if we can
1249  * substitute...
1250  */
1251  if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
1252  !(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 &&
1253  tm->tm_mon <= 31)
1254  {
1255  tm->tm_mday = tm->tm_mon;
1256  tmask = DTK_M(DAY);
1257  }
1258  haveTextMonth = true;
1259  tm->tm_mon = val;
1260  break;
1261 
1262  case DTZMOD:
1263 
1264  /*
1265  * daylight savings time modifier (solves "MET DST"
1266  * syntax)
1267  */
1268  tmask |= DTK_M(DTZ);
1269  tm->tm_isdst = 1;
1270  if (tzp == NULL)
1271  return DTERR_BAD_FORMAT;
1272  *tzp -= val;
1273  break;
1274 
1275  case DTZ:
1276 
1277  /*
1278  * set mask for TZ here _or_ check for DTZ later when
1279  * getting default timezone
1280  */
1281  tmask |= DTK_M(TZ);
1282  tm->tm_isdst = 1;
1283  if (tzp == NULL)
1284  return DTERR_BAD_FORMAT;
1285  *tzp = -val;
1286  break;
1287 
1288  case TZ:
1289  tm->tm_isdst = 0;
1290  if (tzp == NULL)
1291  return DTERR_BAD_FORMAT;
1292  *tzp = -val;
1293  break;
1294 
1295  case DYNTZ:
1296  tmask |= DTK_M(TZ);
1297  if (tzp == NULL)
1298  return DTERR_BAD_FORMAT;
1299  /* we'll determine the actual offset later */
1300  abbrevTz = valtz;
1301  abbrev = field[i];
1302  break;
1303 
1304  case AMPM:
1305  mer = val;
1306  break;
1307 
1308  case ADBC:
1309  bc = (val == BC);
1310  break;
1311 
1312  case DOW:
1313  tm->tm_wday = val;
1314  break;
1315 
1316  case UNITS:
1317  tmask = 0;
1318  ptype = val;
1319  break;
1320 
1321  case ISOTIME:
1322 
1323  /*
1324  * This is a filler field "t" indicating that the next
1325  * field is time. Try to verify that this is sensible.
1326  */
1327  tmask = 0;
1328 
1329  /* No preceding date? Then quit... */
1330  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1331  return DTERR_BAD_FORMAT;
1332 
1333  /***
1334  * We will need one of the following fields:
1335  * DTK_NUMBER should be hhmmss.fff
1336  * DTK_TIME should be hh:mm:ss.fff
1337  * DTK_DATE should be hhmmss-zz
1338  ***/
1339  if (i >= nf - 1 ||
1340  (ftype[i + 1] != DTK_NUMBER &&
1341  ftype[i + 1] != DTK_TIME &&
1342  ftype[i + 1] != DTK_DATE))
1343  return DTERR_BAD_FORMAT;
1344 
1345  ptype = val;
1346  break;
1347 
1348  case UNKNOWN_FIELD:
1349 
1350  /*
1351  * Before giving up and declaring error, check to see
1352  * if it is an all-alpha timezone name.
1353  */
1354  namedTz = pg_tzset(field[i]);
1355  if (!namedTz)
1356  return DTERR_BAD_FORMAT;
1357  /* we'll apply the zone setting below */
1358  tmask = DTK_M(TZ);
1359  break;
1360 
1361  default:
1362  return DTERR_BAD_FORMAT;
1363  }
1364  break;
1365 
1366  default:
1367  return DTERR_BAD_FORMAT;
1368  }
1369 
1370  if (tmask & fmask)
1371  return DTERR_BAD_FORMAT;
1372  fmask |= tmask;
1373  } /* end loop over fields */
1374 
1375  /* do final checking/adjustment of Y/M/D fields */
1376  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
1377  if (dterr)
1378  return dterr;
1379 
1380  /* handle AM/PM */
1381  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
1382  return DTERR_FIELD_OVERFLOW;
1383  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
1384  tm->tm_hour = 0;
1385  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
1386  tm->tm_hour += HOURS_PER_DAY / 2;
1387 
1388  /* do additional checking for full date specs... */
1389  if (*dtype == DTK_DATE)
1390  {
1391  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
1392  {
1393  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1394  return 1;
1395  return DTERR_BAD_FORMAT;
1396  }
1397 
1398  /*
1399  * If we had a full timezone spec, compute the offset (we could not do
1400  * it before, because we need the date to resolve DST status).
1401  */
1402  if (namedTz != NULL)
1403  {
1404  /* daylight savings time modifier disallowed with full TZ */
1405  if (fmask & DTK_M(DTZMOD))
1406  return DTERR_BAD_FORMAT;
1407 
1408  *tzp = DetermineTimeZoneOffset(tm, namedTz);
1409  }
1410 
1411  /*
1412  * Likewise, if we had a dynamic timezone abbreviation, resolve it
1413  * now.
1414  */
1415  if (abbrevTz != NULL)
1416  {
1417  /* daylight savings time modifier disallowed with dynamic TZ */
1418  if (fmask & DTK_M(DTZMOD))
1419  return DTERR_BAD_FORMAT;
1420 
1421  *tzp = DetermineTimeZoneAbbrevOffset(tm, abbrev, abbrevTz);
1422  }
1423 
1424  /* timezone not specified? then use session timezone */
1425  if (tzp != NULL && !(fmask & DTK_M(TZ)))
1426  {
1427  /*
1428  * daylight savings time modifier but no standard timezone? then
1429  * error
1430  */
1431  if (fmask & DTK_M(DTZMOD))
1432  return DTERR_BAD_FORMAT;
1433 
1435  }
1436  }
1437 
1438  return 0;
1439 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:354
#define PM
Definition: datetime.h:73
#define DAY
Definition: datetime.h:94
#define UNITS
Definition: datetime.h:108
#define IGNORE_DTF
Definition: datetime.h:99
int tm_wday
Definition: pgtime.h:33
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
#define DTK_JULIAN
Definition: datetime.h:176
#define DTK_YEAR
Definition: datetime.h:170
int tm_isdst
Definition: pgtime.h:35
#define YEAR
Definition: datetime.h:93
int tm_hour
Definition: pgtime.h:29
#define DTK_TIME_M
Definition: datetime.h:195
int errcode(int sqlerrcode)
Definition: elog.c:575
#define TZ
Definition: datetime.h:96
#define UNKNOWN_FIELD
Definition: datetime.h:125
#define SECOND
Definition: datetime.h:103
static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2803
#define DTK_TODAY
Definition: datetime.h:158
#define DTK_TOMORROW
Definition: datetime.h:159
#define ADBC
Definition: datetime.h:109
Definition: pgtime.h:25
#define DTK_CURRENT
Definition: datetime.h:152
#define INTERVAL_FULL_RANGE
Definition: timestamp.h:48
#define DTK_DATE_M
Definition: datetime.h:194
pg_tz * pg_tzset(const char *tzname)
Definition: pgtz.c:236
#define DTK_MONTH
Definition: datetime.h:168
#define DTK_TZ
Definition: datetime.h:147
#define DTK_HOUR
Definition: datetime.h:165
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define DOW
Definition: datetime.h:107
#define AM
Definition: datetime.h:72
int DecodeTimezoneAbbrev(int field, char *lowtoken, int *offset, pg_tz **tz)
Definition: datetime.c:2968
#define DTK_SECOND
Definition: datetime.h:163
int DecodeTimezone(char *str, int *tzp)
Definition: datetime.c:2890
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1455
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits, struct pg_tm *tm)
Definition: datetime.c:2353
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:371
#define DTK_YESTERDAY
Definition: datetime.h:157
#define DTK_NUMBER
Definition: datetime.h:142
#define MINUTE
Definition: datetime.h:102
#define USECS_PER_DAY
Definition: timestamp.h:91
#define ereport(elevel, rest)
Definition: elog.h:122
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:301
#define MONTH
Definition: datetime.h:92
#define DTK_MINUTE
Definition: datetime.h:164
static int ParseFractionalSecond(char *cp, fsec_t *fsec)
Definition: datetime.c:498
#define BC
Definition: datetime.h:77
char * abbrev
Definition: tzparser.h:26
Definition: pgtz.h:59
#define ISOTIME
Definition: datetime.h:116
#define DTK_TIME
Definition: datetime.h:146
int date2j(int y, int m, int d)
Definition: datetime.c:276
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2542
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1731
#define AMPM
Definition: datetime.h:100
#define DTK_STRING
Definition: datetime.h:143
#define DTK_DAY
Definition: datetime.h:166
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:2618
#define RESERV
Definition: datetime.h:91
int DecodeSpecial(int field, char *lowtoken, int *val)
Definition: datetime.c:3023
#define DTK_ALL_SECS_M
Definition: datetime.h:193
#define DTZ
Definition: datetime.h:97
int tm_year
Definition: pgtime.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DYNTZ
Definition: datetime.h:98
#define DTK_NOW
Definition: datetime.h:156
int i
#define DTK_M(t)
Definition: datetime.h:190
#define HOUR
Definition: datetime.h:101
#define DTK_ZULU
Definition: datetime.h:160
int tm_sec
Definition: pgtime.h:27
#define DTZMOD
Definition: datetime.h:123
int tm_min
Definition: pgtime.h:28
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1613
long val
Definition: informix.c:689
#define DTK_DATE
Definition: datetime.h:145
#define HR24
Definition: datetime.h:74
#define DTK_SPECIAL
Definition: datetime.h:150
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2463

◆ DecodeInterval()

int DecodeInterval ( char **  field,
int *  ftype,
int  nf,
int  range,
int *  dtype,
struct pg_tm tm,
fsec_t fsec 
)

Definition at line 3079 of file datetime.c.

References AdjustFractDays(), AdjustFractSeconds(), AGO, Assert, CENTURY, ClearPgTm(), DAY, DAYS_PER_MONTH, DECADE, DecodeTime(), 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, RESERV, rint(), SECOND, SECS_PER_DAY, SECS_PER_HOUR, SECS_PER_MINUTE, strtoint(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, generate_unaccent_rules::type, UNITS, USECS_PER_SEC, val, WEEK, and YEAR.

Referenced by interval_in(), and reltimein().

3081 {
3082  bool is_before = false;
3083  char *cp;
3084  int fmask = 0,
3085  tmask,
3086  type;
3087  int i;
3088  int dterr;
3089  int val;
3090  double fval;
3091 
3092  *dtype = DTK_DELTA;
3093  type = IGNORE_DTF;
3094  ClearPgTm(tm, fsec);
3095 
3096  /* read through list backwards to pick up units before values */
3097  for (i = nf - 1; i >= 0; i--)
3098  {
3099  switch (ftype[i])
3100  {
3101  case DTK_TIME:
3102  dterr = DecodeTime(field[i], fmask, range,
3103  &tmask, tm, fsec);
3104  if (dterr)
3105  return dterr;
3106  type = DTK_DAY;
3107  break;
3108 
3109  case DTK_TZ:
3110 
3111  /*
3112  * Timezone means a token with a leading sign character and at
3113  * least one digit; there could be ':', '.', '-' embedded in
3114  * it as well.
3115  */
3116  Assert(*field[i] == '-' || *field[i] == '+');
3117 
3118  /*
3119  * Check for signed hh:mm or hh:mm:ss. If so, process exactly
3120  * like DTK_TIME case above, plus handling the sign.
3121  */
3122  if (strchr(field[i] + 1, ':') != NULL &&
3123  DecodeTime(field[i] + 1, fmask, range,
3124  &tmask, tm, fsec) == 0)
3125  {
3126  if (*field[i] == '-')
3127  {
3128  /* flip the sign on all fields */
3129  tm->tm_hour = -tm->tm_hour;
3130  tm->tm_min = -tm->tm_min;
3131  tm->tm_sec = -tm->tm_sec;
3132  *fsec = -(*fsec);
3133  }
3134 
3135  /*
3136  * Set the next type to be a day, if units are not
3137  * specified. This handles the case of '1 +02:03' since we
3138  * are reading right to left.
3139  */
3140  type = DTK_DAY;
3141  break;
3142  }
3143 
3144  /*
3145  * Otherwise, fall through to DTK_NUMBER case, which can
3146  * handle signed float numbers and signed year-month values.
3147  */
3148 
3149  /* FALL THROUGH */
3150 
3151  case DTK_DATE:
3152  case DTK_NUMBER:
3153  if (type == IGNORE_DTF)
3154  {
3155  /* use typmod to decide what rightmost field is */
3156  switch (range)
3157  {
3158  case INTERVAL_MASK(YEAR):
3159  type = DTK_YEAR;
3160  break;
3161  case INTERVAL_MASK(MONTH):
3163  type = DTK_MONTH;
3164  break;
3165  case INTERVAL_MASK(DAY):
3166  type = DTK_DAY;
3167  break;
3168  case INTERVAL_MASK(HOUR):
3170  type = DTK_HOUR;
3171  break;
3172  case INTERVAL_MASK(MINUTE):
3175  type = DTK_MINUTE;
3176  break;
3177  case INTERVAL_MASK(SECOND):
3181  type = DTK_SECOND;
3182  break;
3183  default:
3184  type = DTK_SECOND;
3185  break;
3186  }
3187  }
3188 
3189  errno = 0;
3190  val = strtoint(field[i], &cp, 10);
3191  if (errno == ERANGE)
3192  return DTERR_FIELD_OVERFLOW;
3193 
3194  if (*cp == '-')
3195  {
3196  /* SQL "years-months" syntax */
3197  int val2;
3198 
3199  val2 = strtoint(cp + 1, &cp, 10);
3200  if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
3201  return DTERR_FIELD_OVERFLOW;
3202  if (*cp != '\0')
3203  return DTERR_BAD_FORMAT;
3204  type = DTK_MONTH;
3205  if (*field[i] == '-')
3206  val2 = -val2;
3207  if (((double) val * MONTHS_PER_YEAR + val2) > INT_MAX ||
3208  ((double) val * MONTHS_PER_YEAR + val2) < INT_MIN)
3209  return DTERR_FIELD_OVERFLOW;
3210  val = val * MONTHS_PER_YEAR + val2;
3211  fval = 0;
3212  }
3213  else if (*cp == '.')
3214  {
3215  errno = 0;
3216  fval = strtod(cp, &cp);
3217  if (*cp != '\0' || errno != 0)
3218  return DTERR_BAD_FORMAT;
3219 
3220  if (*field[i] == '-')
3221  fval = -fval;
3222  }
3223  else if (*cp == '\0')
3224  fval = 0;
3225  else
3226  return DTERR_BAD_FORMAT;
3227 
3228  tmask = 0; /* DTK_M(type); */
3229 
3230  switch (type)
3231  {
3232  case DTK_MICROSEC:
3233  *fsec += rint(val + fval);
3234  tmask = DTK_M(MICROSECOND);
3235  break;
3236 
3237  case DTK_MILLISEC:
3238  /* avoid overflowing the fsec field */
3239  tm->tm_sec += val / 1000;
3240  val -= (val / 1000) * 1000;
3241  *fsec += rint((val + fval) * 1000);
3242  tmask = DTK_M(MILLISECOND);
3243  break;
3244 
3245  case DTK_SECOND:
3246  tm->tm_sec += val;
3247  *fsec += rint(fval * 1000000);
3248 
3249  /*
3250  * If any subseconds were specified, consider this
3251  * microsecond and millisecond input as well.
3252  */
3253  if (fval == 0)
3254  tmask = DTK_M(SECOND);
3255  else
3256  tmask = DTK_ALL_SECS_M;
3257  break;
3258 
3259  case DTK_MINUTE:
3260  tm->tm_min += val;
3261  AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
3262  tmask = DTK_M(MINUTE);
3263  break;
3264 
3265  case DTK_HOUR:
3266  tm->tm_hour += val;
3267  AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
3268  tmask = DTK_M(HOUR);
3269  type = DTK_DAY; /* set for next field */
3270  break;
3271 
3272  case DTK_DAY:
3273  tm->tm_mday += val;
3274  AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
3275  tmask = DTK_M(DAY);
3276  break;
3277 
3278  case DTK_WEEK:
3279  tm->tm_mday += val * 7;
3280  AdjustFractDays(fval, tm, fsec, 7);
3281  tmask = DTK_M(WEEK);
3282  break;
3283 
3284  case DTK_MONTH:
3285  tm->tm_mon += val;
3286  AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
3287  tmask = DTK_M(MONTH);
3288  break;
3289 
3290  case DTK_YEAR:
3291  tm->tm_year += val;
3292  if (fval != 0)
3293  tm->tm_mon += fval * MONTHS_PER_YEAR;
3294  tmask = DTK_M(YEAR);
3295  break;
3296 
3297  case DTK_DECADE:
3298  tm->tm_year += val * 10;
3299  if (fval != 0)
3300  tm->tm_mon += fval * MONTHS_PER_YEAR * 10;
3301  tmask = DTK_M(DECADE);
3302  break;
3303 
3304  case DTK_CENTURY:
3305  tm->tm_year += val * 100;
3306  if (fval != 0)
3307  tm->tm_mon += fval * MONTHS_PER_YEAR * 100;
3308  tmask = DTK_M(CENTURY);
3309  break;
3310 
3311  case DTK_MILLENNIUM:
3312  tm->tm_year += val * 1000;
3313  if (fval != 0)
3314  tm->tm_mon += fval * MONTHS_PER_YEAR * 1000;
3315  tmask = DTK_M(MILLENNIUM);
3316  break;
3317 
3318  default:
3319  return DTERR_BAD_FORMAT;
3320  }
3321  break;
3322 
3323  case DTK_STRING:
3324  case DTK_SPECIAL:
3325  type = DecodeUnits(i, field[i], &val);
3326  if (type == IGNORE_DTF)
3327  continue;
3328 
3329  tmask = 0; /* DTK_M(type); */
3330  switch (type)
3331  {
3332  case UNITS:
3333  type = val;
3334  break;
3335 
3336  case AGO:
3337  is_before = true;
3338  type = val;
3339  break;
3340 
3341  case RESERV:
3342  tmask = (DTK_DATE_M | DTK_TIME_M);
3343  *dtype = val;
3344  break;
3345 
3346  default:
3347  return DTERR_BAD_FORMAT;
3348  }
3349  break;
3350 
3351  default:
3352  return DTERR_BAD_FORMAT;
3353  }
3354 
3355  if (tmask & fmask)
3356  return DTERR_BAD_FORMAT;
3357  fmask |= tmask;
3358  }
3359 
3360  /* ensure that at least one time field has been found */
3361  if (fmask == 0)
3362  return DTERR_BAD_FORMAT;
3363 
3364  /* ensure fractional seconds are fractional */
3365  if (*fsec != 0)
3366  {
3367  int sec;
3368 
3369  sec = *fsec / USECS_PER_SEC;
3370  *fsec -= sec * USECS_PER_SEC;
3371  tm->tm_sec += sec;
3372  }
3373 
3374  /*----------
3375  * The SQL standard defines the interval literal
3376  * '-1 1:00:00'
3377  * to mean "negative 1 days and negative 1 hours", while Postgres
3378  * traditionally treats this as meaning "negative 1 days and positive
3379  * 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
3380  * to all fields if there are no other explicit signs.
3381  *
3382  * We leave the signs alone if there are additional explicit signs.
3383  * This protects us against misinterpreting postgres-style dump output,
3384  * since the postgres-style output code has always put an explicit sign on
3385  * all fields following a negative field. But note that SQL-spec output
3386  * is ambiguous and can be misinterpreted on load! (So it's best practice
3387  * to dump in postgres style, not SQL style.)
3388  *----------
3389  */
3390  if (IntervalStyle == INTSTYLE_SQL_STANDARD && *field[0] == '-')
3391  {
3392  /* Check for additional explicit signs */
3393  bool more_signs = false;
3394 
3395  for (i = 1; i < nf; i++)
3396  {
3397  if (*field[i] == '-' || *field[i] == '+')
3398  {
3399  more_signs = true;
3400  break;
3401  }
3402  }
3403 
3404  if (!more_signs)
3405  {
3406  /*
3407  * Rather than re-determining which field was field[0], just force
3408  * 'em all negative.
3409  */
3410  if (*fsec > 0)
3411  *fsec = -(*fsec);
3412  if (tm->tm_sec > 0)
3413  tm->tm_sec = -tm->tm_sec;
3414  if (tm->tm_min > 0)
3415  tm->tm_min = -tm->tm_min;
3416  if (tm->tm_hour > 0)
3417  tm->tm_hour = -tm->tm_hour;
3418  if (tm->tm_mday > 0)
3419  tm->tm_mday = -tm->tm_mday;
3420  if (tm->tm_mon > 0)
3421  tm->tm_mon = -tm->tm_mon;
3422  if (tm->tm_year > 0)
3423  tm->tm_year = -tm->tm_year;
3424  }
3425  }
3426 
3427  /* finally, AGO negates everything */
3428  if (is_before)
3429  {
3430  *fsec = -(*fsec);
3431  tm->tm_sec = -tm->tm_sec;
3432  tm->tm_min = -tm->tm_min;
3433  tm->tm_hour = -tm->tm_hour;
3434  tm->tm_mday = -tm->tm_mday;
3435  tm->tm_mon = -tm->tm_mon;
3436  tm->tm_year = -tm->tm_year;
3437  }
3438 
3439  return 0;
3440 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_CENTURY
Definition: datetime.h:172
#define DAY
Definition: datetime.h:94
#define UNITS
Definition: datetime.h:108
#define IGNORE_DTF
Definition: datetime.h:99
#define DTK_WEEK
Definition: datetime.h:167
#define DTK_YEAR
Definition: datetime.h:170
#define MILLENNIUM
Definition: datetime.h:121
#define USECS_PER_SEC
Definition: timestamp.h:94
#define YEAR
Definition: datetime.h:93
#define CENTURY
Definition: datetime.h:120
#define DTK_DELTA
Definition: datetime.h:162
int tm_hour
Definition: pgtime.h:29
#define DECADE
Definition: datetime.h:119
#define AGO
Definition: datetime.h:111
#define DTK_TIME_M
Definition: datetime.h:195
#define DTK_MILLENNIUM
Definition: datetime.h:173
int IntervalStyle
Definition: globals.c:118
#define SECOND
Definition: datetime.h:103
int DecodeUnits(int field, char *lowtoken, int *val)
Definition: datetime.c:3712
static void AdjustFractSeconds(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
Definition: datetime.c:468
#define DTK_DATE_M
Definition: datetime.h:194
#define DTK_MONTH
Definition: datetime.h:168
#define DTK_MILLISEC
Definition: datetime.h:174
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define DTK_DECADE
Definition: datetime.h:171
#define DTK_TZ
Definition: datetime.h:147
#define DTK_HOUR
Definition: datetime.h:165
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define MILLISECOND
Definition: datetime.h:104
#define SECS_PER_DAY
Definition: timestamp.h:86
#define DTK_SECOND
Definition: datetime.h:163
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
#define DTK_NUMBER
Definition: datetime.h:142
#define MINUTE
Definition: datetime.h:102
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:416
double rint(double x)
Definition: rint.c:22
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define MONTH
Definition: datetime.h:92
#define DTK_MINUTE
Definition: datetime.h:164
#define DTK_MICROSEC
Definition: datetime.h:175
#define DAYS_PER_MONTH
Definition: timestamp.h:77
static void AdjustFractDays(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
Definition: datetime.c:483
#define WEEK
Definition: datetime.h:118
#define DTK_TIME
Definition: datetime.h:146
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2542
static void ClearPgTm(struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:3055
#define Assert(condition)
Definition: c.h:699
#define DTK_STRING
Definition: datetime.h:143
#define DTK_DAY
Definition: datetime.h:166
#define RESERV
Definition: datetime.h:91
#define DTK_ALL_SECS_M
Definition: datetime.h:193
#define INTERVAL_MASK(b)
Definition: timestamp.h:45
#define INTSTYLE_SQL_STANDARD
Definition: miscadmin.h:234
int tm_year
Definition: pgtime.h:32
int i
#define DTK_M(t)
Definition: datetime.h:190
#define HOUR
Definition: datetime.h:101
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
long val
Definition: informix.c:689
#define DTK_DATE
Definition: datetime.h:145
#define DTK_SPECIAL
Definition: datetime.h:150
#define MICROSECOND
Definition: datetime.h:105

◆ DecodeISO8601Interval()

int DecodeISO8601Interval ( char *  str,
int *  dtype,
struct pg_tm tm,
fsec_t fsec 
)

Definition at line 3505 of file datetime.c.

References AdjustFractDays(), AdjustFractSeconds(), ClearPgTm(), DAYS_PER_MONTH, DTERR_BAD_FORMAT, DTK_DELTA, ISO8601IntegerWidth(), MONTHS_PER_YEAR, ParseISO8601Number(), SECS_PER_DAY, SECS_PER_HOUR, SECS_PER_MINUTE, generate_unaccent_rules::str, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, and val.

Referenced by interval_in(), and reltimein().

3507 {
3508  bool datepart = true;
3509  bool havefield = false;
3510 
3511  *dtype = DTK_DELTA;
3512  ClearPgTm(tm, fsec);
3513 
3514  if (strlen(str) < 2 || str[0] != 'P')
3515  return DTERR_BAD_FORMAT;
3516 
3517  str++;
3518  while (*str)
3519  {
3520  char *fieldstart;
3521  int val;
3522  double fval;
3523  char unit;
3524  int dterr;
3525 
3526  if (*str == 'T') /* T indicates the beginning of the time part */
3527  {
3528  datepart = false;
3529  havefield = false;
3530  str++;
3531  continue;
3532  }
3533 
3534  fieldstart = str;
3535  dterr = ParseISO8601Number(str, &str, &val, &fval);
3536  if (dterr)
3537  return dterr;
3538 
3539  /*
3540  * Note: we could step off the end of the string here. Code below
3541  * *must* exit the loop if unit == '\0'.
3542  */
3543  unit = *str++;
3544 
3545  if (datepart)
3546  {
3547  switch (unit) /* before T: Y M W D */
3548  {
3549  case 'Y':
3550  tm->tm_year += val;
3551  tm->tm_mon += (fval * MONTHS_PER_YEAR);
3552  break;
3553  case 'M':
3554  tm->tm_mon += val;
3555  AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
3556  break;
3557  case 'W':
3558  tm->tm_mday += val * 7;
3559  AdjustFractDays(fval, tm, fsec, 7);
3560  break;
3561  case 'D':
3562  tm->tm_mday += val;
3563  AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
3564  break;
3565  case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
3566  case '\0':
3567  if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
3568  {
3569  tm->tm_year += val / 10000;
3570  tm->tm_mon += (val / 100) % 100;
3571  tm->tm_mday += val % 100;
3572  AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
3573  if (unit == '\0')
3574  return 0;
3575  datepart = false;
3576  havefield = false;
3577  continue;
3578  }
3579  /* Else fall through to extended alternative format */
3580  case '-': /* ISO 8601 4.4.3.3 Alternative Format,
3581  * Extended */
3582  if (havefield)
3583  return DTERR_BAD_FORMAT;
3584 
3585  tm->tm_year += val;
3586  tm->tm_mon += (fval * MONTHS_PER_YEAR);
3587  if (unit == '\0')
3588  return 0;
3589  if (unit == 'T')
3590  {
3591  datepart = false;
3592  havefield = false;
3593  continue;
3594  }
3595 
3596  dterr = ParseISO8601Number(str, &str, &val, &fval);
3597  if (dterr)
3598  return dterr;
3599  tm->tm_mon += val;
3600  AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
3601  if (*str == '\0')
3602  return 0;
3603  if (*str == 'T')
3604  {
3605  datepart = false;
3606  havefield = false;
3607  continue;
3608  }
3609  if (*str != '-')
3610  return DTERR_BAD_FORMAT;
3611  str++;
3612 
3613  dterr = ParseISO8601Number(str, &str, &val, &fval);
3614  if (dterr)
3615  return dterr;
3616  tm->tm_mday += val;
3617  AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
3618  if (*str == '\0')
3619  return 0;
3620  if (*str == 'T')
3621  {
3622  datepart = false;
3623  havefield = false;
3624  continue;
3625  }
3626  return DTERR_BAD_FORMAT;
3627  default:
3628  /* not a valid date unit suffix */
3629  return DTERR_BAD_FORMAT;
3630  }
3631  }
3632  else
3633  {
3634  switch (unit) /* after T: H M S */
3635  {
3636  case 'H':
3637  tm->tm_hour += val;
3638  AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
3639  break;
3640  case 'M':
3641  tm->tm_min += val;
3642  AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
3643  break;
3644  case 'S':
3645  tm->tm_sec += val;
3646  AdjustFractSeconds(fval, tm, fsec, 1);
3647  break;
3648  case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
3649  if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
3650  {
3651  tm->tm_hour += val / 10000;
3652  tm->tm_min += (val / 100) % 100;
3653  tm->tm_sec += val % 100;
3654  AdjustFractSeconds(fval, tm, fsec, 1);
3655  return 0;
3656  }
3657  /* Else fall through to extended alternative format */
3658  case ':': /* ISO 8601 4.4.3.3 Alternative Format,
3659  * Extended */
3660  if (havefield)
3661  return DTERR_BAD_FORMAT;
3662 
3663  tm->tm_hour += val;
3664  AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
3665  if (unit == '\0')
3666  return 0;
3667 
3668  dterr = ParseISO8601Number(str, &str, &val, &fval);
3669  if (dterr)
3670  return dterr;
3671  tm->tm_min += val;
3672  AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
3673  if (*str == '\0')
3674  return 0;
3675  if (*str != ':')
3676  return DTERR_BAD_FORMAT;
3677  str++;
3678 
3679  dterr = ParseISO8601Number(str, &str, &val, &fval);
3680  if (dterr)
3681  return dterr;
3682  tm->tm_sec += val;
3683  AdjustFractSeconds(fval, tm, fsec, 1);
3684  if (*str == '\0')
3685  return 0;
3686  return DTERR_BAD_FORMAT;
3687 
3688  default:
3689  /* not a valid time unit suffix */
3690  return DTERR_BAD_FORMAT;
3691  }
3692  }
3693 
3694  havefield = true;
3695  }
3696 
3697  return 0;
3698 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define DTK_DELTA
Definition: datetime.h:162
int tm_hour
Definition: pgtime.h:29
static void AdjustFractSeconds(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
Definition: datetime.c:468
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define SECS_PER_DAY
Definition: timestamp.h:86
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define SECS_PER_MINUTE
Definition: timestamp.h:88
#define SECS_PER_HOUR
Definition: timestamp.h:87
#define DAYS_PER_MONTH
Definition: timestamp.h:77
static void AdjustFractDays(double frac, struct pg_tm *tm, fsec_t *fsec, int scale)
Definition: datetime.c:483
static void ClearPgTm(struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:3055
static int ISO8601IntegerWidth(char *fieldstart)
Definition: datetime.c:3478
int tm_year
Definition: pgtime.h:32
static int ParseISO8601Number(char *str, char **endptr, int *ipart, double *fpart)
Definition: datetime.c:3450
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
long val
Definition: informix.c:689

◆ DecodeSpecial()

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

Definition at line 3023 of file datetime.c.

References datebsearch(), szdatetktbl, datetkn::token, TOKMAXLEN, generate_unaccent_rules::type, datetkn::type, UNKNOWN_FIELD, and datetkn::value.

Referenced by DecodeDate(), DecodeDateTime(), DecodeTimeOnly(), interval_part(), time_part(), timestamp_part(), timestamptz_part(), and timetz_part().

3024 {
3025  int type;
3026  const datetkn *tp;
3027 
3028  tp = datecache[field];
3029  /* use strncmp so that we match truncated tokens */
3030  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3031  {
3032  tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
3033  }
3034  if (tp == NULL)
3035  {
3036  type = UNKNOWN_FIELD;
3037  *val = 0;
3038  }
3039  else
3040  {
3041  datecache[field] = tp;
3042  type = tp->type;
3043  *val = tp->value;
3044  }
3045 
3046  return type;
3047 }
static const datetkn datetktbl[]
Definition: datetime.c:91
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:214
static int szdatetktbl
Definition: datetime.c:169
char token[TOKMAXLEN+1]
Definition: datetime.h:212
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3794
char type
Definition: datetime.h:213
static const datetkn * datecache[MAXDATEFIELDS]
Definition: datetime.c:248
#define TOKMAXLEN
Definition: datetime.h:207
long val
Definition: informix.c:689

◆ DecodeTimeOnly()

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

Definition at line 1728 of file datetime.c.

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_CURRENT, 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(), MINS_PER_HOUR, MINUTE, MONTH, ParseFractionalSecond(), pg_get_timezone_offset(), pg_tzset(), PM, RESERV, SECOND, SECS_PER_MINUTE, session_timezone, strtoint(), 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, USECS_PER_SEC, val, ValidateDate(), and YEAR.

Referenced by time_in(), and timetz_in().

1730 {
1731  int fmask = 0,
1732  tmask,
1733  type;
1734  int ptype = 0; /* "prefix type" for ISO h04mm05s06 format */
1735  int i;
1736  int val;
1737  int dterr;
1738  bool isjulian = false;
1739  bool is2digits = false;
1740  bool bc = false;
1741  int mer = HR24;
1742  pg_tz *namedTz = NULL;
1743  pg_tz *abbrevTz = NULL;
1744  char *abbrev = NULL;
1745  pg_tz *valtz;
1746 
1747  *dtype = DTK_TIME;
1748  tm->tm_hour = 0;
1749  tm->tm_min = 0;
1750  tm->tm_sec = 0;
1751  *fsec = 0;
1752  /* don't know daylight savings time status apriori */
1753  tm->tm_isdst = -1;
1754 
1755  if (tzp != NULL)
1756  *tzp = 0;
1757 
1758  for (i = 0; i < nf; i++)
1759  {
1760  switch (ftype[i])
1761  {
1762  case DTK_DATE:
1763 
1764  /*
1765  * Time zone not allowed? Then should not accept dates or time
1766  * zones no matter what else!
1767  */
1768  if (tzp == NULL)
1769  return DTERR_BAD_FORMAT;
1770 
1771  /* Under limited circumstances, we will accept a date... */
1772  if (i == 0 && nf >= 2 &&
1773  (ftype[nf - 1] == DTK_DATE || ftype[1] == DTK_TIME))
1774  {
1775  dterr = DecodeDate(field[i], fmask,
1776  &tmask, &is2digits, tm);
1777  if (dterr)
1778  return dterr;
1779  }
1780  /* otherwise, this is a time and/or time zone */
1781  else
1782  {
1783  if (isdigit((unsigned char) *field[i]))
1784  {
1785  char *cp;
1786 
1787  /*
1788  * Starts with a digit but we already have a time
1789  * field? Then we are in trouble with time already...
1790  */
1791  if ((fmask & DTK_TIME_M) == DTK_TIME_M)
1792  return DTERR_BAD_FORMAT;
1793 
1794  /*
1795  * Should not get here and fail. Sanity check only...
1796  */
1797  if ((cp = strchr(field[i], '-')) == NULL)
1798  return DTERR_BAD_FORMAT;
1799 
1800  /* Get the time zone from the end of the string */
1801  dterr = DecodeTimezone(cp, tzp);
1802  if (dterr)
1803  return dterr;
1804  *cp = '\0';
1805 
1806  /*
1807  * Then read the rest of the field as a concatenated
1808  * time
1809  */
1810  dterr = DecodeNumberField(strlen(field[i]), field[i],
1811  (fmask | DTK_DATE_M),
1812  &tmask, tm,
1813  fsec, &is2digits);
1814  if (dterr < 0)
1815  return dterr;
1816  ftype[i] = dterr;
1817 
1818  tmask |= DTK_M(TZ);
1819  }
1820  else
1821  {
1822  namedTz = pg_tzset(field[i]);
1823  if (!namedTz)
1824  {
1825  /*
1826  * We should return an error code instead of
1827  * ereport'ing directly, but then there is no way
1828  * to report the bad time zone name.
1829  */
1830  ereport(ERROR,
1831  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1832  errmsg("time zone \"%s\" not recognized",
1833  field[i])));
1834  }
1835  /* we'll apply the zone setting below */
1836  ftype[i] = DTK_TZ;
1837  tmask = DTK_M(TZ);
1838  }
1839  }
1840  break;
1841 
1842  case DTK_TIME:
1843  dterr = DecodeTime(field[i], (fmask | DTK_DATE_M),
1845  &tmask, tm, fsec);
1846  if (dterr)
1847  return dterr;
1848  break;
1849 
1850  case DTK_TZ:
1851  {
1852  int tz;
1853 
1854  if (tzp == NULL)
1855  return DTERR_BAD_FORMAT;
1856 
1857  dterr = DecodeTimezone(field[i], &tz);
1858  if (dterr)
1859  return dterr;
1860  *tzp = tz;
1861  tmask = DTK_M(TZ);
1862  }
1863  break;
1864 
1865  case DTK_NUMBER:
1866 
1867  /*
1868  * Was this an "ISO time" with embedded field labels? An
1869  * example is "h04m05s06" - thomas 2001-02-04
1870  */
1871  if (ptype != 0)
1872  {
1873  char *cp;
1874  int val;
1875 
1876  /* Only accept a date under limited circumstances */
1877  switch (ptype)
1878  {
1879  case DTK_JULIAN:
1880  case DTK_YEAR:
1881  case DTK_MONTH:
1882  case DTK_DAY:
1883  if (tzp == NULL)
1884  return DTERR_BAD_FORMAT;
1885  default:
1886  break;
1887  }
1888 
1889  errno = 0;
1890  val = strtoint(field[i], &cp, 10);
1891  if (errno == ERANGE)
1892  return DTERR_FIELD_OVERFLOW;
1893 
1894  /*
1895  * only a few kinds are allowed to have an embedded
1896  * decimal
1897  */
1898  if (*cp == '.')
1899  switch (ptype)
1900  {
1901  case DTK_JULIAN:
1902  case DTK_TIME:
1903  case DTK_SECOND:
1904  break;
1905  default:
1906  return DTERR_BAD_FORMAT;
1907  break;
1908  }
1909  else if (*cp != '\0')
1910  return DTERR_BAD_FORMAT;
1911 
1912  switch (ptype)
1913  {
1914  case DTK_YEAR:
1915  tm->tm_year = val;
1916  tmask = DTK_M(YEAR);
1917  break;
1918 
1919  case DTK_MONTH:
1920 
1921  /*
1922  * already have a month and hour? then assume
1923  * minutes
1924  */
1925  if ((fmask & DTK_M(MONTH)) != 0 &&
1926  (fmask & DTK_M(HOUR)) != 0)
1927  {
1928  tm->tm_min = val;
1929  tmask = DTK_M(MINUTE);
1930  }
1931  else
1932  {
1933  tm->tm_mon = val;
1934  tmask = DTK_M(MONTH);
1935  }
1936  break;
1937 
1938  case DTK_DAY:
1939  tm->tm_mday = val;
1940  tmask = DTK_M(DAY);
1941  break;
1942 
1943  case DTK_HOUR:
1944  tm->tm_hour = val;
1945  tmask = DTK_M(HOUR);
1946  break;
1947 
1948  case DTK_MINUTE:
1949  tm->tm_min = val;
1950  tmask = DTK_M(MINUTE);
1951  break;
1952 
1953  case DTK_SECOND:
1954  tm->tm_sec = val;
1955  tmask = DTK_M(SECOND);
1956  if (*cp == '.')
1957  {
1958  dterr = ParseFractionalSecond(cp, fsec);
1959  if (dterr)
1960  return dterr;
1961  tmask = DTK_ALL_SECS_M;
1962  }
1963  break;
1964 
1965  case DTK_TZ:
1966  tmask = DTK_M(TZ);
1967  dterr = DecodeTimezone(field[i], tzp);
1968  if (dterr)
1969  return dterr;
1970  break;
1971 
1972  case DTK_JULIAN:
1973  /* previous field was a label for "julian date" */
1974  if (val < 0)
1975  return DTERR_FIELD_OVERFLOW;
1976  tmask = DTK_DATE_M;
1977  j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
1978  isjulian = true;
1979 
1980  if (*cp == '.')
1981  {
1982  double time;
1983 
1984  errno = 0;
1985  time = strtod(cp, &cp);
1986  if (*cp != '\0' || errno != 0)
1987  return DTERR_BAD_FORMAT;
1988  time *= USECS_PER_DAY;
1989  dt2time(time,
1990  &tm->tm_hour, &tm->tm_min,
1991  &tm->tm_sec, fsec);
1992  tmask |= DTK_TIME_M;
1993  }
1994  break;
1995 
1996  case DTK_TIME:
1997  /* previous field was "t" for ISO time */
1998  dterr = DecodeNumberField(strlen(field[i]), field[i],
1999  (fmask | DTK_DATE_M),
2000  &tmask, tm,
2001  fsec, &is2digits);
2002  if (dterr < 0)
2003  return dterr;
2004  ftype[i] = dterr;
2005 
2006  if (tmask != DTK_TIME_M)
2007  return DTERR_BAD_FORMAT;
2008  break;
2009 
2010  default:
2011  return DTERR_BAD_FORMAT;
2012  break;
2013  }
2014 
2015  ptype = 0;
2016  *dtype = DTK_DATE;
2017  }
2018  else
2019  {
2020  char *cp;
2021  int flen;
2022 
2023  flen = strlen(field[i]);
2024  cp = strchr(field[i], '.');
2025 
2026  /* Embedded decimal? */
2027  if (cp != NULL)
2028  {
2029  /*
2030  * Under limited circumstances, we will accept a
2031  * date...
2032  */
2033  if (i == 0 && nf >= 2 && ftype[nf - 1] == DTK_DATE)
2034  {
2035  dterr = DecodeDate(field[i], fmask,
2036  &tmask, &is2digits, tm);
2037  if (dterr)
2038  return dterr;
2039  }
2040  /* embedded decimal and several digits before? */
2041  else if (flen - strlen(cp) > 2)
2042  {
2043  /*
2044  * Interpret as a concatenated date or time Set
2045  * the type field to allow decoding other fields
2046  * later. Example: 20011223 or 040506
2047  */
2048  dterr = DecodeNumberField(flen, field[i],
2049  (fmask | DTK_DATE_M),
2050  &tmask, tm,
2051  fsec, &is2digits);
2052  if (dterr < 0)
2053  return dterr;
2054  ftype[i] = dterr;
2055  }
2056  else
2057  return DTERR_BAD_FORMAT;
2058  }
2059  else if (flen > 4)
2060  {
2061  dterr = DecodeNumberField(flen, field[i],
2062  (fmask | DTK_DATE_M),
2063  &tmask, tm,
2064  fsec, &is2digits);
2065  if (dterr < 0)
2066  return dterr;
2067  ftype[i] = dterr;
2068  }
2069  /* otherwise it is a single date/time field... */
2070  else
2071  {
2072  dterr = DecodeNumber(flen, field[i],
2073  false,
2074  (fmask | DTK_DATE_M),
2075  &tmask, tm,
2076  fsec, &is2digits);
2077  if (dterr)
2078  return dterr;
2079  }
2080  }
2081  break;
2082 
2083  case DTK_STRING:
2084  case DTK_SPECIAL:
2085  /* timezone abbrevs take precedence over built-in tokens */
2086  type = DecodeTimezoneAbbrev(i, field[i], &val, &valtz);
2087  if (type == UNKNOWN_FIELD)
2088  type = DecodeSpecial(i, field[i], &val);
2089  if (type == IGNORE_DTF)
2090  continue;
2091 
2092  tmask = DTK_M(type);
2093  switch (type)
2094  {
2095  case RESERV:
2096  switch (val)
2097  {
2098  case DTK_CURRENT:
2099  ereport(ERROR,
2100  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2101  errmsg("date/time value \"current\" is no longer supported")));
2102  return DTERR_BAD_FORMAT;
2103  break;
2104 
2105  case DTK_NOW:
2106  tmask = DTK_TIME_M;
2107  *dtype = DTK_TIME;
2108  GetCurrentTimeUsec(tm, fsec, NULL);
2109  break;
2110 
2111  case DTK_ZULU:
2112  tmask = (DTK_TIME_M | DTK_M(TZ));
2113  *dtype = DTK_TIME;
2114  tm->tm_hour = 0;
2115  tm->tm_min = 0;
2116  tm->tm_sec = 0;
2117  tm->tm_isdst = 0;
2118  break;
2119 
2120  default:
2121  return DTERR_BAD_FORMAT;
2122  }
2123 
2124  break;
2125 
2126  case DTZMOD:
2127 
2128  /*
2129  * daylight savings time modifier (solves "MET DST"
2130  * syntax)
2131  */
2132  tmask |= DTK_M(DTZ);
2133  tm->tm_isdst = 1;
2134  if (tzp == NULL)
2135  return DTERR_BAD_FORMAT;
2136  *tzp -= val;
2137  break;
2138 
2139  case DTZ:
2140 
2141  /*
2142  * set mask for TZ here _or_ check for DTZ later when
2143  * getting default timezone
2144  */
2145  tmask |= DTK_M(TZ);
2146  tm->tm_isdst = 1;
2147  if (tzp == NULL)
2148  return DTERR_BAD_FORMAT;
2149  *tzp = -val;
2150  ftype[i] = DTK_TZ;
2151  break;
2152 
2153  case TZ:
2154  tm->tm_isdst = 0;
2155  if (tzp == NULL)
2156  return DTERR_BAD_FORMAT;
2157  *tzp = -val;
2158  ftype[i] = DTK_TZ;
2159  break;
2160 
2161  case DYNTZ:
2162  tmask |= DTK_M(TZ);
2163  if (tzp == NULL)
2164  return DTERR_BAD_FORMAT;
2165  /* we'll determine the actual offset later */
2166  abbrevTz = valtz;
2167  abbrev = field[i];
2168  ftype[i] = DTK_TZ;
2169  break;
2170 
2171  case AMPM:
2172  mer = val;
2173  break;
2174 
2175  case ADBC:
2176  bc = (val == BC);
2177  break;
2178 
2179  case UNITS:
2180  tmask = 0;
2181  ptype = val;
2182  break;
2183 
2184  case ISOTIME:
2185  tmask = 0;
2186 
2187  /***
2188  * We will need one of the following fields:
2189  * DTK_NUMBER should be hhmmss.fff
2190  * DTK_TIME should be hh:mm:ss.fff
2191  * DTK_DATE should be hhmmss-zz
2192  ***/
2193  if (i >= nf - 1 ||
2194  (ftype[i + 1] != DTK_NUMBER &&
2195  ftype[i + 1] != DTK_TIME &&
2196  ftype[i + 1] != DTK_DATE))
2197  return DTERR_BAD_FORMAT;
2198 
2199  ptype = val;
2200  break;
2201 
2202  case UNKNOWN_FIELD:
2203 
2204  /*
2205  * Before giving up and declaring error, check to see
2206  * if it is an all-alpha timezone name.
2207  */
2208  namedTz = pg_tzset(field[i]);
2209  if (!namedTz)
2210  return DTERR_BAD_FORMAT;
2211  /* we'll apply the zone setting below */
2212  tmask = DTK_M(TZ);
2213  break;
2214 
2215  default:
2216  return DTERR_BAD_FORMAT;
2217  }
2218  break;
2219 
2220  default:
2221  return DTERR_BAD_FORMAT;
2222  }
2223 
2224  if (tmask & fmask)
2225  return DTERR_BAD_FORMAT;
2226  fmask |= tmask;
2227  } /* end loop over fields */
2228 
2229  /* do final checking/adjustment of Y/M/D fields */
2230  dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
2231  if (dterr)
2232  return dterr;
2233 
2234  /* handle AM/PM */
2235  if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
2236  return DTERR_FIELD_OVERFLOW;
2237  if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
2238  tm->tm_hour = 0;
2239  else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
2240  tm->tm_hour += HOURS_PER_DAY / 2;
2241 
2242  /*
2243  * This should match the checks in make_timestamp_internal
2244  */
2245  if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > MINS_PER_HOUR - 1 ||
2246  tm->tm_sec < 0 || tm->tm_sec > SECS_PER_MINUTE ||
2247  tm->tm_hour > HOURS_PER_DAY ||
2248  /* test for > 24:00:00 */
2249  (tm->tm_hour == HOURS_PER_DAY &&
2250  (tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)) ||
2251  *fsec < INT64CONST(0) || *fsec > USECS_PER_SEC)
2252  return DTERR_FIELD_OVERFLOW;
2253 
2254  if ((fmask & DTK_TIME_M) != DTK_TIME_M)
2255  return DTERR_BAD_FORMAT;
2256 
2257  /*
2258  * If we had a full timezone spec, compute the offset (we could not do it
2259  * before, because we may need the date to resolve DST status).
2260  */
2261  if (namedTz != NULL)
2262  {
2263  long int gmtoff;
2264 
2265  /* daylight savings time modifier disallowed with full TZ */
2266  if (fmask & DTK_M(DTZMOD))
2267  return DTERR_BAD_FORMAT;
2268 
2269  /* if non-DST zone, we do not need to know the date */
2270  if (pg_get_timezone_offset(namedTz, &gmtoff))
2271  {
2272  *tzp = -(int) gmtoff;
2273  }
2274  else
2275  {
2276  /* a date has to be specified */
2277  if ((fmask & DTK_DATE_M) != DTK_DATE_M)
2278  return DTERR_BAD_FORMAT;
2279  *tzp = DetermineTimeZoneOffset(tm, namedTz);
2280  }
2281  }
2282 
2283  /*
2284  * Likewise, if we had a dynamic timezone abbreviation, resolve it now.
2285  */
2286  if (abbrevTz != NULL)
2287  {
2288  struct pg_tm tt,
2289  *tmp = &tt;
2290 
2291  /*
2292  * daylight savings time modifier but no standard timezone? then error
2293  */
2294  if (fmask & DTK_M(DTZMOD))
2295  return DTERR_BAD_FORMAT;
2296 
2297  if ((fmask & DTK_DATE_M) == 0)
2298  GetCurrentDateTime(tmp);
2299  else
2300  {
2301  tmp->tm_year = tm->tm_year;
2302  tmp->tm_mon = tm->tm_mon;
2303  tmp->tm_mday = tm->tm_mday;
2304  }
2305  tmp->tm_hour = tm->tm_hour;
2306  tmp->tm_min = tm->tm_min;
2307  tmp->tm_sec = tm->tm_sec;
2308  *tzp = DetermineTimeZoneAbbrevOffset(tmp, abbrev, abbrevTz);
2309  tm->tm_isdst = tmp->tm_isdst;
2310  }
2311 
2312  /* timezone not specified? then use session timezone */
2313  if (tzp != NULL && !(fmask & DTK_M(TZ)))
2314  {
2315  struct pg_tm tt,
2316  *tmp = &tt;
2317 
2318  /*
2319  * daylight savings time modifier but no standard timezone? then error
2320  */
2321  if (fmask & DTK_M(DTZMOD))
2322  return DTERR_BAD_FORMAT;
2323 
2324  if ((fmask & DTK_DATE_M) == 0)
2325  GetCurrentDateTime(tmp);
2326  else
2327  {
2328  tmp->tm_year = tm->tm_year;
2329  tmp->tm_mon = tm->tm_mon;
2330  tmp->tm_mday = tm->tm_mday;
2331  }
2332  tmp->tm_hour = tm->tm_hour;
2333  tmp->tm_min = tm->tm_min;
2334  tmp->tm_sec = tm->tm_sec;
2336  tm->tm_isdst = tmp->tm_isdst;
2337  }
2338 
2339  return 0;
2340 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:354
#define PM
Definition: datetime.h:73
#define DAY
Definition: datetime.h:94
#define UNITS
Definition: datetime.h:108
#define IGNORE_DTF
Definition: datetime.h:99
PGDLLIMPORT pg_tz * session_timezone
Definition: pgtz.c:28
#define DTK_JULIAN
Definition: datetime.h:176
#define DTK_YEAR
Definition: datetime.h:170
int tm_isdst
Definition: pgtime.h:35
#define USECS_PER_SEC
Definition: timestamp.h:94
#define YEAR
Definition: datetime.h:93
int tm_hour
Definition: pgtime.h:29
#define DTK_TIME_M
Definition: datetime.h:195
int errcode(int sqlerrcode)
Definition: elog.c:575
#define TZ
Definition: datetime.h:96
#define UNKNOWN_FIELD
Definition: datetime.h:125
#define SECOND
Definition: datetime.h:103
static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct pg_tm *tm, fsec_t *fsec, bool *is2digits)
Definition: datetime.c:2803
#define ADBC
Definition: datetime.h:109
Definition: pgtime.h:25
#define DTK_CURRENT
Definition: datetime.h:152
#define INTERVAL_FULL_RANGE
Definition: timestamp.h:48
#define DTK_DATE_M
Definition: datetime.h:194
#define MINS_PER_HOUR
Definition: timestamp.h:89
pg_tz * pg_tzset(const char *tzname)
Definition: pgtz.c:236
#define DTK_MONTH
Definition: datetime.h:168
#define DTK_TZ
Definition: datetime.h:147
#define DTK_HOUR
Definition: datetime.h:165
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
#define AM
Definition: datetime.h:72
int DecodeTimezoneAbbrev(int field, char *lowtoken, int *offset, pg_tz **tz)
Definition: datetime.c:2968
#define DTK_SECOND
Definition: datetime.h:163
int DecodeTimezone(char *str, int *tzp)
Definition: datetime.c:2890
int tm_mday
Definition: pgtime.h:30
#define HOURS_PER_DAY
Definition: timestamp.h:78
int tm_mon
Definition: pgtime.h:31
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1455
#define SECS_PER_MINUTE
Definition: timestamp.h:88
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits, struct pg_tm *tm)
Definition: datetime.c:2353
void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp)
Definition: datetime.c:371
#define DTK_NUMBER
Definition: datetime.h:142
#define MINUTE
Definition: datetime.h:102
#define USECS_PER_DAY
Definition: timestamp.h:91
#define ereport(elevel, rest)
Definition: elog.h:122
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:301
#define MONTH
Definition: datetime.h:92
#define DTK_MINUTE
Definition: datetime.h:164
static int ParseFractionalSecond(char *cp, fsec_t *fsec)
Definition: datetime.c:498
#define BC
Definition: datetime.h:77
Definition: pgtz.h:59
#define ISOTIME
Definition: datetime.h:116
#define DTK_TIME
Definition: datetime.h:146
static int DecodeTime(char *str, int fmask, int range, int *tmask, struct pg_tm *tm, fsec_t *fsec)
Definition: datetime.c:2542
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1731
#define AMPM
Definition: datetime.h:100
#define DTK_STRING
Definition: datetime.h:143
#define DTK_DAY
Definition: datetime.h:166
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:2618
#define RESERV
Definition: datetime.h:91
int DecodeSpecial(int field, char *lowtoken, int *val)
Definition: datetime.c:3023
#define DTK_ALL_SECS_M
Definition: datetime.h:193
#define DTZ
Definition: datetime.h:97
int tm_year
Definition: pgtime.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define DYNTZ
Definition: datetime.h:98
#define DTK_NOW
Definition: datetime.h:156
int i
#define DTK_M(t)
Definition: datetime.h:190
#define HOUR
Definition: datetime.h:101
bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
Definition: localtime.c:1800
#define DTK_ZULU
Definition: datetime.h:160
int tm_sec
Definition: pgtime.h:27
#define DTZMOD
Definition: datetime.h:123
int tm_min
Definition: pgtime.h:28
int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp)
Definition: datetime.c:1613
long val
Definition: informix.c:689
#define DTK_DATE
Definition: datetime.h:145
#define HR24
Definition: datetime.h:74
#define DTK_SPECIAL
Definition: datetime.h:150
int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc, struct pg_tm *tm)
Definition: datetime.c:2463

◆ DecodeTimezone()

int DecodeTimezone ( char *  str,
int *  tzp 
)

Definition at line 2890 of file datetime.c.

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

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

2891 {
2892  int tz;
2893  int hr,
2894  min,
2895  sec = 0;
2896  char *cp;
2897 
2898  /* leading character must be "+" or "-" */
2899  if (*str != '+' && *str != '-')
2900  return DTERR_BAD_FORMAT;
2901 
2902  errno = 0;
2903  hr = strtoint(str + 1, &cp, 10);
2904  if (errno == ERANGE)
2905  return DTERR_TZDISP_OVERFLOW;
2906 
2907  /* explicit delimiter? */
2908  if (*cp == ':')
2909  {
2910  errno = 0;
2911  min = strtoint(cp + 1, &cp, 10);
2912  if (errno == ERANGE)
2913  return DTERR_TZDISP_OVERFLOW;
2914  if (*cp == ':')
2915  {
2916  errno = 0;
2917  sec = strtoint(cp + 1, &cp, 10);
2918  if (errno == ERANGE)
2919  return DTERR_TZDISP_OVERFLOW;
2920  }
2921  }
2922  /* otherwise, might have run things together... */
2923  else if (*cp == '\0' && strlen(str) > 3)
2924  {
2925  min = hr % 100;
2926  hr = hr / 100;
2927  /* we could, but don't, support a run-together hhmmss format */
2928  }
2929  else
2930  min = 0;
2931 
2932  /* Range-check the values; see notes in datatype/timestamp.h */
2933  if (hr < 0 || hr > MAX_TZDISP_HOUR)
2934  return DTERR_TZDISP_OVERFLOW;
2935  if (min < 0 || min >= MINS_PER_HOUR)
2936  return DTERR_TZDISP_OVERFLOW;
2937  if (sec < 0 || sec >= SECS_PER_MINUTE)
2938  return DTERR_TZDISP_OVERFLOW;
2939 
2940  tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
2941  if (*str == '-')
2942  tz = -tz;
2943 
2944  *tzp = -tz;
2945 
2946  if (*cp != '\0')
2947  return DTERR_BAD_FORMAT;
2948 
2949  return 0;
2950 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define MINS_PER_HOUR
Definition: timestamp.h:89
#define MAX_TZDISP_HOUR
Definition: timestamp.h:103
#define SECS_PER_MINUTE
Definition: timestamp.h:88
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:286

◆ DecodeTimezoneAbbrev()

int DecodeTimezoneAbbrev ( int  field,
char *  lowtoken,
int *  offset,
pg_tz **  tz 
)

Definition at line 2968 of file datetime.c.

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

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

2970 {
2971  int type;
2972  const datetkn *tp;
2973 
2974  tp = abbrevcache[field];
2975  /* use strncmp so that we match truncated tokens */
2976  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
2977  {
2978  if (zoneabbrevtbl)
2979  tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
2981  else
2982  tp = NULL;
2983  }
2984  if (tp == NULL)
2985  {
2986  type = UNKNOWN_FIELD;
2987  *offset = 0;
2988  *tz = NULL;
2989  }
2990  else
2991  {
2992  abbrevcache[field] = tp;
2993  type = tp->type;
2994  if (type == DYNTZ)
2995  {
2996  *offset = 0;
2998  }
2999  else
3000  {
3001  *offset = tp->value;
3002  *tz = NULL;
3003  }
3004  }
3005 
3006  return type;
3007 }
static pg_tz * FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp)
Definition: datetime.c:4598
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:214
char token[TOKMAXLEN+1]
Definition: datetime.h:212
datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:222
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3794
char type
Definition: datetime.h:213
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:244
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:252
#define DYNTZ
Definition: datetime.h:98
#define TOKMAXLEN
Definition: datetime.h:207

◆ DecodeUnits()

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

Definition at line 3712 of file datetime.c.

3713 {
3714  int type;
3715  const datetkn *tp;
3716 
3717  tp = deltacache[field];
3718  /* use strncmp so that we match truncated tokens */
3719  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3720  {
3721  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3722  }
3723  if (tp == NULL)
3724  {
3725  type = UNKNOWN_FIELD;
3726  *val = 0;
3727  }
3728  else
3729  {
3730  deltacache[field] = tp;
3731  type = tp->type;
3732  *val = tp->value;
3733  }
3734 
3735  return type;
3736 } /* DecodeUnits() */
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:250
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:214
char token[TOKMAXLEN+1]
Definition: datetime.h:212
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3794
static const datetkn deltatktbl[]
Definition: datetime.c:175
static int szdeltatktbl
Definition: datetime.c:242
char type
Definition: datetime.h:213
#define TOKMAXLEN
Definition: datetime.h:207
long val
Definition: informix.c:689

◆ DetermineTimeZoneAbbrevOffset()

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

Definition at line 1613 of file datetime.c.

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

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

1614 {
1615  pg_time_t t;
1616  int zone_offset;
1617  int abbr_offset;
1618  int abbr_isdst;
1619 
1620  /*
1621  * Compute the UTC time we want to probe at. (In event of overflow, we'll
1622  * probe at the epoch, which is a bit random but probably doesn't matter.)
1623  */
1624  zone_offset = DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1625 
1626  /*
1627  * Try to match the abbreviation to something in the zone definition.
1628  */
1629  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1630  &abbr_offset, &abbr_isdst))
1631  {
1632  /* Success, so use the abbrev-specific answers. */
1633  tm->tm_isdst = abbr_isdst;
1634  return abbr_offset;
1635  }
1636 
1637  /*
1638  * No match, so use the answers we already got from
1639  * DetermineTimeZoneOffsetInternal.
1640  */
1641  return zone_offset;
1642 }
int64 pg_time_t
Definition: pgtime.h:23
int tm_isdst
Definition: pgtime.h:35
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
Definition: datetime.c:1477
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1688

◆ DetermineTimeZoneAbbrevOffsetTS()

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

Definition at line 1651 of file datetime.c.

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

Referenced by pg_timezone_abbrevs(), and timestamptz_zone().

1653 {
1655  int zone_offset;
1656  int abbr_offset;
1657  int tz;
1658  struct pg_tm tm;
1659  fsec_t fsec;
1660 
1661  /*
1662  * If the abbrev matches anything in the zone data, this is pretty easy.
1663  */
1664  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1665  &abbr_offset, isdst))
1666  return abbr_offset;
1667 
1668  /*
1669  * Else, break down the timestamp so we can use DetermineTimeZoneOffset.
1670  */
1671  if (timestamp2tm(ts, &tz, &tm, &fsec, NULL, tzp) != 0)
1672  ereport(ERROR,
1673  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1674  errmsg("timestamp out of range")));
1675 
1676  zone_offset = DetermineTimeZoneOffset(&tm, tzp);
1677  *isdst = tm.tm_isdst;
1678  return zone_offset;
1679 }
int64 pg_time_t
Definition: pgtime.h:23
int tm_isdst
Definition: pgtime.h:35
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: pgtime.h:25
static struct pg_tm tm
Definition: localtime.c:107
#define ERROR
Definition: elog.h:43
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1455
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1692
int32 fsec_t
Definition: timestamp.h:41
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1688

◆ DetermineTimeZoneOffset()

int DetermineTimeZoneOffset ( struct pg_tm tm,
pg_tz tzp 
)

Definition at line 1455 of file datetime.c.

References DetermineTimeZoneOffsetInternal().

Referenced by date2timestamptz(), DecodeDateTime(), DecodeTimeOnly(), DetermineTimeZoneAbbrevOffsetTS(), parse_sane_timezone(), time_timetz(), timestamp2timestamptz(), timestamp_abstime(), timestamp_zone(), timestamptz_pl_interval(), timestamptz_trunc(), and to_timestamp().

1456 {
1457  pg_time_t t;
1458 
1459  return DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1460 }
int64 pg_time_t
Definition: pgtime.h:23
static int DetermineTimeZoneOffsetInternal(struct pg_tm *tm, pg_tz *tzp, pg_time_t *tp)
Definition: datetime.c:1477

◆ EncodeDateOnly()

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

Definition at line 3868 of file datetime.c.

References Assert, DateOrder, DATEORDER_DMY, MONTHS_PER_YEAR, pg_ltostr_zeropad(), 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().

3869 {
3870  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
3871 
3872  switch (style)
3873  {
3874  case USE_ISO_DATES:
3875  case USE_XSD_DATES:
3876  /* compatible with ISO date formats */
3878  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3879  *str++ = '-';
3880  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3881  *str++ = '-';
3882  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3883  break;
3884 
3885  case USE_SQL_DATES:
3886  /* compatible with Oracle/Ingres date formats */
3887  if (DateOrder == DATEORDER_DMY)
3888  {
3889  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3890  *str++ = '/';
3891  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3892  }
3893  else
3894  {
3895  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3896  *str++ = '/';
3897  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3898  }
3899  *str++ = '/';
3901  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3902  break;
3903 
3904  case USE_GERMAN_DATES:
3905  /* German-style date format */
3906  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3907  *str++ = '.';
3908  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3909  *str++ = '.';
3911  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3912  break;
3913 
3914  case USE_POSTGRES_DATES:
3915  default:
3916  /* traditional date-only style for Postgres */
3917  if (DateOrder == DATEORDER_DMY)
3918  {
3919  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3920  *str++ = '-';
3921  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3922  }
3923  else
3924  {
3925  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3926  *str++ = '-';
3927  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3928  }
3929  *str++ = '-';
3931  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3932  break;
3933  }
3934 
3935  if (tm->tm_year <= 0)
3936  {
3937  memcpy(str, " BC", 3); /* Don't copy NUL */
3938  str += 3;
3939  }
3940  *str = '\0';
3941 }
#define USE_SQL_DATES
Definition: miscadmin.h:213
#define USE_ISO_DATES
Definition: miscadmin.h:212
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define USE_POSTGRES_DATES
Definition: miscadmin.h:211
int DateOrder
Definition: globals.c:117
char * pg_ltostr_zeropad(char *str, int32 value, int32 minwidth)
Definition: numutils.c:257
#define DATEORDER_DMY
Definition: miscadmin.h:219
#define Assert(condition)
Definition: c.h:699
#define USE_XSD_DATES
Definition: miscadmin.h:215
int tm_year
Definition: pgtime.h:32
#define USE_GERMAN_DATES
Definition: miscadmin.h:214

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

References AppendTimestampSeconds(), Assert, date2j(), DateOrder, DATEORDER_DMY, days, EncodeTimezone(), j2day(), MAXTZLEN, months, MONTHS_PER_YEAR, pg_ltostr_zeropad(), 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 abstimeout(), JsonEncodeDateTime(), map_sql_value_to_xml_value(), PGTYPEStimestamp_to_asc(), timestamp_out(), timestamptz_out(), and timestamptz_to_str().

3984 {
3985  int day;
3986 
3987  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
3988 
3989  /*
3990  * Negative tm_isdst means we have no valid time zone translation.
3991  */
3992  if (tm->tm_isdst < 0)
3993  print_tz = false;
3994 
3995  switch (style)
3996  {
3997  case USE_ISO_DATES:
3998  case USE_XSD_DATES:
3999  /* Compatible with ISO-8601 date formats */
4001  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4002  *str++ = '-';
4003  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
4004  *str++ = '-';
4005  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4006  *str++ = (style == USE_ISO_DATES) ? ' ' : 'T';
4007  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
4008  *str++ = ':';
4009  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
4010  *str++ = ':';
4011  str = AppendTimestampSeconds(str, tm, fsec);
4012  if (print_tz)
4013  str = EncodeTimezone(str, tz, style);
4014  break;
4015 
4016  case USE_SQL_DATES:
4017  /* Compatible with Oracle/Ingres date formats */
4018  if (DateOrder == DATEORDER_DMY)
4019  {
4020  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4021  *str++ = '/';
4022  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
4023  }
4024  else
4025  {
4026  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
4027  *str++ = '/';
4028  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4029  }
4030  *str++ = '/';
4032  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4033  *str++ = ' ';
4034  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
4035  *str++ = ':';
4036  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
4037  *str++ = ':';
4038  str = AppendTimestampSeconds(str, tm, fsec);
4039 
4040  /*
4041  * Note: the uses of %.*s in this function would be risky if the
4042  * timezone names ever contain non-ASCII characters. However, all
4043  * TZ abbreviations in the IANA database are plain ASCII.
4044  */
4045  if (print_tz)
4046  {
4047  if (tzn)
4048  {
4049  sprintf(str, " %.*s", MAXTZLEN, tzn);
4050  str += strlen(str);
4051  }
4052  else
4053  str = EncodeTimezone(str, tz, style);
4054  }
4055  break;
4056 
4057  case USE_GERMAN_DATES:
4058  /* German variant on European style */
4059  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4060  *str++ = '.';
4061  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
4062  *str++ = '.';
4064  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4065  *str++ = ' ';
4066  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
4067  *str++ = ':';
4068  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
4069  *str++ = ':';
4070  str = AppendTimestampSeconds(str, tm, fsec);
4071 
4072  if (print_tz)
4073  {
4074  if (tzn)
4075  {
4076  sprintf(str, " %.*s", MAXTZLEN, tzn);
4077  str += strlen(str);
4078  }
4079  else
4080  str = EncodeTimezone(str, tz, style);
4081  }
4082  break;
4083 
4084  case USE_POSTGRES_DATES:
4085  default:
4086  /* Backward-compatible with traditional Postgres abstime dates */
4087  day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
4088  tm->tm_wday = j2day(day);
4089  memcpy(str, days[tm->tm_wday], 3);
4090  str += 3;
4091  *str++ = ' ';
4092  if (DateOrder == DATEORDER_DMY)
4093  {
4094  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4095  *str++ = ' ';
4096  memcpy(str, months[tm->tm_mon - 1], 3);
4097  str += 3;
4098  }
4099  else
4100  {
4101  memcpy(str, months[tm->tm_mon - 1], 3);
4102  str += 3;
4103  *str++ = ' ';
4104  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
4105  }
4106  *str++ = ' ';
4107  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
4108  *str++ = ':';
4109  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
4110  *str++ = ':';
4111  str = AppendTimestampSeconds(str, tm, fsec);
4112  *str++ = ' ';
4114  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
4115 
4116  if (print_tz)
4117  {
4118  if (tzn)
4119  {
4120  sprintf(str, " %.*s", MAXTZLEN, tzn);
4121  str += strlen(str);
4122  }
4123  else
4124  {
4125  /*
4126  * We have a time zone, but no string version. Use the
4127  * numeric form, but be sure to include a leading space to
4128  * avoid formatting something which would be rejected by
4129  * the date/time parser later. - thomas 2001-10-19
4130  */
4131  *str++ = ' ';
4132  str = EncodeTimezone(str, tz, style);
4133  }
4134  }
4135  break;
4136  }
4137 
4138  if (tm->tm_year <= 0)
4139  {
4140  memcpy(str, " BC", 3); /* Don't copy NUL */
4141  str += 3;
4142  }
4143  *str = '\0';
4144 }
int tm_wday
Definition: pgtime.h:33
int tm_isdst
Definition: pgtime.h:35
int tm_hour
Definition: pgtime.h:29
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:3830
#define USE_SQL_DATES
Definition: miscadmin.h:213
#define MAXTZLEN
Definition: miscadmin.h:239
#define USE_ISO_DATES
Definition: miscadmin.h:212
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
const char *const months[]
Definition: datetime.c:67
int j2day(int date)
Definition: datetime.c:336
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define USE_POSTGRES_DATES
Definition: miscadmin.h:211
const char *const days[]
Definition: datetime.c:70
int DateOrder
Definition: globals.c:117
char * pg_ltostr_zeropad(char *str, int32 value, int32 minwidth)
Definition: numutils.c:257
static char * AppendTimestampSeconds(char *cp, struct pg_tm *tm, fsec_t fsec)
Definition: datetime.c:458
#define DATEORDER_DMY
Definition: miscadmin.h:219
int date2j(int y, int m, int d)
Definition: datetime.c:276
#define Assert(condition)
Definition: c.h:699
#define USE_XSD_DATES
Definition: miscadmin.h:215
int tm_year
Definition: pgtime.h:32
#define USE_GERMAN_DATES
Definition: miscadmin.h:214
int tm_min
Definition: pgtime.h:28

◆ EncodeInterval()

void EncodeInterval ( struct pg_tm tm,
fsec_t  fsec,
int  style,
char *  str 
)

Definition at line 4225 of file datetime.c.

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

Referenced by interval_out(), and reltimeout().

4226 {
4227  char *cp = str;
4228  int year = tm->tm_year;
4229  int mon = tm->tm_mon;
4230  int mday = tm->tm_mday;
4231  int hour = tm->tm_hour;
4232  int min = tm->tm_min;
4233  int sec = tm->tm_sec;
4234  bool is_before = false;
4235  bool is_zero = true;
4236 
4237  /*
4238  * The sign of year and month are guaranteed to match, since they are
4239  * stored internally as "month". But we'll need to check for is_before and
4240  * is_zero when determining the signs of day and hour/minute/seconds
4241  * fields.
4242  */
4243  switch (style)
4244  {
4245  /* SQL Standard interval format */
4246  case INTSTYLE_SQL_STANDARD:
4247  {
4248  bool has_negative = year < 0 || mon < 0 ||
4249  mday < 0 || hour < 0 ||
4250  min < 0 || sec < 0 || fsec < 0;
4251  bool has_positive = year > 0 || mon > 0 ||
4252  mday > 0 || hour > 0 ||
4253  min > 0 || sec > 0 || fsec > 0;
4254  bool has_year_month = year != 0 || mon != 0;
4255  bool has_day_time = mday != 0 || hour != 0 ||
4256  min != 0 || sec != 0 || fsec != 0;
4257  bool has_day = mday != 0;
4258  bool sql_standard_value = !(has_negative && has_positive) &&
4259  !(has_year_month && has_day_time);
4260 
4261  /*
4262  * SQL Standard wants only 1 "<sign>" preceding the whole
4263  * interval ... but can't do that if mixed signs.
4264  */
4265  if (has_negative && sql_standard_value)
4266  {
4267  *cp++ = '-';
4268  year = -year;
4269  mon = -mon;
4270  mday = -mday;
4271  hour = -hour;
4272  min = -min;
4273  sec = -sec;
4274  fsec = -fsec;
4275  }
4276 
4277  if (!has_negative && !has_positive)
4278  {
4279  sprintf(cp, "0");
4280  }
4281  else if (!sql_standard_value)
4282  {
4283  /*
4284  * For non sql-standard interval values, force outputting
4285  * the signs to avoid ambiguities with intervals with
4286  * mixed sign components.
4287  */
4288  char year_sign = (year < 0 || mon < 0) ? '-' : '+';
4289  char day_sign = (mday < 0) ? '-' : '+';
4290  char sec_sign = (hour < 0 || min < 0 ||
4291  sec < 0 || fsec < 0) ? '-' : '+';
4292 
4293  sprintf(cp, "%c%d-%d %c%d %c%d:%02d:",
4294  year_sign, abs(year), abs(mon),
4295  day_sign, abs(mday),
4296  sec_sign, abs(hour), abs(min));
4297  cp += strlen(cp);
4298  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4299  *cp = '\0';
4300  }
4301  else if (has_year_month)
4302  {
4303  sprintf(cp, "%d-%d", year, mon);
4304  }
4305  else if (has_day)
4306  {
4307  sprintf(cp, "%d %d:%02d:", mday, hour, min);
4308  cp += strlen(cp);
4309  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4310  *cp = '\0';
4311  }
4312  else
4313  {
4314  sprintf(cp, "%d:%02d:", hour, min);
4315  cp += strlen(cp);
4316  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4317  *cp = '\0';
4318  }
4319  }
4320  break;
4321 
4322  /* ISO 8601 "time-intervals by duration only" */
4323  case INTSTYLE_ISO_8601:
4324  /* special-case zero to avoid printing nothing */
4325  if (year == 0 && mon == 0 && mday == 0 &&
4326  hour == 0 && min == 0 && sec == 0 && fsec == 0)
4327  {
4328  sprintf(cp, "PT0S");
4329  break;
4330  }
4331  *cp++ = 'P';
4332  cp = AddISO8601IntPart(cp, year, 'Y');
4333  cp = AddISO8601IntPart(cp, mon, 'M');
4334  cp = AddISO8601IntPart(cp, mday, 'D');
4335  if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
4336  *cp++ = 'T';
4337  cp = AddISO8601IntPart(cp, hour, 'H');
4338  cp = AddISO8601IntPart(cp, min, 'M');
4339  if (sec != 0 || fsec != 0)
4340  {
4341  if (sec < 0 || fsec < 0)
4342  *cp++ = '-';
4343  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4344  *cp++ = 'S';
4345  *cp++ = '\0';
4346  }
4347  break;
4348 
4349  /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
4350  case INTSTYLE_POSTGRES:
4351  cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
4352 
4353  /*
4354  * Ideally we should spell out "month" like we do for "year" and
4355  * "day". However, for backward compatibility, we can't easily
4356  * fix this. bjm 2011-05-24
4357  */
4358  cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
4359  cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
4360  if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
4361  {
4362  bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
4363 
4364  sprintf(cp, "%s%s%02d:%02d:",
4365  is_zero ? "" : " ",
4366  (minus ? "-" : (is_before ? "+" : "")),
4367  abs(hour), abs(min));
4368  cp += strlen(cp);
4369  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true);
4370  *cp = '\0';
4371  }
4372  break;
4373 
4374  /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
4376  default:
4377  strcpy(cp, "@");
4378  cp++;
4379  cp = AddVerboseIntPart(cp, year, "year", &is_zero, &is_before);
4380  cp = AddVerboseIntPart(cp, mon, "mon", &is_zero, &is_before);
4381  cp = AddVerboseIntPart(cp, mday, "day", &is_zero, &is_before);
4382  cp = AddVerboseIntPart(cp, hour, "hour", &is_zero, &is_before);
4383  cp = AddVerboseIntPart(cp, min, "min", &is_zero, &is_before);
4384  if (sec != 0 || fsec != 0)
4385  {
4386  *cp++ = ' ';
4387  if (sec < 0 || (sec == 0 && fsec < 0))
4388  {
4389  if (is_zero)
4390  is_before = true;
4391  else if (!is_before)
4392  *cp++ = '-';
4393  }
4394  else if (is_before)
4395  *cp++ = '-';
4396  cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, false);
4397  sprintf(cp, " sec%s",
4398  (abs(sec) != 1 || fsec != 0) ? "s" : "");
4399  is_zero = false;
4400  }
4401  /* identically zero? then put in a unitless zero... */
4402  if (is_zero)
4403  strcat(cp, " 0");
4404  if (is_before)
4405  strcat(cp, " ago");
4406  break;
4407  }
4408 }
#define INTSTYLE_POSTGRES_VERBOSE
Definition: miscadmin.h:233
int tm_hour
Definition: pgtime.h:29
#define MAX_INTERVAL_PRECISION
Definition: timestamp.h:54
static char * AddISO8601IntPart(char *cp, int value, char units)
Definition: datetime.c:4153
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
static char * AddPostgresIntPart(char *cp, int value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4163
#define INTSTYLE_ISO_8601
Definition: miscadmin.h:235
static char * AddVerboseIntPart(char *cp, int value, const char *units, bool *is_zero, bool *is_before)
Definition: datetime.c:4186
static char * AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Definition: datetime.c:395
#define INTSTYLE_SQL_STANDARD
Definition: miscadmin.h:234
int tm_year
Definition: pgtime.h:32
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
#define INTSTYLE_POSTGRES
Definition: miscadmin.h:232

◆ EncodeSpecialTimestamp()

void EncodeSpecialTimestamp ( Timestamp  dt,
char *  str 
)

Definition at line 1523 of file timestamp.c.

References EARLY, elog, ERROR, LATE, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

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

1524 {
1525  if (TIMESTAMP_IS_NOBEGIN(dt))
1526  strcpy(str, EARLY);
1527  else if (TIMESTAMP_IS_NOEND(dt))
1528  strcpy(str, LATE);
1529  else /* shouldn't happen */
1530  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1531 }
#define LATE
Definition: datetime.h:41
#define ERROR
Definition: elog.h:43
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:120
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:115
#define elog
Definition: elog.h:219
#define EARLY
Definition: datetime.h:40

◆ EncodeTimeOnly()

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

Definition at line 3953 of file datetime.c.

References AppendSeconds(), EncodeTimezone(), MAX_TIME_PRECISION, pg_ltostr_zeropad(), pg_tm::tm_hour, pg_tm::tm_min, and pg_tm::tm_sec.

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

3954 {
3955  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
3956  *str++ = ':';
3957  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
3958  *str++ = ':';
3959  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
3960  if (print_tz)
3961  str = EncodeTimezone(str, tz, style);
3962  *str = '\0';
3963 }
int tm_hour
Definition: pgtime.h:29
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:3830
char * pg_ltostr_zeropad(char *str, int32 value, int32 minwidth)
Definition: numutils.c:257
static char * AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Definition: datetime.c:395
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
#define MAX_TIME_PRECISION
Definition: date.h:51

◆ GetCurrentDateTime()

void GetCurrentDateTime ( struct pg_tm tm)

Definition at line 354 of file datetime.c.

References GetCurrentTransactionStartTimestamp(), and timestamp2tm().

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

355 {
356  int tz;
357  fsec_t fsec;
358 
360  NULL, NULL);
361  /* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
362 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
int32 fsec_t
Definition: timestamp.h:41
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:700

◆ GetCurrentTimeUsec()

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

Definition at line 371 of file datetime.c.

References GetCurrentTransactionStartTimestamp(), and timestamp2tm().

Referenced by DecodeDateTime(), and DecodeTimeOnly().

372 {
373  int tz;
374 
376  NULL, NULL);
377  /* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
378  if (tzp != NULL)
379  *tzp = tz;
380 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:700

◆ InstallTimeZoneAbbrevs()

void InstallTimeZoneAbbrevs ( TimeZoneAbbrevTable tbl)

Definition at line 4587 of file datetime.c.

Referenced by assign_timezone_abbreviations().

4588 {
4589  zoneabbrevtbl = tbl;
4590  /* reset abbrevcache, which may contain pointers into old table */
4591  memset(abbrevcache, 0, sizeof(abbrevcache));
4592 }
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:244
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:252

◆ j2date()

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

Definition at line 301 of file datetime.c.

302 {
303  unsigned int julian;
304  unsigned int quad;
305  unsigned int extra;
306  int y;
307 
308  julian = jd;
309  julian += 32044;
310  quad = julian / 146097;
311  extra = (julian - quad * 146097) * 4 + 3;
312  julian += 60 + quad * 3 + extra / 146097;
313  quad = julian / 1461;
314  julian -= quad * 1461;
315  y = julian * 4 / 1461;
316  julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
317  + 123;
318  y += quad * 4;
319  *year = y - 4800;
320  quad = julian * 2141 / 65536;
321  *day = julian - 7834 * quad / 256;
322  *month = (quad + 10) % MONTHS_PER_YEAR + 1;
323 
324  return;
325 } /* j2date() */
#define MONTHS_PER_YEAR
Definition: timestamp.h:69

◆ j2day()

int j2day ( int  jd)

Definition at line 336 of file datetime.c.

Referenced by date2isoweek(), date2isoyear(), EncodeDateTime(), isoweek2j(), timestamp_part(), and timestamptz_part().

337 {
338  date += 1;
339  date %= 7;
340  /* Cope if division truncates towards zero, as it probably does */
341  if (date < 0)
342  date += 7;
343 
344  return date;
345 } /* j2day() */
long date
Definition: pgtypes_date.h:8

◆ ParseDateTime()

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

Definition at line 546 of file datetime.c.

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

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

548 {
549  int nf = 0;
550  const char *cp = timestr;
551  char *bufp = workbuf;
552  const char *bufend = workbuf + buflen;
553 
554  /*
555  * Set the character pointed-to by "bufptr" to "newchar", and increment
556  * "bufptr". "end" gives the end of the buffer -- we return an error if
557  * there is no space left to append a character to the buffer. Note that
558  * "bufptr" is evaluated twice.
559  */
560 #define APPEND_CHAR(bufptr, end, newchar) \
561  do \
562  { \
563  if (((bufptr) + 1) >= (end)) \
564  return DTERR_BAD_FORMAT; \
565  *(bufptr)++ = newchar; \
566  } while (0)
567 
568  /* outer loop through fields */
569  while (*cp != '\0')
570  {
571  /* Ignore spaces between fields */
572  if (isspace((unsigned char) *cp))
573  {
574  cp++;
575  continue;
576  }
577 
578  /* Record start of current field */
579  if (nf >= maxfields)
580  return DTERR_BAD_FORMAT;
581  field[nf] = bufp;
582 
583  /* leading digit? then date or time */
584  if (isdigit((unsigned char) *cp))
585  {
586  APPEND_CHAR(bufp, bufend, *cp++);
587  while (isdigit((unsigned char) *cp))
588  APPEND_CHAR(bufp, bufend, *cp++);
589 
590  /* time field? */
591  if (*cp == ':')
592  {
593  ftype[nf] = DTK_TIME;
594  APPEND_CHAR(bufp, bufend, *cp++);
595  while (isdigit((unsigned char) *cp) ||
596  (*cp == ':') || (*cp == '.'))
597  APPEND_CHAR(bufp, bufend, *cp++);
598  }
599  /* date field? allow embedded text month */
600  else if (*cp == '-' || *cp == '/' || *cp == '.')
601  {
602  /* save delimiting character to use later */
603  char delim = *cp;
604 
605  APPEND_CHAR(bufp, bufend, *cp++);
606  /* second field is all digits? then no embedded text month */
607  if (isdigit((unsigned char) *cp))
608  {
609  ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);
610  while (isdigit((unsigned char) *cp))
611  APPEND_CHAR(bufp, bufend, *cp++);
612 
613  /*
614  * insist that the delimiters match to get a three-field
615  * date.
616  */
617  if (*cp == delim)
618  {
619  ftype[nf] = DTK_DATE;
620  APPEND_CHAR(bufp, bufend, *cp++);
621  while (isdigit((unsigned char) *cp) || *cp == delim)
622  APPEND_CHAR(bufp, bufend, *cp++);
623  }
624  }
625  else
626  {
627  ftype[nf] = DTK_DATE;
628  while (isalnum((unsigned char) *cp) || *cp == delim)
629  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
630  }
631  }
632 
633  /*
634  * otherwise, number only and will determine year, month, day, or
635  * concatenated fields later...
636  */
637  else
638  ftype[nf] = DTK_NUMBER;
639  }
640  /* Leading decimal point? Then fractional seconds... */
641  else if (*cp == '.')
642  {
643  APPEND_CHAR(bufp, bufend, *cp++);
644  while (isdigit((unsigned char) *cp))
645  APPEND_CHAR(bufp, bufend, *cp++);
646 
647  ftype[nf] = DTK_NUMBER;
648  }
649 
650  /*
651  * text? then date string, month, day of week, special, or timezone
652  */
653  else if (isalpha((unsigned char) *cp))
654  {
655  bool is_date;
656 
657  ftype[nf] = DTK_STRING;
658  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
659  while (isalpha((unsigned char) *cp))
660  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
661 
662  /*
663  * Dates can have embedded '-', '/', or '.' separators. It could
664  * also be a timezone name containing embedded '/', '+', '-', '_',
665  * or ':' (but '_' or ':' can't be the first punctuation). If the
666  * next character is a digit or '+', we need to check whether what
667  * we have so far is a recognized non-timezone keyword --- if so,
668  * don't believe that this is the start of a timezone.
669  */
670  is_date = false;
671  if (*cp == '-' || *cp == '/' || *cp == '.')
672  is_date = true;
673  else if (*cp == '+' || isdigit((unsigned char) *cp))
674  {
675  *bufp = '\0'; /* null-terminate current field value */
676  /* we need search only the core token table, not TZ names */
677  if (datebsearch(field[nf], datetktbl, szdatetktbl) == NULL)
678  is_date = true;
679  }
680  if (is_date)
681  {
682  ftype[nf] = DTK_DATE;
683  do
684  {
685  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
686  } while (*cp == '+' || *cp == '-' ||
687  *cp == '/' || *cp == '_' ||
688  *cp == '.' || *cp == ':' ||
689  isalnum((unsigned char) *cp));
690  }
691  }
692  /* sign? then special or numeric timezone */
693  else if (*cp == '+' || *cp == '-')
694  {
695  APPEND_CHAR(bufp, bufend, *cp++);
696  /* soak up leading whitespace */
697  while (isspace((unsigned char) *cp))
698  cp++;
699  /* numeric timezone? */
700  /* note that "DTK_TZ" could also be a signed float or yyyy-mm */
701  if (isdigit((unsigned char) *cp))
702  {
703  ftype[nf] = DTK_TZ;
704  APPEND_CHAR(bufp, bufend, *cp++);
705  while (isdigit((unsigned char) *cp) ||
706  *cp == ':' || *cp == '.' || *cp == '-')
707  APPEND_CHAR(bufp, bufend, *cp++);
708  }
709  /* special? */
710  else if (isalpha((unsigned char) *cp))
711  {
712  ftype[nf] = DTK_SPECIAL;
713  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
714  while (isalpha((unsigned char) *cp))
715  APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));
716  }
717  /* otherwise something wrong... */
718  else
719  return DTERR_BAD_FORMAT;
720  }
721  /* ignore other punctuation but use as delimiter */
722  else if (ispunct((unsigned char) *cp))
723  {
724  cp++;
725  continue;
726  }
727  /* otherwise, something is not right... */
728  else
729  return DTERR_BAD_FORMAT;
730 
731  /* force in a delimiter after each field */
732  *bufp++ = '\0';
733  nf++;
734  }
735 
736  *numfields = nf;
737 
738  return 0;
739 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:282
#define APPEND_CHAR(bufptr, end, newchar)
static const datetkn datetktbl[]
Definition: datetime.c:91
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
static int szdatetktbl
Definition: datetime.c:169
#define DTK_TZ
Definition: datetime.h:147
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3794
#define DTK_NUMBER
Definition: datetime.h:142
#define DTK_TIME
Definition: datetime.h:146
#define DTK_STRING
Definition: datetime.h:143
#define DTK_DATE
Definition: datetime.h:145
#define DTK_SPECIAL
Definition: datetime.h:150

◆ TemporalTransform()

Node* TemporalTransform ( int32  max_precis,
Node node 
)

Definition at line 4470 of file datetime.c.

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

Referenced by time_transform(), and timestamp_transform().

4471 {
4472  FuncExpr *expr = castNode(FuncExpr, node);
4473  Node *ret = NULL;
4474  Node *typmod;
4475 
4476  Assert(list_length(expr->args) >= 2);
4477 
4478  typmod = (Node *) lsecond(expr->args);
4479 
4480  if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
4481  {
4482  Node *source = (Node *) linitial(expr->args);
4483  int32 old_precis = exprTypmod(source);
4484  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4485 
4486  if (new_precis < 0 || new_precis == max_precis ||
4487  (old_precis >= 0 && new_precis >= old_precis))
4488  ret = relabel_to_typmod(source, new_precis);
4489  }
4490 
4491  return ret;
4492 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
List * args
Definition: primnodes.h:458
#define DatumGetInt32(X)
Definition: postgres.h:455
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Definition: nodes.h:517
#define lsecond(l)
Definition: pg_list.h:116
signed int int32
Definition: c.h:313
#define linitial(l)
Definition: pg_list.h:111
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:588

◆ ValidateDate()

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

Definition at line 2463 of file datetime.c.

References date2j(), DAY, day_tab, DOY, DTERR_FIELD_OVERFLOW, DTERR_MD_FIELD_OVERFLOW, DTK_DATE_M, DTK_M, isleap, j2date(), MONTH, MONTHS_PER_YEAR, 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().

2465 {
2466  if (fmask & DTK_M(YEAR))
2467  {
2468  if (isjulian)
2469  {
2470  /* tm_year is correct and should not be touched */
2471  }
2472  else if (bc)
2473  {
2474  /* there is no year zero in AD/BC notation */
2475  if (tm->tm_year <= 0)
2476  return DTERR_FIELD_OVERFLOW;
2477  /* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
2478  tm->tm_year = -(tm->tm_year - 1);
2479  }
2480  else if (is2digits)
2481  {
2482  /* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
2483  if (tm->tm_year < 0) /* just paranoia */
2484  return DTERR_FIELD_OVERFLOW;
2485  if (tm->tm_year < 70)
2486  tm->tm_year += 2000;
2487  else if (tm->tm_year < 100)
2488  tm->tm_year += 1900;
2489  }
2490  else
2491  {
2492  /* there is no year zero in AD/BC notation */
2493  if (tm->tm_year <= 0)
2494  return DTERR_FIELD_OVERFLOW;
2495  }
2496  }
2497 
2498  /* now that we have correct year, decode DOY */
2499  if (fmask & DTK_M(DOY))
2500  {
2501  j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
2502  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2503  }
2504 
2505  /* check for valid month */
2506  if (fmask & DTK_M(MONTH))
2507  {
2508  if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
2509  return DTERR_MD_FIELD_OVERFLOW;
2510  }
2511 
2512  /* minimal check for valid day */
2513  if (fmask & DTK_M(DAY))
2514  {
2515  if (tm->tm_mday < 1 || tm->tm_mday > 31)
2516  return DTERR_MD_FIELD_OVERFLOW;
2517  }
2518 
2519  if ((fmask & DTK_DATE_M) == DTK_DATE_M)
2520  {
2521  /*
2522  * Check for valid day of month, now that we know for sure the month
2523  * and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
2524  * unlikely that "Feb 29" is a YMD-order error.
2525  */
2526  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
2527  return DTERR_FIELD_OVERFLOW;
2528  }
2529 
2530  return 0;
2531 }
#define DAY
Definition: datetime.h:94
#define YEAR
Definition: datetime.h:93
#define isleap(y)
Definition: datetime.h:273
#define DTK_DATE_M
Definition: datetime.h:194
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:283
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:301
#define MONTH
Definition: datetime.h:92
const int day_tab[2][13]
Definition: datetime.c:61
int date2j(int y, int m, int d)
Definition: datetime.c:276
int tm_year
Definition: pgtime.h:32
#define DTK_M(t)
Definition: datetime.h:190
int tm_yday
Definition: pgtime.h:34
#define DTERR_MD_FIELD_OVERFLOW
Definition: datetime.h:284
#define DOY
Definition: datetime.h:106

Variable Documentation

◆ day_tab

const int day_tab[2][13]

Definition at line 61 of file datetime.c.

◆ days

const char* const days[]

Definition at line 70 of file datetime.c.

◆ months

const char* const months[]

Definition at line 67 of file datetime.c.