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

Go to the source code of this file.

Data Structures

struct  datetkn
 
struct  TimeZoneAbbrevTable
 
struct  DynamicZoneAbbrev
 

Macros

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

Typedefs

typedef struct TimeZoneAbbrevTable TimeZoneAbbrevTable
 
typedef struct DynamicZoneAbbrev DynamicZoneAbbrev
 

Functions

void GetCurrentDateTime (struct pg_tm *tm)
 
void GetCurrentTimeUsec (struct pg_tm *tm, fsec_t *fsec, int *tzp)
 
void j2date (int jd, int *year, int *month, int *day)
 
int date2j (int year, int month, int day)
 
int ParseDateTime (const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
 
int DecodeDateTime (char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
 
int DecodeTimezone (char *str, int *tzp)
 
int DecodeTimeOnly (char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp)
 
int DecodeInterval (char **field, int *ftype, int nf, int range, int *dtype, struct pg_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)
 
NodeTemporalSimplify (int32 max_precis, Node *node)
 
bool CheckDateTokenTables (void)
 
TimeZoneAbbrevTableConvertTimeZoneAbbrevs (struct tzEntry *abbrevs, int n)
 
void InstallTimeZoneAbbrevs (TimeZoneAbbrevTable *tbl)
 
void AdjustTimestampForTypmod (Timestamp *time, int32 typmod)
 
bool AdjustTimestampForTypmodError (Timestamp *time, int32 typmod, bool *error)
 

Variables

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

Referenced by DateTimeParseError(), and interval_in().

◆ DTERR_MD_FIELD_OVERFLOW

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

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

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

◆ DTK_CENTURY

◆ DTK_DATE

◆ DTK_DATE_M

◆ DTK_DAY

◆ DTK_DECADE

◆ DTK_DELTA

#define DTK_DELTA   17

◆ DTK_DOW

#define DTK_DOW   32

Definition at line 176 of file datetime.h.

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

◆ DTK_DOY

#define DTK_DOY   33

Definition at line 177 of file datetime.h.

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

◆ DTK_EARLY

#define DTK_EARLY   9

Definition at line 151 of file datetime.h.

Referenced by date_in(), PGTYPEStimestamp_from_asc(), timestamp_in(), and timestamptz_in().

◆ DTK_EPOCH

◆ DTK_HOUR

◆ DTK_ISODOW

#define DTK_ISODOW   37

Definition at line 181 of file datetime.h.

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

◆ DTK_ISOYEAR

#define DTK_ISOYEAR   36

Definition at line 180 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

Definition at line 152 of file datetime.h.

Referenced by date_in(), PGTYPEStimestamp_from_asc(), timestamp_in(), and timestamptz_in().

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

Referenced by DecodeDateTime().

◆ DTK_TOMORROW

#define DTK_TOMORROW   15

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

Referenced by DecodeDateTime().

◆ DTK_ZULU

#define DTK_ZULU   16

Definition at line 158 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 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:21

Definition at line 238 of file datetime.h.

Referenced by 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 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 249 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

◆ AdjustTimestampForTypmod()

void AdjustTimestampForTypmod ( Timestamp time,
int32  typmod 
)

Definition at line 391 of file timestamp.c.

References AdjustTimestampForTypmodError().

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

392 {
393  (void) AdjustTimestampForTypmodError(time, typmod, NULL);
394 }
bool AdjustTimestampForTypmodError(Timestamp *time, int32 typmod, bool *error)
Definition: timestamp.c:336

◆ AdjustTimestampForTypmodError()

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

Definition at line 336 of file timestamp.c.

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

Referenced by AdjustTimestampForTypmod().

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

◆ CheckDateTokenTables()

bool CheckDateTokenTables ( void  )

Definition at line 4437 of file datetime.c.

4438 {
4439  bool ok = true;
4440 
4441  Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1));
4442  Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1));
4443 
4444  ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
4445  ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
4446  return ok;
4447 }
static const datetkn datetktbl[]
Definition: datetime.c:89
static const int szdeltatktbl
Definition: datetime.c:235
static bool CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
Definition: datetime.c:4405
static const datetkn deltatktbl[]
Definition: datetime.c:170
int date2j(int y, int m, int d)
Definition: datetime.c:269
#define Assert(condition)
Definition: c.h:733
static const int szdatetktbl
Definition: datetime.c:164
#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 4499 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().

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

◆ date2j()

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

Definition at line 269 of file datetime.c.

