1/* src/interfaces/ecpg/pgtypeslib/dt.h */
2
3#ifndef DT_H
4#define DT_H
5
6#include <pgtypes_timestamp.h>
7
8#define MAXTZLEN 10
9
10typedef int32 fsec_t;
11
12#define USE_POSTGRES_DATES 0
13#define USE_ISO_DATES 1
14#define USE_SQL_DATES 2
15#define USE_GERMAN_DATES 3
16
17#define INTSTYLE_POSTGRES 0
18#define INTSTYLE_POSTGRES_VERBOSE 1
19#define INTSTYLE_SQL_STANDARD 2
20#define INTSTYLE_ISO_8601 3
21
22#define INTERVAL_FULL_RANGE (0x7FFF)
23#define INTERVAL_MASK(b) (1 << (b))
24#define MAX_INTERVAL_PRECISION 6
25
26#define DTERR_BAD_FORMAT (-1)
27#define DTERR_FIELD_OVERFLOW (-2)
28#define DTERR_MD_FIELD_OVERFLOW (-3) /* triggers hint about DateStyle */
29#define DTERR_INTERVAL_OVERFLOW (-4)
30#define DTERR_TZDISP_OVERFLOW (-5)
31
32
33#define DAGO "ago"
34#define DCURRENT "current"
35#define EPOCH "epoch"
36#define INVALID "invalid"
37#define EARLY "-infinity"
38#define LATE "infinity"
39#define NOW "now"
40#define TODAY "today"
41#define TOMORROW "tomorrow"
42#define YESTERDAY "yesterday"
43#define ZULU "zulu"
44
45#define DMICROSEC "usecond"
46#define DMILLISEC "msecond"
47#define DSECOND "second"
48#define DMINUTE "minute"
49#define DHOUR "hour"
50#define DDAY "day"
51#define DWEEK "week"
52#define DMONTH "month"
53#define DQUARTER "quarter"
54#define DYEAR "year"
55#define DDECADE "decade"
56#define DCENTURY "century"
57#define DMILLENNIUM "millennium"
58#define DA_D "ad"
59#define DB_C "bc"
60#define DTIMEZONE "timezone"
61
62/*
63 * Fundamental time field definitions for parsing.
64 *
65 * Meridian: am, pm, or 24-hour style.
66 * Millennium: ad, bc
67 */
68
69#define AM 0
70#define PM 1
71#define HR24 2
72
73#define AD 0
74#define BC 1
75
76/*
77 * Field types for time decoding.
78 *
79 * Can't have more of these than there are bits in an unsigned int
80 * since these are turned into bit masks during parsing and decoding.
81 *
82 * Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
83 * must be in the range 0..14 so that the associated bitmasks can fit
84 * into the left half of an INTERVAL's typmod value.
85 *
86 * Copy&pasted these values from src/include/utils/datetime.h
87 * 2008-11-20, changing a number of their values.
88 */
89
90#define RESERV 0
91#define MONTH 1
92#define YEAR 2
93#define DAY 3
94#define JULIAN 4
95#define TZ 5 /* fixed-offset timezone abbreviation */
96#define DTZ 6 /* fixed-offset timezone abbrev, DST */
97#define DYNTZ 7 /* dynamic timezone abbr (unimplemented) */
98#define IGNORE_DTF 8
99#define AMPM 9
100#define HOUR 10
101#define MINUTE 11
102#define SECOND 12
103#define MILLISECOND 13
104#define MICROSECOND 14
105#define DOY 15
106#define DOW 16
107#define UNITS 17
108#define ADBC 18
109/* these are only for relative dates */
110#define AGO 19
111#define ABS_BEFORE 20
112#define ABS_AFTER 21
113/* generic fields to help with parsing */
114#define ISODATE 22
115#define ISOTIME 23
116/* hack for parsing two-word timezone specs "MET DST" etc */
117#define DTZMOD 28 /* "DST" as a separate word */
118/* reserved for unrecognized string values */
119#define UNKNOWN_FIELD 31
120
121
122/*
123 * Token field definitions for time parsing and decoding.
124 *
125 * Some field type codes (see above) use these as the "value" in datetktbl[].
126 * These are also used for bit masks in DecodeDateTime and friends
127 * so actually restrict them to within [0,31] for now.
128 * - thomas 97/06/19
129 * Not all of these fields are used for masks in DecodeDateTime
130 * so allow some larger than 31. - thomas 1997-11-17
131 *
132 * Caution: there are undocumented assumptions in the code that most of these
133 * values are not equal to IGNORE_DTF nor RESERV. Be very careful when
134 * renumbering values in either of these apparently-independent lists :-(
135 */
136
137#define DTK_NUMBER 0
138#define DTK_STRING 1
139
140#define DTK_DATE 2
141#define DTK_TIME 3
142#define DTK_TZ 4
143#define DTK_AGO 5
144
145#define DTK_SPECIAL 6
146#define DTK_EARLY 9
147#define DTK_LATE 10
148#define DTK_EPOCH 11
149#define DTK_NOW 12
150#define DTK_YESTERDAY 13
151#define DTK_TODAY 14
152#define DTK_TOMORROW 15
153#define DTK_ZULU 16
154
155#define DTK_DELTA 17
156#define DTK_SECOND 18
157#define DTK_MINUTE 19
158#define DTK_HOUR 20
159#define DTK_DAY 21
160#define DTK_WEEK 22
161#define DTK_MONTH 23
162#define DTK_QUARTER 24
163#define DTK_YEAR 25
164#define DTK_DECADE 26
165#define DTK_CENTURY 27
166#define DTK_MILLENNIUM 28
167#define DTK_MILLISEC 29
168#define DTK_MICROSEC 30
169#define DTK_JULIAN 31
170
171#define DTK_DOW 32
172#define DTK_DOY 33
173#define DTK_TZ_HOUR 34
174#define DTK_TZ_MINUTE 35
175#define DTK_ISOYEAR 36
176#define DTK_ISODOW 37
177
178
179/*
180 * Bit mask definitions for time parsing.
181 */
182/* Copy&pasted these values from src/include/utils/datetime.h */
183#define DTK_M(t) (0x01 << (t))
184#define DTK_ALL_SECS_M (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))
185#define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
186#define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
187
188/*
189 * Working buffer size for input and output of interval, timestamp, etc.
190 * Inputs that need more working space will be rejected early. Longer outputs
191 * will overrun buffers, so this must suffice for all possible output. As of
192 * this writing, PGTYPESinterval_to_asc() needs the most space at ~90 bytes.
193 */
194#define MAXDATELEN 128
195/* maximum possible number of fields in a date string */
196#define MAXDATEFIELDS 25
197/* only this many chars are stored in datetktbl */
198#define TOKMAXLEN 10
199
200/* keep this struct small; it gets used a lot */
201typedef struct
202{
203 char token[TOKMAXLEN + 1]; /* always NUL-terminated */
204 char type; /* see field type codes above */
205 int32 value; /* meaning depends on type */
206} datetkn;
207
208
209/* FMODULO()
210 * Macro to replace modf(), which is broken on some platforms.
211 * t = input and remainder
212 * q = integer part
213 * u = divisor
214 */
215#define FMODULO(t,q,u) \
216do { \
217 (q) = (((t) < 0) ? ceil((t) / (u)): floor((t) / (u))); \
218 if ((q) != 0) (t) -= rint((q) * (u)); \
219} while(0)
220
221/* TMODULO()
222 * Like FMODULO(), but work on the timestamp datatype (now always int64).
223 * We assume that int64 follows the C99 semantics for division (negative
224 * quotients truncate towards zero).
225 */
226#define TMODULO(t,q,u) \
227do { \
228 (q) = ((t) / (u)); \
229 if ((q) != 0) (t) -= ((q) * (u)); \
230} while(0)
231
232/* in both timestamp.h and ecpg/dt.h */
233#define DAYS_PER_YEAR 365.25 /* assumes leap year every four years */
234#define MONTHS_PER_YEAR 12
235/*
236 * DAYS_PER_MONTH is very imprecise. The more accurate value is
237 * 365.2425/12 = 30.436875, or '30 days 10:29:06'. Right now we only
238 * return an integral number of days, but someday perhaps we should
239 * also return a 'time' value to be used as well. ISO 8601 suggests
240 * 30 days.
241 */
242#define DAYS_PER_MONTH 30 /* assumes exactly 30 days per month */
243#define HOURS_PER_DAY 24 /* assume no daylight savings time changes */
244
245/*
246 * This doesn't adjust for uneven daylight savings time intervals or leap
247 * seconds, and it crudely estimates leap years. A more accurate value
248 * for days per years is 365.2422.
249 */
250#define SECS_PER_YEAR (36525 * 864) /* avoid floating-point computation */
251#define SECS_PER_DAY 86400
252#define SECS_PER_HOUR 3600
253#define SECS_PER_MINUTE 60
254#define MINS_PER_HOUR 60
255
256#define USECS_PER_DAY INT64CONST(86400000000)
257#define USECS_PER_HOUR INT64CONST(3600000000)
258#define USECS_PER_MINUTE INT64CONST(60000000)
259#define USECS_PER_SEC INT64CONST(1000000)
260
261/*
262 * Date/time validation
263 * Include check for leap year.
264 */
265#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
266
267/*
268 * Julian date support --- see comments in backend's timestamp.h.
269 */
270
271#define JULIAN_MINYEAR (-4713)
272#define JULIAN_MINMONTH (11)
273#define JULIAN_MINDAY (24)
274#define JULIAN_MAXYEAR (5874898)
275#define JULIAN_MAXMONTH (6)
276#define JULIAN_MAXDAY (3)
277
278#define IS_VALID_JULIAN(y,m,d) \
279 (((y) > JULIAN_MINYEAR || \
280 ((y) == JULIAN_MINYEAR && ((m) >= JULIAN_MINMONTH))) && \
281 ((y) < JULIAN_MAXYEAR || \
282 ((y) == JULIAN_MAXYEAR && ((m) < JULIAN_MAXMONTH))))
283
284#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
285#define END_TIMESTAMP INT64CONST(9223371331200000000)
286
287#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
288
289#define UTIME_MINYEAR (1901)
290#define UTIME_MINMONTH (12)
291#define UTIME_MINDAY (14)
292#define UTIME_MAXYEAR (2038)
293#define UTIME_MAXMONTH (01)
294#define UTIME_MAXDAY (18)
295
296#define IS_VALID_UTIME(y,m,d) ((((y) > UTIME_MINYEAR) \
297 || (((y) == UTIME_MINYEAR) && (((m) > UTIME_MINMONTH) \
298 || (((m) == UTIME_MINMONTH) && ((d) >= UTIME_MINDAY))))) \
299 && (((y) < UTIME_MAXYEAR) \
300 || (((y) == UTIME_MAXYEAR) && (((m) < UTIME_MAXMONTH) \
301 || (((m) == UTIME_MAXMONTH) && ((d) <= UTIME_MAXDAY))))))
302
303#define DT_NOBEGIN (-INT64CONST(0x7fffffffffffffff) - 1)
304#define DT_NOEND (INT64CONST(0x7fffffffffffffff))
305
306#define TIMESTAMP_NOBEGIN(j) do {(j) = DT_NOBEGIN;} while (0)
307#define TIMESTAMP_NOEND(j) do {(j) = DT_NOEND;} while (0)
308#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
309#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
310#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
311
312int DecodeInterval(char **, int *, int, int *, struct tm *, fsec_t *);
313int DecodeTime(char *, int *, struct tm *, fsec_t *);
314void EncodeDateTime(struct tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates);
315void EncodeInterval(struct tm *tm, fsec_t fsec, int style, char *str);
316int tm2timestamp(struct tm *, fsec_t, int *, timestamp *);
317int DecodeUnits(int field, char *lowtoken, int *val);
318bool CheckDateTokenTables(void);
319void EncodeDateOnly(struct tm *tm, int style, char *str, bool EuroDates);
320int GetEpochTime(struct tm *);
321int ParseDateTime(char *, char *, char **, int *, int *, char **);
322int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool);
323void j2date(int, int *, int *, int *);
324void GetCurrentDateTime(struct tm *);
325int date2j(int, int, int);
326void TrimTrailingZeros(char *);
327void dt2time(double, int *, int *, int *, fsec_t *);
328int PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d,
329 int *year, int *month, int *day,
330 int *hour, int *minute, int *second,
331 int *tz);
332
333extern char *pgtypes_date_weekdays_short[];
334extern char *pgtypes_date_months[];
335extern char *months[];
336extern char *days[];
337extern const int day_tab[2][13];
338
339#endif /* DT_H */
340