dt.h 8.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*-------------------------------------------------------------------------
 *
 * dt.h--
 *    Definitions for the date/time and other date/time support code.
 *    The support code is shared with other date data types,
 *     including abstime, reltime, date, and time.
 *
 *
 * Copyright (c) 1994, Regents of the University of California
 *
11
 * $Id: dt.h,v 1.3 1997/03/25 08:11:18 scrappy Exp $
12 13 14 15 16 17 18
 *
 *-------------------------------------------------------------------------
 */
#ifndef DT_H
#define DT_H

#include <time.h>
19
#include <math.h>
20 21 22

/*
 * DateTime represents absolute time.
23 24 25 26
 * TimeSpan represents delta time. Keep track of months (and years)
 *  separately since the elapsed time spanned is unknown until instantiated
 *  relative to an absolute time.
 *
27
 * Note that Postgres uses "time interval" to mean a bounded interval,
28
 *  consisting of a beginning and ending time, not a time span - tgl 97/03/20
29 30 31 32 33 34
 */

typedef double DateTime;

typedef struct {
    double      time;   /* all time units other than months and years */
35
    int4        month;  /* months and years, after time for alignment */
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
} TimeSpan;


#define USE_NEW_TIME_CODE	1
#define USE_NEW_DATE		0
#define USE_NEW_TIME		0

/* ----------------------------------------------------------------
 *		time types + support macros
 *
 * String definitions for standard time quantities.
 *
 * These strings are the defaults used to form output time strings.
 * Other alternate forms are hardcoded into token tables in dt.c.
 * ----------------------------------------------------------------
 */
52

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#define DAGO		"ago"
#define DCURRENT	"current"
#define EPOCH		"epoch"
#define INVALID		"invalid"
#define EARLY		"-infinity"
#define LATE		"infinity"
#define NOW		"now"
#define TODAY		"today"
#define TOMORROW	"tomorrow"
#define YESTERDAY	"yesterday"
#define ZULU		"zulu"

#define DMICROSEC	"usecond"
#define DMILLISEC	"msecond"
#define DSECOND		"second"
#define DMINUTE		"minute"
#define DHOUR		"hour"
#define DDAY		"day"
#define DWEEK		"week"
#define DMONTH		"month"
73
#define DQUARTER	"quarter"
74 75 76 77 78 79
#define DYEAR		"year"
#define DDECADE		"decade"
#define DCENTURY	"century"
#define DMILLENIUM	"millenium"
#define DA_D		"ad"
#define DB_C		"bc"
80
#define DTIMEZONE	"timezone"
81 82 83 84 85 86 87

/*
 * Fundamental time field definitions for parsing.
 *
 *  Meridian:  am, pm, or 24-hour style.
 *  Millenium: ad, bc
 */
88

89 90 91 92 93 94 95 96 97 98 99 100
#define AM	0
#define PM	1
#define HR24	2

#define AD	0
#define BC	1

/*
 * Fields for time decoding.
 * Can't have more of these than there are bits in an unsigned int
 *  since these are turned into bit masks during parsing and decoding.
 */
101

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
#define RESERV	0
#define MONTH	1
#define YEAR	2
#define DAY	3
#define TIME	4
#define TZ	5
#define DTZ	6
#define IGNORE	7
#define AMPM	8
#define HOUR	9
#define MINUTE	10
#define SECOND	11
#define DOY	12
#define DOW	13
#define UNITS	14
#define ADBC	15
/* these are only for relative dates */
#define ABS_BEFORE	14
#define ABS_AFTER	15
#define AGO	16

/*
 * Token field definitions for time parsing and decoding.
 * These need to fit into the datetkn table type.
 * At the moment, that means keep them within [-127,127].
 */
128

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#define DTK_NUMBER	0
#define DTK_STRING	1

#define DTK_DATETIME	2
#define DTK_DATE	3
#define DTK_TIME	4
#define DTK_TZ		5