270 {
271  int julian;
272  int century;
273 
274  if (m > 2)
275  {
276  m += 1;
277  y += 4800;
278  }
279  else
280  {
281  m += 13;
282  y += 4799;
283  }
284 
285  century = y / 100;
286  julian = y * 365 - 32167;
287  julian += y / 4 - century + century / 4;
288  julian += 7834 * m / 256 + d;
289 
290  return julian;
291 } /* date2j() */

◆ DateTimeParseError()

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

Definition at line 3738 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 date_in(), do_to_timestamp(), interval_in(), parse_datetime(), time_in(), timestamp_in(), timestamptz_in(), timetz_in(), and to_timestamp().

3739 {
3740  switch (dterr)
3741  {
3742  case DTERR_FIELD_OVERFLOW:
3743  ereport(ERROR,
3744  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3745  errmsg("date/time field value out of range: \"%s\"",
3746  str)));
3747  break;
3749  /* <nanny>same as above, but add hint about DateStyle</nanny> */
3750  ereport(ERROR,
3751  (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
3752  errmsg("date/time field value out of range: \"%s\"",
3753  str),
3754  errhint("Perhaps you need a different \"datestyle\" setting.")));
3755  break;
3757  ereport(ERROR,
3758  (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW),
3759  errmsg("interval field value out of range: \"%s\"",
3760  str)));
3761  break;
3762  case DTERR_TZDISP_OVERFLOW:
3763  ereport(ERROR,
3764  (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
3765  errmsg("time zone displacement out of range: \"%s\"",
3766  str)));
3767  break;
3768  case DTERR_BAD_FORMAT:
3769  default:
3770  ereport(ERROR,
3771  (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3772  errmsg("invalid input syntax for type %s: \"%s\"",
3773  datatype, str)));
3774  break;
3775  }
3776 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:280
int errhint(const char *fmt,...)
Definition: elog.c:1071
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define DTERR_FIELD_OVERFLOW
Definition: datetime.h:281
#define DTERR_INTERVAL_OVERFLOW
Definition: datetime.h:283
#define ereport(elevel, rest)
Definition: elog.h:141
#define DTERR_TZDISP_OVERFLOW
Definition: datetime.h:284
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define DTERR_MD_FIELD_OVERFLOW
Definition: datetime.h:282

◆ DecodeDateTime()

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

Definition at line 760 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_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 check_recovery_target_time(), date_in(), pg_logdir_ls_internal(), PGTYPESdate_from_asc(), PGTYPEStimestamp_from_asc(), timestamp_in(), and timestamptz_in().

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

◆ DecodeInterval()

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

Definition at line 3066 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().

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

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

◆ DecodeSpecial()

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

Definition at line 3010 of file datetime.c.

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

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

3011 {
3012  int type;
3013  const datetkn *tp;
3014 
3015  tp = datecache[field];
3016  /* use strncmp so that we match truncated tokens */
3017  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3018  {
3019  tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
3020  }
3021  if (tp == NULL)
3022  {
3023  type = UNKNOWN_FIELD;
3024  *val = 0;
3025  }
3026  else
3027  {
3028  datecache[field] = tp;
3029  type = tp->type;
3030  *val = tp->value;
3031  }
3032 
3033  return type;
3034 }
static const datetkn datetktbl[]
Definition: datetime.c:89
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:212
char token[TOKMAXLEN+1]
Definition: datetime.h:210
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3783
char type
Definition: datetime.h:211
static const datetkn * datecache[MAXDATEFIELDS]
Definition: datetime.c:241
static const int szdatetktbl
Definition: datetime.c:164
#define TOKMAXLEN
Definition: datetime.h:205
long val
Definition: informix.c:684

◆ DecodeTimeOnly()

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

Definition at line 1716 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_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().

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

◆ DecodeTimezone()

int DecodeTimezone ( char *  str,
int *  tzp 
)

Definition at line 2877 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_datetime(), parse_sane_timezone(), and to_timestamp().

