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