#define DTK_SPECIAL	6
#define DTK_INVALID	7
#define DTK_CURRENT	8
#define DTK_EARLY	9
#define DTK_LATE	10
#define DTK_EPOCH	11
#define DTK_NOW		12
#define DTK_YESTERDAY	13
#define DTK_TODAY	14
#define DTK_TOMORROW	15
#define DTK_ZULU	16

#define DTK_DELTA	32
#define DTK_SECOND	33
#define DTK_MINUTE	34
#define DTK_HOUR	35
#define DTK_DAY		36
#define DTK_WEEK	37
#define DTK_MONTH	38
156 157 158 159 160 161 162 163
#define DTK_QUARTER	39
#define DTK_YEAR	40
#define DTK_DECADE	41
#define DTK_CENTURY	42
#define DTK_MILLENIUM	43
#define DTK_MILLISEC	44
#define DTK_MICROSEC	45
#define DTK_AGO		46
164 165 166 167

/*
 * Bit mask definitions for time parsing.
 */
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#define DTK_M(t)	(0x01 << t)

#define DTK_DATE_M	(DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
#define DTK_TIME_M	(DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))

#define MAXDATELEN	47	/* maximum possible length of an input date string */
#define MAXDATEFIELDS	25	/* maximum possible number of fields in a date string */
#define TOKMAXLEN	10	/* only this many chars are stored in datetktbl */

/* keep this struct small; it gets used a lot */
typedef struct {
#if defined(aix)
    char *token;
#else
    char token[TOKMAXLEN];
#endif /* aix */
    char type;
    char value;		/* this may be unsigned, alas */
} datetkn;

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
#ifdef NAN
#define DT_INVALID	(NAN)
#else
#define DT_INVALID	(DBL_MIN+DBL_MIN)
#endif
#ifdef HUGE_VAL
#define DT_NOBEGIN	(-HUGE_VAL)
#define DT_NOEND	(HUGE_VAL)
#else
#define DT_NOBEGIN	(-DBL_MAX)
#define DT_NOEND	(DBL_MAX)
#endif
#define DT_CURRENT	(DBL_MIN)
#define DT_EPOCH	(-DBL_MIN)

#define DATETIME_INVALID(j)	{j = DT_INVALID;}
#ifdef NAN
#define DATETIME_IS_INVALID(j)	(isnan(j))
#else
#define DATETIME_IS_INVALID(j)	(j == DT_INVALID)
#endif

#define DATETIME_NOBEGIN(j)	{j = DT_NOBEGIN;}
#define DATETIME_IS_NOBEGIN(j)	(j == DT_NOBEGIN)

#define DATETIME_NOEND(j)	{j = DT_NOEND;}
#define DATETIME_IS_NOEND(j)	(j == DT_NOEND)

#define DATETIME_CURRENT(j)	{j = DT_CURRENT;}
#define DATETIME_IS_CURRENT(j)	(j == DT_CURRENT)

#define DATETIME_EPOCH(j)	{j = DT_EPOCH;}
#define DATETIME_IS_EPOCH(j)	(j == DT_EPOCH)

#define DATETIME_IS_RELATIVE(j)	(DATETIME_IS_CURRENT(j) || DATETIME_IS_EPOCH(j))
#define DATETIME_NOT_FINITE(j)	(DATETIME_IS_INVALID(j) \
				|| DATETIME_IS_NOBEGIN(j) || DATETIME_IS_NOEND(j))
#define DATETIME_IS_RESERVED(j) (DATETIME_IS_RELATIVE(j) || DATETIME_NOT_FINITE(j))

#define TIMESPAN_INVALID(j)	{j->time = DT_INVALID;}
#ifdef NAN
#define TIMESPAN_IS_INVALID(j)	(isnan((j).time))
#else
#define TIMESPAN_IS_INVALID(j)	((j).time == DT_INVALID)
#endif

#define TIME_PREC 1e-6
#define JROUND(j) (rint(((double) j)/TIME_PREC)*TIME_PREC)
237 238 239 240