2878 {
2879  int tz;
2880  int hr,
2881  min,
2882  sec = 0;
2883  char *cp;
2884 
2885  /* leading character must be "+" or "-" */
2886  if (*str != '+' && *str != '-')
2887  return DTERR_BAD_FORMAT;
2888 
2889  errno = 0;
2890  hr = strtoint(str + 1, &cp, 10);
2891  if (errno == ERANGE)
2892  return DTERR_TZDISP_OVERFLOW;
2893 
2894  /* explicit delimiter? */
2895  if (*cp == ':')
2896  {
2897  errno = 0;
2898  min = strtoint(cp + 1, &cp, 10);
2899  if (errno == ERANGE)
2900  return DTERR_TZDISP_OVERFLOW;
2901  if (*cp == ':')
2902  {
2903  errno = 0;
2904  sec = strtoint(cp + 1, &cp, 10);
2905  if (errno == ERANGE)
2906  return DTERR_TZDISP_OVERFLOW;
2907  }
2908  }
2909  /* otherwise, might have run things together... */
2910  else if (*cp == '\0' && strlen(str) > 3)
2911  {
2912  min = hr % 100;
2913  hr = hr / 100;
2914  /* we could, but don't, support a run-together hhmmss format */
2915  }
2916  else
2917  min = 0;
2918 
2919  /* Range-check the values; see notes in datatype/timestamp.h */
2920  if (hr < 0 || hr > MAX_TZDISP_HOUR)
2921  return DTERR_TZDISP_OVERFLOW;
2922  if (min < 0 || min >= MINS_PER_HOUR)
2923  return DTERR_TZDISP_OVERFLOW;
2924  if (sec < 0 || sec >= SECS_PER_MINUTE)
2925  return DTERR_TZDISP_OVERFLOW;
2926 
2927  tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
2928  if (*str == '-')
2929  tz = -tz;
2930 
2931  *tzp = -tz;
2932 
2933  if (*cp != '\0')
2934  return DTERR_BAD_FORMAT;
2935 
2936  return 0;
2937 }
#define DTERR_BAD_FORMAT
Definition: datetime.h:280
#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:284

◆ DecodeTimezoneAbbrev()

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

Definition at line 2955 of file datetime.c.

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

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

2957 {
2958  int type;
2959  const datetkn *tp;
2960 
2961  tp = abbrevcache[field];
2962  /* use strncmp so that we match truncated tokens */
2963  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
2964  {
2965  if (zoneabbrevtbl)
2966  tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs,
2968  else
2969  tp = NULL;
2970  }
2971  if (tp == NULL)
2972  {
2973  type = UNKNOWN_FIELD;
2974  *offset = 0;
2975  *tz = NULL;
2976  }
2977  else
2978  {
2979  abbrevcache[field] = tp;
2980  type = tp->type;
2981  if (type == DYNTZ)
2982  {
2983  *offset = 0;
2985  }
2986  else
2987  {
2988  *offset = tp->value;
2989  *tz = NULL;
2990  }
2991  }
2992 
2993  return type;
2994 }
static pg_tz * FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp)
Definition: datetime.c:4594
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:212
char token[TOKMAXLEN+1]
Definition: datetime.h:210
datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER]
Definition: datetime.h:220
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3783
char type
Definition: datetime.h:211
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:237
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:245
#define DYNTZ
Definition: datetime.h:98
#define TOKMAXLEN
Definition: datetime.h:205

◆ DecodeUnits()

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

Definition at line 3701 of file datetime.c.

3702 {
3703  int type;
3704  const datetkn *tp;
3705 
3706  tp = deltacache[field];
3707  /* use strncmp so that we match truncated tokens */
3708  if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
3709  {
3710  tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
3711  }
3712  if (tp == NULL)
3713  {
3714  type = UNKNOWN_FIELD;
3715  *val = 0;
3716  }
3717  else
3718  {
3719  deltacache[field] = tp;
3720  type = tp->type;
3721  *val = tp->value;
3722  }
3723 
3724  return type;
3725 } /* DecodeUnits() */
static const datetkn * deltacache[MAXDATEFIELDS]
Definition: datetime.c:243
#define UNKNOWN_FIELD
Definition: datetime.h:125
int32 value
Definition: datetime.h:212
static const int szdeltatktbl
Definition: datetime.c:235
char token[TOKMAXLEN+1]
Definition: datetime.h:210
static const datetkn * datebsearch(const char *key, const datetkn *base, int nel)
Definition: datetime.c:3783
static const datetkn deltatktbl[]
Definition: datetime.c:170
char type
Definition: datetime.h:211
#define TOKMAXLEN
Definition: datetime.h:205
long val
Definition: informix.c:684

◆ DetermineTimeZoneAbbrevOffset()

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

Definition at line 1601 of file datetime.c.

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

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

