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 | |
10 | typedef 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 */ |
201 | typedef 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) \ |
216 | do { \ |
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) \ |
227 | do { \ |
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 | |
312 | int DecodeInterval(char **, int *, int, int *, struct tm *, fsec_t *); |
313 | int DecodeTime(char *, int *, struct tm *, fsec_t *); |
314 | void EncodeDateTime(struct tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates); |
315 | void EncodeInterval(struct tm *tm, fsec_t fsec, int style, char *str); |
316 | int tm2timestamp(struct tm *, fsec_t, int *, timestamp *); |
317 | int DecodeUnits(int field, char *lowtoken, int *val); |
318 | bool CheckDateTokenTables(void); |
319 | void EncodeDateOnly(struct tm *tm, int style, char *str, bool EuroDates); |
320 | int GetEpochTime(struct tm *); |
321 | int ParseDateTime(char *, char *, char **, int *, int *, char **); |
322 | int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool); |
323 | void j2date(int, int *, int *, int *); |
324 | void GetCurrentDateTime(struct tm *); |
325 | int date2j(int, int, int); |
326 | void TrimTrailingZeros(char *); |
327 | void dt2time(double, int *, int *, int *, fsec_t *); |
328 | int 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 | |
333 | extern char *pgtypes_date_weekdays_short[]; |
334 | extern char *pgtypes_date_months[]; |
335 | extern char *months[]; |
336 | extern char *days[]; |
337 | extern const int day_tab[2][13]; |
338 | |
339 | #endif /* DT_H */ |
340 | |