/*
 * dt.c prototypes 
 */
241

242 243
extern DateTime *datetime_in( char *str);
extern char *datetime_out( DateTime *dt);
244 245 246 247 248 249 250
extern bool datetime_eq(DateTime *dt1, DateTime *dt2);
extern bool datetime_ne(DateTime *dt1, DateTime *dt2);
extern bool datetime_lt(DateTime *dt1, DateTime *dt2);
extern bool datetime_le(DateTime *dt1, DateTime *dt2);
extern bool datetime_ge(DateTime *dt1, DateTime *dt2);
extern bool datetime_gt(DateTime *dt1, DateTime *dt2);

251 252
extern TimeSpan *timespan_in(char *str);
extern char *timespan_out(TimeSpan *span);
253 254 255 256 257 258 259 260 261 262 263 264 265
extern bool timespan_eq(TimeSpan *span1, TimeSpan *span2);
extern bool timespan_ne(TimeSpan *span1, TimeSpan *span2);
extern bool timespan_lt(TimeSpan *span1, TimeSpan *span2);
extern bool timespan_le(TimeSpan *span1, TimeSpan *span2);
extern bool timespan_ge(TimeSpan *span1, TimeSpan *span2);
extern bool timespan_gt(TimeSpan *span1, TimeSpan *span2);

float64 datetime_part(text *units, DateTime *datetime);
float64 timespan_part(text *units, TimeSpan *timespan);

extern TimeSpan *timespan_um(TimeSpan *span);
extern TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2);
extern TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2);
266 267 268 269

extern TimeSpan *datetime_sub(DateTime *dt1, DateTime *dt2);
extern DateTime *datetime_add_span(DateTime *dt, TimeSpan *span);
extern DateTime *datetime_sub_span(DateTime *dt, TimeSpan *span);
270 271 272 273 274 275 276 277

extern void GetCurrentTime(struct tm *tm);
DateTime SetDateTime(DateTime datetime);
DateTime tm2datetime(struct tm *tm, double fsec, int tzp);
int datetime2tm( DateTime dt, struct tm *tm, double *fsec);

int timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec);
int tm2timespan(struct tm *tm, double fsec, TimeSpan *span);
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

extern DateTime dt2local( DateTime dt, int timezone);

extern void j2date( int jd, int *year, int *month, int *day);
extern int date2j( int year, int month, int day);
extern int j2day( int jd);

extern double time2t(const int hour, const int min, const double sec);
extern void dt2time(DateTime dt, int *hour, int *min, double *sec);

extern int ParseDateTime( char *timestr, char *lowstr,
  char *field[], int ftype[], int maxfields, int *numfields);
extern int DecodeDateTime( char *field[], int ftype[],
 int nf, int *dtype, struct tm *tm, double *fsec, int *tzp);
extern int DecodeDate(char *str, int fmask, int *tmask, struct tm *tm);
extern int DecodeNumber( int flen, char *field,
 int fmask, int *tmask, struct tm *tm, double *fsec);
extern int DecodeNumberField( int len, char *str,
 int fmask, int *tmask, struct tm *tm, double *fsec);
extern int DecodeTime(char *str,
 int fmask, int *tmask, struct tm *tm, double *fsec);
extern int DecodeTimeOnly( char *field[], int ftype[], int nf,
 int *dtype, struct tm *tm, double *fsec);
extern int DecodeTimezone( char *str, int *tzp);
extern int DecodeSpecial(int field, char *lowtoken, int *val);

extern int DecodeDateDelta( char *field[], int ftype[],
 int nf, int *dtype, struct tm *tm, double *fsec);
extern int DecodeUnits(int field, char *lowtoken, int *val);

308
extern int EncodeSpecialDateTime(DateTime dt, char *str);
309 310 311 312 313 314
extern int EncodePostgresDate(struct tm *tm, double fsec, char *str);
extern int EncodePostgresSpan(struct tm *tm, double fsec, char *str);

extern datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);

#endif /* DT_H */