1602 {
1603  pg_time_t t;
1604  int zone_offset;
1605  int abbr_offset;
1606  int abbr_isdst;
1607 
1608  /*
1609  * Compute the UTC time we want to probe at. (In event of overflow, we'll
1610  * probe at the epoch, which is a bit random but probably doesn't matter.)
1611  */
1612  zone_offset = DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1613 
1614  /*
1615  * Try to match the abbreviation to something in the zone definition.
1616  */
1617  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1618  &abbr_offset, &abbr_isdst))
1619  {
1620  /* Success, so use the abbrev-specific answers. */
1621  tm->tm_isdst = abbr_isdst;
1622  return abbr_offset;
1623  }
1624 
1625  /*
1626  * No match, so use the answers we already got from
1627  * DetermineTimeZoneOffsetInternal.
1628  */
1629  return zone_offset;
1630 }
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:1462
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1676

◆ DetermineTimeZoneAbbrevOffsetTS()

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

Definition at line 1639 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().

1641 {
1643  int zone_offset;
1644  int abbr_offset;
1645  int tz;
1646  struct pg_tm tm;
1647  fsec_t fsec;
1648 
1649  /*
1650  * If the abbrev matches anything in the zone data, this is pretty easy.
1651  */
1652  if (DetermineTimeZoneAbbrevOffsetInternal(t, abbr, tzp,
1653  &abbr_offset, isdst))
1654  return abbr_offset;
1655 
1656  /*
1657  * Else, break down the timestamp so we can use DetermineTimeZoneOffset.
1658  */
1659  if (timestamp2tm(ts, &tz, &tm, &fsec, NULL, tzp) != 0)
1660  ereport(ERROR,
1661  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1662  errmsg("timestamp out of range")));
1663 
1664  zone_offset = DetermineTimeZoneOffset(&tm, tzp);
1665  *isdst = tm.tm_isdst;
1666  return zone_offset;
1667 }
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:1791
int errcode(int sqlerrcode)
Definition: elog.c:608
Definition: pgtime.h:25
static struct pg_tm tm
Definition: localtime.c:108
#define ERROR
Definition: elog.h:43
int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
Definition: datetime.c:1440
pg_time_t timestamptz_to_time_t(TimestampTz t)
Definition: timestamp.c:1725
int32 fsec_t
Definition: timestamp.h:41
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822
static bool DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, int *offset, int *isdst)
Definition: datetime.c:1676

◆ DetermineTimeZoneOffset()

int DetermineTimeZoneOffset ( struct pg_tm tm,
pg_tz tzp 
)

Definition at line 1440 of file datetime.c.

References DetermineTimeZoneOffsetInternal().

Referenced by date2timestamptz_opt_overflow(), DecodeDateTime(), DecodeTimeOnly(), DetermineTimeZoneAbbrevOffsetTS(), parse_sane_timezone(), time_timetz(), timestamp2timestamptz_opt_overflow(), timestamp_zone(), timestamptz_pl_interval(), timestamptz_trunc_internal(), and to_timestamp().

1441 {
1442  pg_time_t t;
1443 
1444  return DetermineTimeZoneOffsetInternal(tm, tzp, &t);
1445 }
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:1462

◆ EncodeDateOnly()

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

Definition at line 3857 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().

3858 {
3859  Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
3860 
3861  switch (style)
3862  {
3863  case USE_ISO_DATES:
3864  case USE_XSD_DATES:
3865  /* compatible with ISO date formats */
3867  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3868  *str++ = '-';
3869  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3870  *str++ = '-';
3871  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3872  break;
3873 
3874  case USE_SQL_DATES:
3875  /* compatible with Oracle/Ingres date formats */
3876  if (DateOrder == DATEORDER_DMY)
3877  {
3878  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3879  *str++ = '/';
3880  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3881  }
3882  else
3883  {
3884  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3885  *str++ = '/';
3886  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3887  }
3888  *str++ = '/';
3890  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3891  break;
3892 
3893  case USE_GERMAN_DATES:
3894  /* German-style date format */
3895  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3896  *str++ = '.';
3897  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3898  *str++ = '.';
3900  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3901  break;
3902 
3903  case USE_POSTGRES_DATES:
3904  default:
3905  /* traditional date-only style for Postgres */
3906  if (DateOrder == DATEORDER_DMY)
3907  {
3908  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3909  *str++ = '-';
3910  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3911  }
3912  else
3913  {
3914  str = pg_ltostr_zeropad(str, tm->tm_mon, 2);
3915  *str++ = '-';
3916  str = pg_ltostr_zeropad(str, tm->tm_mday, 2);
3917  }
3918  *str++ = '-';
3920  (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1), 4);
3921  break;
3922  }
3923 
3924  if (tm->tm_year <= 0)
3925  {
3926  memcpy(str, " BC", 3); /* Don't copy NUL */
3927  str += 3;
3928  }
3929  *str = '\0';
3930 }
#define USE_SQL_DATES
Definition: miscadmin.h:215
#define USE_ISO_DATES
Definition: miscadmin.h:214
#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:213
int DateOrder
Definition: globals.c:116
char * pg_ltostr_zeropad(char *str, int32 value, int32 minwidth)
Definition: numutils.c:410
#define DATEORDER_DMY
Definition: miscadmin.h:221
#define Assert(condition)
Definition: c.h:733
#define USE_XSD_DATES
Definition: miscadmin.h:217
int tm_year
Definition: pgtime.h:32
#define USE_GERMAN_DATES
Definition: miscadmin.h:216

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

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

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

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

