codekingpro/portable-devtools
115k
1/*-------------------------------------------------------------------------2 *3 * datetime.h4 * Definitions for date/time support code.5 * The support code is shared with other date data types,6 * including date, and time.7 *8 *9 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group10 * Portions Copyright (c) 1994, Regents of the University of California11 *12 * src/include/utils/datetime.h13 *14 *-------------------------------------------------------------------------15 */16#ifndef DATETIME_H17#define DATETIME_H18 19#include "utils/timestamp.h"20 21/* this struct is declared in utils/tzparser.h: */22struct tzEntry;23 24 25/* ----------------------------------------------------------------26 * time types + support macros27 *28 * String definitions for standard time quantities.29 *30 * These strings are the defaults used to form output time strings.31 * Other alternative forms are hardcoded into token tables in datetime.c.32 * ----------------------------------------------------------------33 */34 35#define DAGO "ago"36#define DCURRENT "current"37#define EPOCH "epoch"38#define INVALID "invalid"39#define EARLY "-infinity"40#define LATE "infinity"41#define NOW "now"42#define TODAY "today"43#define TOMORROW "tomorrow"44#define YESTERDAY "yesterday"45#define ZULU "zulu"46 47#define DMICROSEC "usecond"48#define DMILLISEC "msecond"49#define DSECOND "second"50#define DMINUTE "minute"51#define DHOUR "hour"52#define DDAY "day"53#define DWEEK "week"54#define DMONTH "month"55#define DQUARTER "quarter"56#define DYEAR "year"57#define DDECADE "decade"58#define DCENTURY "century"59#define DMILLENNIUM "millennium"60#define DA_D "ad"61#define DB_C "bc"62#define DTIMEZONE "timezone"63 64/*65 * Fundamental time field definitions for parsing.66 *67 * Meridian: am, pm, or 24-hour style.68 * Millennium: ad, bc69 */70 71#define AM 072#define PM 173#define HR24 274 75#define AD 076#define BC 177 78/*79 * Field types for time decoding.80 *81 * Can't have more of these than there are bits in an unsigned int82 * since these are turned into bit masks during parsing and decoding.83 *84 * Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND85 * must be in the range 0..14 so that the associated bitmasks can fit86 * into the left half of an INTERVAL's typmod value. Since those bits87 * are stored in typmods, you can't change them without initdb!88 */89 90#define RESERV 091#define MONTH 192#define YEAR 293#define DAY 394#define JULIAN 495#define TZ 5 /* fixed-offset timezone abbreviation */96#define DTZ 6 /* fixed-offset timezone abbrev, DST */97#define DYNTZ 7 /* dynamic timezone abbreviation */98#define IGNORE_DTF 899#define AMPM 9100#define HOUR 10101#define MINUTE 11102#define SECOND 12103#define MILLISECOND 13104#define MICROSECOND 14105#define DOY 15106#define DOW 16107#define UNITS 17108#define ADBC 18109/* these are only for relative dates */110#define AGO 19111#define ABS_BEFORE 20112#define ABS_AFTER 21113/* generic fields to help with parsing */114#define ISODATE 22115#define ISOTIME 23116/* these are only for parsing intervals */117#define WEEK 24118#define DECADE 25119#define CENTURY 26120#define MILLENNIUM 27121/* hack for parsing two-word timezone specs "MET DST" etc */122#define DTZMOD 28 /* "DST" as a separate word */123/* reserved for unrecognized string values */124#define UNKNOWN_FIELD 31125 126/*127 * Token field definitions for time parsing and decoding.128 *129 * Some field type codes (see above) use these as the "value" in datetktbl[].130 * These are also used for bit masks in DecodeDateTime and friends131 * so actually restrict them to within [0,31] for now.132 * - thomas 97/06/19133 * Not all of these fields are used for masks in DecodeDateTime134 * so allow some larger than 31. - thomas 1997-11-17135 *136 * Caution: there are undocumented assumptions in the code that most of these137 * values are not equal to IGNORE_DTF nor RESERV. Be very careful when138 * renumbering values in either of these apparently-independent lists :-(139 */140 141#define DTK_NUMBER 0142#define DTK_STRING 1143 144#define DTK_DATE 2145#define DTK_TIME 3146#define DTK_TZ 4147#define DTK_AGO 5148 149#define DTK_SPECIAL 6150#define DTK_EARLY 9151#define DTK_LATE 10152#define DTK_EPOCH 11153#define DTK_NOW 12154#define DTK_YESTERDAY 13155#define DTK_TODAY 14156#define DTK_TOMORROW 15157#define DTK_ZULU 16158 159#define DTK_DELTA 17160#define DTK_SECOND 18161#define DTK_MINUTE 19162#define DTK_HOUR 20163#define DTK_DAY 21164#define DTK_WEEK 22165#define DTK_MONTH 23166#define DTK_QUARTER 24167#define DTK_YEAR 25168#define DTK_DECADE 26169#define DTK_CENTURY 27170#define DTK_MILLENNIUM 28171#define DTK_MILLISEC 29172#define DTK_MICROSEC 30173#define DTK_JULIAN 31174 175#define DTK_DOW 32176#define DTK_DOY 33177#define DTK_TZ_HOUR 34178#define DTK_TZ_MINUTE 35179#define DTK_ISOYEAR 36180#define DTK_ISODOW 37181 182 183/*184 * Bit mask definitions for time parsing.185 */186 187#define DTK_M(t) (0x01 << (t))188 189/* Convenience: a second, plus any fractional component */190#define DTK_ALL_SECS_M (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))191#define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))192#define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_ALL_SECS_M)193 194/*195 * Working buffer size for input and output of interval, timestamp, etc.196 * Inputs that need more working space will be rejected early. Longer outputs197 * will overrun buffers, so this must suffice for all possible output. As of198 * this writing, interval_out() needs the most space at ~90 bytes.199 */200#define MAXDATELEN 128201/* maximum possible number of fields in a date string */202#define MAXDATEFIELDS 25203/* only this many chars are stored in datetktbl */204#define TOKMAXLEN 10205 206/* keep this struct small; it gets used a lot */207typedef struct208{209 char token[TOKMAXLEN + 1]; /* always NUL-terminated */210 char type; /* see field type codes above */211 int32 value; /* meaning depends on type */212} datetkn;213 214/* one of its uses is in tables of time zone abbreviations */215typedef struct TimeZoneAbbrevTable216{217 Size tblsize; /* size in bytes of TimeZoneAbbrevTable */218 int numabbrevs; /* number of entries in abbrevs[] array */219 datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER];220 /* DynamicZoneAbbrev(s) may follow the abbrevs[] array */221} TimeZoneAbbrevTable;222 223/* auxiliary data for a dynamic time zone abbreviation (non-fixed-offset) */224typedef struct DynamicZoneAbbrev225{226 pg_tz *tz; /* NULL if not yet looked up */227 char zone[FLEXIBLE_ARRAY_MEMBER]; /* NUL-terminated zone name */228} DynamicZoneAbbrev;229 230 231/* FMODULO()232 * Macro to replace modf(), which is broken on some platforms.233 * t = input and remainder234 * q = integer part235 * u = divisor236 */237#define FMODULO(t,q,u) \238do { \239 (q) = (((t) < 0) ? ceil((t) / (u)) : floor((t) / (u))); \240 if ((q) != 0) (t) -= rint((q) * (u)); \241} while(0)242 243/* TMODULO()244 * Like FMODULO(), but work on the timestamp datatype (now always int64).245 * We assume that int64 follows the C99 semantics for division (negative246 * quotients truncate towards zero).247 */248#define TMODULO(t,q,u) \249do { \250 (q) = ((t) / (u)); \251 if ((q) != 0) (t) -= ((q) * (u)); \252} while(0)253 254/*255 * Date/time validation256 * Include check for leap year.257 */258 259extern PGDLLIMPORT const char *const months[]; /* months (3-char260 * abbreviations) */261extern PGDLLIMPORT const char *const days[]; /* days (full names) */262extern PGDLLIMPORT const int day_tab[2][13];263 264/*265 * These are the rules for the Gregorian calendar, which was adopted in 1582.266 * However, we use this calculation for all prior years as well because the267 * SQL standard specifies use of the Gregorian calendar. This prevents the268 * date 1500-02-29 from being stored, even though it is valid in the Julian269 * calendar.270 */271#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))272 273 274/*275 * Datetime input parsing routines (ParseDateTime, DecodeDateTime, etc)276 * return zero or a positive value on success. On failure, they return277 * one of these negative code values. DateTimeParseError may be used to278 * produce a suitable error report. For some of these codes,279 * DateTimeParseError requires additional information, which is carried280 * in struct DateTimeErrorExtra.281 */282#define DTERR_BAD_FORMAT (-1)283#define DTERR_FIELD_OVERFLOW (-2)284#define DTERR_MD_FIELD_OVERFLOW (-3) /* triggers hint about DateStyle */285#define DTERR_INTERVAL_OVERFLOW (-4)286#define DTERR_TZDISP_OVERFLOW (-5)287#define DTERR_BAD_TIMEZONE (-6)288#define DTERR_BAD_ZONE_ABBREV (-7)289 290typedef struct DateTimeErrorExtra291{292 /* Needed for DTERR_BAD_TIMEZONE and DTERR_BAD_ZONE_ABBREV: */293 const char *dtee_timezone; /* incorrect time zone name */294 /* Needed for DTERR_BAD_ZONE_ABBREV: */295 const char *dtee_abbrev; /* relevant time zone abbreviation */296} DateTimeErrorExtra;297 298/* Result codes for DecodeTimezoneName() */299#define TZNAME_FIXED_OFFSET 0300#define TZNAME_DYNTZ 1301#define TZNAME_ZONE 2302 303 304extern void GetCurrentDateTime(struct pg_tm *tm);305extern void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp);306extern void j2date(int jd, int *year, int *month, int *day);307extern int date2j(int year, int month, int day);308 309extern int ParseDateTime(const char *timestr, char *workbuf, size_t buflen,310 char **field, int *ftype,311 int maxfields, int *numfields);312extern int DecodeDateTime(char **field, int *ftype, int nf,313 int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,314 DateTimeErrorExtra *extra);315extern int DecodeTimezone(const char *str, int *tzp);316extern int DecodeTimeOnly(char **field, int *ftype, int nf,317 int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,318 DateTimeErrorExtra *extra);319extern int DecodeInterval(char **field, int *ftype, int nf, int range,320 int *dtype, struct pg_itm_in *itm_in);321extern int DecodeISO8601Interval(char *str,322 int *dtype, struct pg_itm_in *itm_in);323 324extern void DateTimeParseError(int dterr, DateTimeErrorExtra *extra,325 const char *str, const char *datatype,326 struct Node *escontext);327 328extern int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp);329extern int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp);330extern int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr,331 pg_tz *tzp, int *isdst);332 333extern void EncodeDateOnly(struct pg_tm *tm, int style, char *str);334extern void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str);335extern void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str);336extern void EncodeInterval(struct pg_itm *itm, int style, char *str);337extern void EncodeSpecialTimestamp(Timestamp dt, char *str);338 339extern int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,340 struct pg_tm *tm);341 342extern int DecodeTimezoneAbbrev(int field, const char *lowtoken,343 int *ftype, int *offset, pg_tz **tz,344 DateTimeErrorExtra *extra);345extern int DecodeSpecial(int field, const char *lowtoken, int *val);346extern int DecodeUnits(int field, const char *lowtoken, int *val);347 348extern int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz);349extern pg_tz *DecodeTimezoneNameToTz(const char *tzname);350 351extern int j2day(int date);352 353extern struct Node *TemporalSimplify(int32 max_precis, struct Node *node);354 355extern bool CheckDateTokenTables(void);356 357extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,358 int n);359extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);360 361extern bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod,362 struct Node *escontext);363 364#endif /* DATETIME_H */365 