Header And Logo

PostgreSQL
| The world's most advanced open source database.

dt.h

Go to the documentation of this file.
00001 /* src/interfaces/ecpg/pgtypeslib/dt.h */
00002 
00003 #ifndef DT_H
00004 #define DT_H
00005 
00006 #include <pgtypes_timestamp.h>
00007 
00008 #define MAXTZLEN             10
00009 
00010 #ifdef HAVE_INT64_TIMESTAMP
00011 
00012 typedef int32 fsec_t;
00013 #else
00014 
00015 typedef double fsec_t;
00016 
00017 /* round off to MAX_TIMESTAMP_PRECISION decimal places */
00018 /* note: this is also used for rounding off intervals */
00019 #define TS_PREC_INV 1000000.0
00020 #define TSROUND(j) (rint(((double) (j)) * TS_PREC_INV) / TS_PREC_INV)
00021 #endif
00022 
00023 #define USE_POSTGRES_DATES              0
00024 #define USE_ISO_DATES                   1
00025 #define USE_SQL_DATES                   2
00026 #define USE_GERMAN_DATES                3
00027 
00028 #define INTSTYLE_POSTGRES             0
00029 #define INTSTYLE_POSTGRES_VERBOSE     1
00030 #define INTSTYLE_SQL_STANDARD         2
00031 #define INTSTYLE_ISO_8601             3
00032 
00033 #define INTERVAL_FULL_RANGE (0x7FFF)
00034 #define INTERVAL_MASK(b) (1 << (b))
00035 #define MAX_INTERVAL_PRECISION 6
00036 
00037 #define DTERR_BAD_FORMAT        (-1)
00038 #define DTERR_FIELD_OVERFLOW    (-2)
00039 #define DTERR_MD_FIELD_OVERFLOW (-3)    /* triggers hint about DateStyle */
00040 #define DTERR_INTERVAL_OVERFLOW (-4)
00041 #define DTERR_TZDISP_OVERFLOW   (-5)
00042 
00043 
00044 #define DAGO            "ago"
00045 #define EPOCH           "epoch"
00046 #define INVALID         "invalid"
00047 #define EARLY           "-infinity"
00048 #define LATE            "infinity"
00049 #define NOW             "now"
00050 #define TODAY           "today"
00051 #define TOMORROW        "tomorrow"
00052 #define YESTERDAY       "yesterday"
00053 #define ZULU            "zulu"
00054 
00055 #define DMICROSEC       "usecond"
00056 #define DMILLISEC       "msecond"
00057 #define DSECOND         "second"
00058 #define DMINUTE         "minute"
00059 #define DHOUR           "hour"
00060 #define DDAY            "day"
00061 #define DWEEK           "week"
00062 #define DMONTH          "month"
00063 #define DQUARTER        "quarter"
00064 #define DYEAR           "year"
00065 #define DDECADE         "decade"
00066 #define DCENTURY        "century"
00067 #define DMILLENNIUM     "millennium"
00068 #define DA_D            "ad"
00069 #define DB_C            "bc"
00070 #define DTIMEZONE       "timezone"
00071 #define DCURRENT           "current"
00072 
00073 /*
00074  * Fundamental time field definitions for parsing.
00075  *
00076  *  Meridian:  am, pm, or 24-hour style.
00077  *  Millennium: ad, bc
00078  */
00079 
00080 #define AM      0
00081 #define PM      1
00082 #define HR24    2
00083 
00084 #define AD      0
00085 #define BC      1
00086 
00087 /*
00088  * Fields for time decoding.
00089  *
00090  * Can't have more of these than there are bits in an unsigned int
00091  * since these are turned into bit masks during parsing and decoding.
00092  *
00093  * Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
00094  * must be in the range 0..14 so that the associated bitmasks can fit
00095  * into the left half of an INTERVAL's typmod value.
00096  *
00097  * Copy&pasted these values from src/include/utils/datetime.h
00098  * 2008-11-20, changing a number of their values.
00099  */
00100 
00101 #define RESERV  0
00102 #define MONTH   1
00103 #define YEAR    2
00104 #define DAY     3
00105 #define JULIAN  4
00106 #define TZ      5
00107 #define DTZ     6
00108 #define DTZMOD  7
00109 #define IGNORE_DTF  8
00110 #define AMPM    9
00111 #define HOUR    10
00112 #define MINUTE  11
00113 #define SECOND  12
00114 #define MILLISECOND 13
00115 #define MICROSECOND 14
00116 #define DOY     15
00117 #define DOW     16
00118 #define UNITS   17
00119 #define ADBC    18
00120 /* these are only for relative dates */
00121 #define AGO     19
00122 #define ABS_BEFORE      20
00123 #define ABS_AFTER       21
00124 /* generic fields to help with parsing */
00125 #define ISODATE 22
00126 #define ISOTIME 23
00127 /* reserved for unrecognized string values */
00128 #define UNKNOWN_FIELD   31
00129 
00130 
00131 /*
00132  * Token field definitions for time parsing and decoding.
00133  * These need to fit into the datetkn table type.
00134  * At the moment, that means keep them within [-127,127].
00135  * These are also used for bit masks in DecodeDateDelta()
00136  *  so actually restrict them to within [0,31] for now.
00137  * - thomas 97/06/19
00138  * Not all of these fields are used for masks in DecodeDateDelta
00139  *  so allow some larger than 31. - thomas 1997-11-17
00140  */
00141 
00142 #define DTK_NUMBER      0
00143 #define DTK_STRING      1
00144 
00145 #define DTK_DATE        2
00146 #define DTK_TIME        3
00147 #define DTK_TZ          4
00148 #define DTK_AGO         5
00149 
00150 #define DTK_SPECIAL     6
00151 #define DTK_INVALID     7
00152 #define DTK_CURRENT     8
00153 #define DTK_EARLY       9
00154 #define DTK_LATE        10
00155 #define DTK_EPOCH       11
00156 #define DTK_NOW         12
00157 #define DTK_YESTERDAY   13
00158 #define DTK_TODAY       14
00159 #define DTK_TOMORROW    15
00160 #define DTK_ZULU        16
00161 
00162 #define DTK_DELTA       17
00163 #define DTK_SECOND      18
00164 #define DTK_MINUTE      19
00165 #define DTK_HOUR        20
00166 #define DTK_DAY         21
00167 #define DTK_WEEK        22
00168 #define DTK_MONTH       23
00169 #define DTK_QUARTER     24
00170 #define DTK_YEAR        25
00171 #define DTK_DECADE      26
00172 #define DTK_CENTURY     27
00173 #define DTK_MILLENNIUM  28
00174 #define DTK_MILLISEC    29
00175 #define DTK_MICROSEC    30
00176 #define DTK_JULIAN      31
00177 
00178 #define DTK_DOW         32
00179 #define DTK_DOY         33
00180 #define DTK_TZ_HOUR     34
00181 #define DTK_TZ_MINUTE   35
00182 #define DTK_ISOYEAR     36
00183 #define DTK_ISODOW      37
00184 
00185 
00186 /*
00187  * Bit mask definitions for time parsing.
00188  */
00189 /* Copy&pasted these values from src/include/utils/datetime.h */
00190 #define DTK_M(t)        (0x01 << (t))
00191 #define DTK_ALL_SECS_M     (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))
00192 #define DTK_DATE_M      (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
00193 #define DTK_TIME_M      (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
00194 
00195 #define MAXDATELEN      63      /* maximum possible length of an input date
00196                                  * string (not counting tr. null) */
00197 #define MAXDATEFIELDS   25      /* maximum possible number of fields in a date
00198                                  * string */
00199 #define TOKMAXLEN       10      /* only this many chars are stored in
00200                                  * datetktbl */
00201 
00202 /* keep this struct small; it gets used a lot */
00203 typedef struct
00204 {
00205 #if defined(_AIX)
00206     char       *token;
00207 #else
00208     char        token[TOKMAXLEN];
00209 #endif   /* _AIX */
00210     char        type;
00211     char        value;          /* this may be unsigned, alas */
00212 } datetkn;
00213 
00214 
00215 /* FMODULO()
00216  * Macro to replace modf(), which is broken on some platforms.
00217  * t = input and remainder
00218  * q = integer part
00219  * u = divisor
00220  */
00221 #define FMODULO(t,q,u) \
00222 do { \
00223     (q) = (((t) < 0) ? ceil((t) / (u)): floor((t) / (u))); \
00224     if ((q) != 0) (t) -= rint((q) * (u)); \
00225 } while(0)
00226 
00227 /* TMODULO()
00228  * Like FMODULO(), but work on the timestamp datatype (either int64 or float8).
00229  * We assume that int64 follows the C99 semantics for division (negative
00230  * quotients truncate towards zero).
00231  */
00232 #ifdef HAVE_INT64_TIMESTAMP
00233 #define TMODULO(t,q,u) \
00234 do { \
00235     (q) = ((t) / (u)); \
00236     if ((q) != 0) (t) -= ((q) * (u)); \
00237 } while(0)
00238 #else
00239 #define TMODULO(t,q,u) \
00240 do { \
00241     (q) = (((t) < 0) ? ceil((t) / (u)): floor((t) / (u))); \
00242     if ((q) != 0) (t) -= rint((q) * (u)); \
00243 } while(0)
00244 #endif
00245 
00246 /* in both timestamp.h and ecpg/dt.h */
00247 #define DAYS_PER_YEAR   365.25  /* assumes leap year every four years */
00248 #define MONTHS_PER_YEAR 12
00249 /*
00250  *  DAYS_PER_MONTH is very imprecise.  The more accurate value is
00251  *  365.2425/12 = 30.436875, or '30 days 10:29:06'.  Right now we only
00252  *  return an integral number of days, but someday perhaps we should
00253  *  also return a 'time' value to be used as well.  ISO 8601 suggests
00254  *  30 days.
00255  */
00256 #define DAYS_PER_MONTH  30      /* assumes exactly 30 days per month */
00257 #define HOURS_PER_DAY   24      /* assume no daylight savings time changes */
00258 
00259 /*
00260  *  This doesn't adjust for uneven daylight savings time intervals or leap
00261  *  seconds, and it crudely estimates leap years.  A more accurate value
00262  *  for days per years is 365.2422.
00263  */
00264 #define SECS_PER_YEAR   (36525 * 864)   /* avoid floating-point computation */
00265 #define SECS_PER_DAY    86400
00266 #define SECS_PER_HOUR   3600
00267 #define SECS_PER_MINUTE 60
00268 #define MINS_PER_HOUR   60
00269 
00270 #ifdef HAVE_INT64_TIMESTAMP
00271 #define USECS_PER_DAY   INT64CONST(86400000000)
00272 #define USECS_PER_HOUR  INT64CONST(3600000000)
00273 #define USECS_PER_MINUTE INT64CONST(60000000)
00274 #define USECS_PER_SEC   INT64CONST(1000000)
00275 #endif
00276 
00277 /*
00278  * Date/time validation
00279  * Include check for leap year.
00280  */
00281 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
00282 
00283 /* Julian date support for date2j() and j2date()
00284  *
00285  * IS_VALID_JULIAN checks the minimum date exactly, but is a bit sloppy
00286  * about the maximum, since it's far enough out to not be especially
00287  * interesting.
00288  */
00289 
00290 #define JULIAN_MINYEAR (-4713)
00291 #define JULIAN_MINMONTH (11)
00292 #define JULIAN_MINDAY (24)
00293 #define JULIAN_MAXYEAR (5874898)
00294 
00295 #define IS_VALID_JULIAN(y,m,d) ((((y) > JULIAN_MINYEAR) \
00296   || (((y) == JULIAN_MINYEAR) && (((m) > JULIAN_MINMONTH) \
00297   || (((m) == JULIAN_MINMONTH) && ((d) >= JULIAN_MINDAY))))) \
00298  && ((y) < JULIAN_MAXYEAR))
00299 
00300 #define UTIME_MINYEAR (1901)
00301 #define UTIME_MINMONTH (12)
00302 #define UTIME_MINDAY (14)
00303 #define UTIME_MAXYEAR (2038)
00304 #define UTIME_MAXMONTH (01)
00305 #define UTIME_MAXDAY (18)
00306 
00307 #define IS_VALID_UTIME(y,m,d) ((((y) > UTIME_MINYEAR) \
00308  || (((y) == UTIME_MINYEAR) && (((m) > UTIME_MINMONTH) \
00309   || (((m) == UTIME_MINMONTH) && ((d) >= UTIME_MINDAY))))) \
00310  && (((y) < UTIME_MAXYEAR) \
00311  || (((y) == UTIME_MAXYEAR) && (((m) < UTIME_MAXMONTH) \
00312   || (((m) == UTIME_MAXMONTH) && ((d) <= UTIME_MAXDAY))))))
00313 
00314 #ifdef HAVE_INT64_TIMESTAMP
00315 
00316 #define DT_NOBEGIN      (-INT64CONST(0x7fffffffffffffff) - 1)
00317 #define DT_NOEND        (INT64CONST(0x7fffffffffffffff))
00318 #else
00319 
00320 #ifdef HUGE_VAL
00321 #define DT_NOBEGIN      (-HUGE_VAL)
00322 #define DT_NOEND        (HUGE_VAL)
00323 #else
00324 #define DT_NOBEGIN      (-DBL_MAX)
00325 #define DT_NOEND        (DBL_MAX)
00326 #endif
00327 #endif   /* HAVE_INT64_TIMESTAMP */
00328 
00329 #define TIMESTAMP_NOBEGIN(j)    do {(j) = DT_NOBEGIN;} while (0)
00330 #define TIMESTAMP_NOEND(j)          do {(j) = DT_NOEND;} while (0)
00331 #define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
00332 #define TIMESTAMP_IS_NOEND(j)   ((j) == DT_NOEND)
00333 #define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
00334 
00335 int         DecodeInterval(char **, int *, int, int *, struct tm *, fsec_t *);
00336 int         DecodeTime(char *, int *, struct tm *, fsec_t *);
00337 int         EncodeDateTime(struct tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates);
00338 int         EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str);
00339 int         tm2timestamp(struct tm *, fsec_t, int *, timestamp *);
00340 int         DecodeUnits(int field, char *lowtoken, int *val);
00341 bool        CheckDateTokenTables(void);
00342 int         EncodeDateOnly(struct tm * tm, int style, char *str, bool EuroDates);
00343 int         GetEpochTime(struct tm *);
00344 int         ParseDateTime(char *, char *, char **, int *, int *, char **);
00345 int         DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool);
00346 void        j2date(int, int *, int *, int *);
00347 void        GetCurrentDateTime(struct tm *);
00348 int         date2j(int, int, int);
00349 void        TrimTrailingZeros(char *);
00350 void        dt2time(double, int *, int *, int *, fsec_t *);
00351 
00352 extern char *pgtypes_date_weekdays_short[];
00353 extern char *pgtypes_date_months[];
00354 extern char *months[];
00355 extern char *days[];
00356 extern int  day_tab[2][13];
00357 
00358 #endif   /* DT_H */