◆ EncodeInterval()

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

Definition at line 4214 of file datetime.c.

References AddISO8601IntPart(), AddPostgresIntPart(), AddVerboseIntPart(), AppendSeconds(), INTSTYLE_ISO_8601, INTSTYLE_POSTGRES, INTSTYLE_POSTGRES_VERBOSE, INTSTYLE_SQL_STANDARD, MAX_INTERVAL_PRECISION, sprintf, 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().

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

◆ EncodeSpecialTimestamp()

void EncodeSpecialTimestamp ( Timestamp  dt,
char *  str 
)

Definition at line 1536 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().

1537 {
1538  if (TIMESTAMP_IS_NOBEGIN(dt))
1539  strcpy(str, EARLY);
1540  else if (TIMESTAMP_IS_NOEND(dt))
1541  strcpy(str, LATE);
1542  else /* shouldn't happen */
1543  elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
1544 }
#define 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(elevel,...)
Definition: elog.h:228
#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 3942 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().

3943 {
3944  str = pg_ltostr_zeropad(str, tm->tm_hour, 2);
3945  *str++ = ':';
3946  str = pg_ltostr_zeropad(str, tm->tm_min, 2);
3947  *str++ = ':';
3948  str = AppendSeconds(str, tm->tm_sec, fsec, MAX_TIME_PRECISION, true);
3949  if (print_tz)
3950  str = EncodeTimezone(str, tz, style);
3951  *str = '\0';
3952 }
int tm_hour
Definition: pgtime.h:29
static char * EncodeTimezone(char *str, int tz, int style)
Definition: datetime.c:3819
char * pg_ltostr_zeropad(char *str, int32 value, int32 minwidth)
Definition: numutils.c:410
static char * AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros)
Definition: datetime.c:388
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 347 of file datetime.c.

References GetCurrentTransactionStartTimestamp(), and timestamp2tm().

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

348 {
349  int tz;
350  fsec_t fsec;
351 
353  NULL, NULL);
354  /* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
355 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
int32 fsec_t
Definition: timestamp.h:41
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:782

◆ GetCurrentTimeUsec()

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

Definition at line 364 of file datetime.c.

References GetCurrentTransactionStartTimestamp(), and timestamp2tm().

Referenced by DecodeDateTime(), and DecodeTimeOnly().

365 {
366  int tz;
367 
369  NULL, NULL);
370  /* Note: don't pass NULL tzp to timestamp2tm; affects behavior */
371  if (tzp != NULL)
372  *tzp = tz;
373 }
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
TimestampTz GetCurrentTransactionStartTimestamp(void)
Definition: xact.c:782

◆ InstallTimeZoneAbbrevs()

void InstallTimeZoneAbbrevs ( TimeZoneAbbrevTable tbl)

Definition at line 4583 of file datetime.c.

Referenced by assign_timezone_abbreviations().

4584 {
4585  zoneabbrevtbl = tbl;
4586  /* reset abbrevcache, which may contain pointers into old table */
4587  memset(abbrevcache, 0, sizeof(abbrevcache));
4588 }
static TimeZoneAbbrevTable * zoneabbrevtbl
Definition: datetime.c:237
static const datetkn * abbrevcache[MAXDATEFIELDS]
Definition: datetime.c:245

◆ j2date()

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

Definition at line 294 of file datetime.c.

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

◆ j2day()

int j2day ( int  jd)

Definition at line 329 of file datetime.c.

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

