1 /*-------------------------------------------------------------------------
4 * Definitions for date/time support code.
5 * The support code is shared with other date data types,
6 * including date, and time.
9 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/include/utils/datetime.h
14 *-------------------------------------------------------------------------
19 #include "utils/timestamp.h"
21 /* this struct is declared in utils/tzparser.h: */
25 /* ----------------------------------------------------------------
26 * time types + support macros
28 * String definitions for standard time quantities.
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 * ----------------------------------------------------------------
36 #define DCURRENT "current"
38 #define INVALID "invalid"
39 #define EARLY "-infinity"
40 #define LATE "infinity"
43 #define TOMORROW "tomorrow"
44 #define YESTERDAY "yesterday"
47 #define DMICROSEC "usecond"
48 #define DMILLISEC "msecond"
49 #define DSECOND "second"
50 #define DMINUTE "minute"
54 #define DMONTH "month"
55 #define DQUARTER "quarter"
57 #define DDECADE "decade"
58 #define DCENTURY "century"
59 #define DMILLENNIUM "millennium"
62 #define DTIMEZONE "timezone"
65 * Fundamental time field definitions for parsing.
67 * Meridian: am, pm, or 24-hour style.
79 * Field types for time decoding.
81 * Can't have more of these than there are bits in an unsigned int
82 * since these are turned into bit masks during parsing and decoding.
84 * Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
85 * must be in the range 0..14 so that the associated bitmasks can fit
86 * into the left half of an INTERVAL's typmod value. Since those bits
87 * are stored in typmods, you can't change them without initdb!
95 #define TZ 5 /* fixed-offset timezone abbreviation */
96 #define DTZ 6 /* fixed-offset timezone abbrev, DST */
97 #define DYNTZ 7 /* dynamic timezone abbreviation */
103 #define MILLISECOND 13
104 #define MICROSECOND 14
109 /* these are only for relative dates */
111 #define ABS_BEFORE 20
113 /* generic fields to help with parsing */
116 /* these are only for parsing intervals */
120 #define MILLENNIUM 27
121 /* 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 31
127 * Token field definitions for time parsing and decoding.
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 friends
131 * so actually restrict them to within [0,31] for now.
133 * Not all of these fields are used for masks in DecodeDateTime
134 * so allow some larger than 31. - thomas 1997-11-17
136 * Caution: there are undocumented assumptions in the code that most of these
137 * values are not equal to IGNORE_DTF nor RESERV. Be very careful when
138 * renumbering values in either of these apparently-independent lists :-(
149 #define DTK_SPECIAL 6
154 #define DTK_YESTERDAY 13
156 #define DTK_TOMORROW 15
160 #define DTK_SECOND 18
161 #define DTK_MINUTE 19
166 #define DTK_QUARTER 24
168 #define DTK_DECADE 26
169 #define DTK_CENTURY 27
170 #define DTK_MILLENNIUM 28
171 #define DTK_MILLISEC 29
172 #define DTK_MICROSEC 30
173 #define DTK_JULIAN 31
177 #define DTK_TZ_HOUR 34
178 #define DTK_TZ_MINUTE 35
179 #define DTK_ISOYEAR 36
180 #define DTK_ISODOW 37
184 * Bit mask definitions for time parsing.
187 #define DTK_M(t) (0x01 << (t))
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)
195 * Working buffer size for input and output of interval, timestamp, etc.
196 * Inputs that need more working space will be rejected early. Longer outputs
197 * will overrun buffers, so this must suffice for all possible output. As of
198 * this writing, interval_out() needs the most space at ~90 bytes.
200 #define MAXDATELEN 128
201 /* maximum possible number of fields in a date string */
202 #define MAXDATEFIELDS 25
203 /* only this many chars are stored in datetktbl */
206 /* keep this struct small; it gets used a lot */
209 char token
[TOKMAXLEN
+ 1]; /* always NUL-terminated */
210 char type
; /* see field type codes above */
211 int32 value
; /* meaning depends on type */
214 /* one of its uses is in tables of time zone abbreviations */
215 typedef struct TimeZoneAbbrevTable
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
;
223 /* auxiliary data for a dynamic time zone abbreviation (non-fixed-offset) */
224 typedef struct DynamicZoneAbbrev
226 pg_tz
*tz
; /* NULL if not yet looked up */
227 char zone
[FLEXIBLE_ARRAY_MEMBER
]; /* NUL-terminated zone name */
232 * Macro to replace modf(), which is broken on some platforms.
233 * t = input and remainder
237 #define FMODULO(t,q,u) \
239 (q) = (((t) < 0) ? ceil((t) / (u)) : floor((t) / (u))); \
240 if ((q) != 0) (t) -= rint((q) * (u)); \
244 * Like FMODULO(), but work on the timestamp datatype (now always int64).
245 * We assume that int64 follows the C99 semantics for division (negative
246 * quotients truncate towards zero).
248 #define TMODULO(t,q,u) \
251 if ((q) != 0) (t) -= ((q) * (u)); \
255 * Date/time validation
256 * Include check for leap year.
259 extern PGDLLIMPORT
const char *const months
[]; /* months (3-char
261 extern PGDLLIMPORT
const char *const days
[]; /* days (full names) */
262 extern PGDLLIMPORT
const int day_tab
[2][13];
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 the
267 * SQL standard specifies use of the Gregorian calendar. This prevents the
268 * date 1500-02-29 from being stored, even though it is valid in the Julian
271 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
275 * Datetime input parsing routines (ParseDateTime, DecodeDateTime, etc)
276 * return zero or a positive value on success. On failure, they return
277 * one of these negative code values. DateTimeParseError may be used to
278 * produce a suitable error report. For some of these codes,
279 * DateTimeParseError requires additional information, which is carried
280 * in struct DateTimeErrorExtra.
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)
290 typedef struct DateTimeErrorExtra
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
;
298 /* Result codes for DecodeTimezoneName() */
299 #define TZNAME_FIXED_OFFSET 0
300 #define TZNAME_DYNTZ 1
301 #define TZNAME_ZONE 2
304 extern void GetCurrentDateTime(struct pg_tm
*tm
);
305 extern void GetCurrentTimeUsec(struct pg_tm
*tm
, fsec_t
*fsec
, int *tzp
);
306 extern void j2date(int jd
, int *year
, int *month
, int *day
);
307 extern int date2j(int year
, int month
, int day
);
309 extern int ParseDateTime(const char *timestr
, char *workbuf
, size_t buflen
,
310 char **field
, int *ftype
,
311 int maxfields
, int *numfields
);
312 extern int DecodeDateTime(char **field
, int *ftype
, int nf
,
313 int *dtype
, struct pg_tm
*tm
, fsec_t
*fsec
, int *tzp
,
314 DateTimeErrorExtra
*extra
);
315 extern int DecodeTimezone(const char *str
, int *tzp
);
316 extern int DecodeTimeOnly(char **field
, int *ftype
, int nf
,
317 int *dtype
, struct pg_tm
*tm
, fsec_t
*fsec
, int *tzp
,
318 DateTimeErrorExtra
*extra
);
319 extern int DecodeInterval(char **field
, int *ftype
, int nf
, int range
,
320 int *dtype
, struct pg_itm_in
*itm_in
);
321 extern int DecodeISO8601Interval(char *str
,
322 int *dtype
, struct pg_itm_in
*itm_in
);
324 extern void DateTimeParseError(int dterr
, DateTimeErrorExtra
*extra
,
325 const char *str
, const char *datatype
,
326 struct Node
*escontext
);
328 extern int DetermineTimeZoneOffset(struct pg_tm
*tm
, pg_tz
*tzp
);
329 extern int DetermineTimeZoneAbbrevOffset(struct pg_tm
*tm
, const char *abbr
, pg_tz
*tzp
);
330 extern int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts
, const char *abbr
,
331 pg_tz
*tzp
, int *isdst
);
333 extern void EncodeDateOnly(struct pg_tm
*tm
, int style
, char *str
);
334 extern void EncodeTimeOnly(struct pg_tm
*tm
, fsec_t fsec
, bool print_tz
, int tz
, int style
, char *str
);
335 extern void EncodeDateTime(struct pg_tm
*tm
, fsec_t fsec
, bool print_tz
, int tz
, const char *tzn
, int style
, char *str
);
336 extern void EncodeInterval(struct pg_itm
*itm
, int style
, char *str
);
337 extern void EncodeSpecialTimestamp(Timestamp dt
, char *str
);
339 extern int ValidateDate(int fmask
, bool isjulian
, bool is2digits
, bool bc
,
342 extern int DecodeTimezoneAbbrev(int field
, const char *lowtoken
,
343 int *ftype
, int *offset
, pg_tz
**tz
,
344 DateTimeErrorExtra
*extra
);
345 extern int DecodeSpecial(int field
, const char *lowtoken
, int *val
);
346 extern int DecodeUnits(int field
, const char *lowtoken
, int *val
);
348 extern int DecodeTimezoneName(const char *tzname
, int *offset
, pg_tz
**tz
);
349 extern pg_tz
*DecodeTimezoneNameToTz(const char *tzname
);
351 extern int DecodeTimezoneAbbrevPrefix(const char *str
,
352 int *offset
, pg_tz
**tz
);
354 extern int j2day(int date
);
356 extern struct Node
*TemporalSimplify(int32 max_precis
, struct Node
*node
);
358 extern bool CheckDateTokenTables(void);
360 extern TimeZoneAbbrevTable
*ConvertTimeZoneAbbrevs(struct tzEntry
*abbrevs
,
362 extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable
*tbl
);
364 extern bool AdjustTimestampForTypmod(Timestamp
*time
, int32 typmod
,
365 struct Node
*escontext
);
367 #endif /* DATETIME_H */