330 {
331  date += 1;
332  date %= 7;
333  /* Cope if division truncates towards zero, as it probably does */
334  if (date < 0)
335  date += 7;
336 
337  return date;
338 } /* j2day() */
long date
Definition: pgtypes_date.h:9

◆ ParseDateTime()

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

Definition at line 539 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 check_recovery_target_time(), date_in(), interval_in(), pg_logdir_ls_internal(), PGTYPESdate_from_asc(), PGTYPESinterval_from_asc(), PGTYPEStimestamp_from_asc(), time_in(), timestamp_in(), timestamptz_in(), and timetz_in().

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

◆ TemporalSimplify()

Node* TemporalSimplify ( int32  max_precis,
Node node 
)

Definition at line 4466 of file datetime.c.

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

Referenced by time_support(), and timestamp_support().

4467 {
4468  FuncExpr *expr = castNode(FuncExpr, node);
4469  Node *ret = NULL;
4470  Node *typmod;
4471 
4472  Assert(list_length(expr->args) >= 2);
4473 
4474  typmod = (Node *) lsecond(expr->args);
4475 
4476  if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
4477  {
4478  Node *source = (Node *) linitial(expr->args);
4479  int32 old_precis = exprTypmod(source);
4480  int32 new_precis = DatumGetInt32(((Const *) typmod)->constvalue);
4481 
4482  if (new_precis < 0 || new_precis == max_precis ||
4483  (old_precis >= 0 && new_precis >= old_precis))
4484  ret = relabel_to_typmod(source, new_precis);
4485  }
4486 
4487  return ret;
4488 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * args
Definition: primnodes.h:463
#define DatumGetInt32(X)
Definition: postgres.h:472
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
Definition: nodes.h:525
#define lsecond(l)
Definition: pg_list.h:200
signed int int32
Definition: c.h:347
#define linitial(l)
Definition: pg_list.h:195
#define Assert(condition)
Definition: c.h:733
static int list_length(const List *l)
Definition: pg_list.h:169
Node * relabel_to_typmod(Node *expr, int32 typmod)
Definition: nodeFuncs.c:587

◆ ValidateDate()

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

Definition at line 2450 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().

2452 {
2453  if (fmask & DTK_M(YEAR))
2454  {
2455  if (isjulian)
2456  {
2457  /* tm_year is correct and should not be touched */
2458  }
2459  else if (bc)
2460  {
2461  /* there is no year zero in AD/BC notation */
2462  if (tm->tm_year <= 0)
2463  return DTERR_FIELD_OVERFLOW;
2464  /* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
2465  tm->tm_year = -(tm->tm_year - 1);
2466  }
2467  else if (is2digits)
2468  {
2469  /* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
2470  if (tm->tm_year < 0) /* just paranoia */
2471  return DTERR_FIELD_OVERFLOW;
2472  if (tm->tm_year < 70)
2473  tm->tm_year += 2000;
2474  else if (tm->tm_year < 100)
2475  tm->tm_year += 1900;
2476  }
2477  else
2478  {
2479  /* there is no year zero in AD/BC notation */
2480  if (tm->tm_year <= 0)
2481  return DTERR_FIELD_OVERFLOW;
2482  }
2483  }
2484 
2485  /* now that we have correct year, decode DOY */
2486  if (fmask & DTK_M(DOY))
2487  {
2488  j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
2489  &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
2490  }
2491 
2492  /* check for valid month */
2493  if (fmask & DTK_M(MONTH))
2494  {
2495  if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
2496  return DTERR_MD_FIELD_OVERFLOW;
2497  }
2498 
2499  /* minimal check for valid day */
2500  if (fmask & DTK_M(DAY))
2501  {
2502  if (tm->tm_mday < 1 || tm->tm_mday > 31)
2503  return DTERR_MD_FIELD_OVERFLOW;
2504  }
2505 
2506  if ((fmask & DTK_DATE_M) == DTK_DATE_M)
2507  {
2508  /*
2509  * Check for valid day of month, now that we know for sure the month
2510  * and year. Note we don't use MD_FIELD_OVERFLOW here, since it seems
2511  * unlikely that "Feb 29" is a YMD-order error.
2512  */
2513  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
2514  return DTERR_FIELD_OVERFLOW;
2515  }
2516 
2517  return 0;
2518 }
#define DAY
Definition: datetime.h:94
#define YEAR
Definition: datetime.h:93
#define isleap(y)
Definition: datetime.h:271
#define DTK_DATE_M
Definition: