date.c 27.9 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * date.c
4 5 6
 *	  Utilities for the built-in type "AbsoluteTime" (defined in nabstime).
 *	  Functions for the built-in type "RelativeTime".
 *	  Functions for the built-in type "TimeInterval".
7 8 9 10 11
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
12
 *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.33 1999/07/14 01:19:59 momjian Exp $
13 14
 *
 * NOTES
15 16
 *	 This code is actually (almost) unused.
 *	 It needs to be integrated with Time and struct trange.
17 18 19 20 21
 *
 * XXX	This code needs to be rewritten to work with the "new" definitions
 * XXX	in h/tim.h.  Look for int32's, int, long, etc. in the code.  The
 * XXX	definitions in h/tim.h may need to be rethought also.
 *
22
 * XXX	This code has been cleaned up some - avi 07/07/93
23 24 25 26 27 28 29 30 31 32 33 34
 *
 *-------------------------------------------------------------------------
 */
#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>

#include "postgres.h"
#include "miscadmin.h"
35
#ifdef HAVE_FLOAT_H
36
#include <float.h>
37
#endif
38
#ifdef HAVE_LIMITS_H
39
#include <limits.h>
40
#endif
41
#include "access/xact.h"
42
#include "utils/builtins.h"		/* where function declarations go */
43
#include "utils/palloc.h"
44
#include "utils/dt.h"
45
#include "utils/mcxt.h"
46

47 48 49 50 51
#define INVALID_RELTIME_STR		"Undefined RelTime"
#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1)
#define RELTIME_LABEL			'@'
#define RELTIME_PAST			"ago"
#define DIRMAXLEN				(sizeof(RELTIME_PAST)-1)
52 53

/*
54 55 56
 *	Unix epoch is Jan  1 00:00:00 1970.  Postgres knows about times
 *	sixty-eight years on either side of that.
 */
57

58
#define IsSpace(C)				((C) == ' ')
59

60 61
#define T_INTERVAL_INVAL   0	/* data represents no valid interval */
#define T_INTERVAL_VALID   1	/* data represents a valid interval */
62 63
/*
 * ['Mon May 10 23:59:12 1943 PST' 'Sun Jan 14 03:14:21 1973 PST']
64
 * 0		1		  2			3		  4			5		  6
65 66 67 68 69
 * 1234567890123456789012345678901234567890123456789012345678901234
 *
 * we allocate some extra -- timezones are usually 3 characters but
 * this is not in the POSIX standard...
 */
70 71 72
#define T_INTERVAL_LEN					80
#define INVALID_INTERVAL_STR			"Undefined Range"
#define INVALID_INTERVAL_STR_LEN		(sizeof(INVALID_INTERVAL_STR)-1)
73 74 75 76

#define ABSTIMEMIN(t1, t2) abstimele((t1),(t2)) ? (t1) : (t2)
#define ABSTIMEMAX(t1, t2) abstimelt((t1),(t2)) ? (t2) : (t1)

77
#ifdef NOT_USED
78
static char *unit_tab[] = {
79 80
	"second", "seconds", "minute", "minutes",
	"hour", "hours", "day", "days", "week", "weeks",
81 82 83 84
"month", "months", "year", "years"};

#define UNITMAXLEN 7			/* max length of a unit name */
#define NUNITS 14				/* number of different units */
85 86

/* table of seconds per unit (month = 30 days, year = 365 days)  */
87
static int	sec_tab[] = {
88 89 90 91
	1, 1, 60, 60,
	3600, 3600, 86400, 86400, 604800, 604800,
2592000, 2592000, 31536000, 31536000};

92
#endif
93 94 95 96

/*
 * Function prototypes -- internal to this file only
 */
97

98
static void reltime2tm(RelativeTime time, struct tm * tm);
99

100
#ifdef NOT_USED
101 102
static int	correct_unit(char *unit, int *unptr);
static int	correct_dir(char *direction, int *signptr);
103

104
#endif
105

106
static int istinterval(char *i_string,
Bruce Momjian's avatar
Bruce Momjian committed
107 108
			AbsoluteTime *i_start,
			AbsoluteTime *i_end);
109

110 111
/*****************************************************************************
 *	 USER I/O ROUTINES														 *
112 113 114
 *****************************************************************************/

/*
115
 *		reltimein		- converts a reltime string in an internal format
116
 */
117 118
RelativeTime
reltimein(char *str)
119
{
120
	RelativeTime result;
121

122 123 124 125 126 127 128 129
	struct tm	tt,
			   *tm = &tt;
	double		fsec;
	int			dtype;
	char	   *field[MAXDATEFIELDS];
	int			nf,
				ftype[MAXDATEFIELDS];
	char		lowstr[MAXDATELEN + 1];
130

131
	if (!PointerIsValid(str))
132
		elog(ERROR, "Bad (null) date external representation", NULL);
133

134
	if (strlen(str) > MAXDATELEN)
135
		elog(ERROR, "Bad (length) reltime external representation '%s'", str);
136

137 138
	if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
		|| (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
139
		elog(ERROR, "Bad reltime external representation '%s'", str);
140 141

#ifdef DATEDEBUG
142
	printf("reltimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE);
143 144
#endif

145 146
	switch (dtype)
	{
147 148 149
		case DTK_DELTA:
			result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec);
			result += (((tm->tm_year * 365) + (tm->tm_mon * 30) + tm->tm_mday) * (24 * 60 * 60));
150
			return result;
151

152
		default:
153
			return INVALID_RELTIME;
154
	}
155

156
	elog(ERROR, "Bad reltime (internal coding error) '%s'", str);
157
	return INVALID_RELTIME;
158
}	/* reltimein() */
159 160 161


/*
162
 *		reltimeout		- converts the internal format to a reltime string
163
 */
164
char *
165
reltimeout(RelativeTime time)
166
{
167 168 169 170
	char	   *result;
	struct tm	tt,
			   *tm = &tt;
	char		buf[MAXDATELEN + 1];
171

172 173 174
	if (time == INVALID_RELTIME)
	{
		strcpy(buf, INVALID_RELTIME_STR);
175

176 177 178 179 180 181
	}
	else
	{
		reltime2tm(time, tm);
		EncodeTimeSpan(tm, 0, DateStyle, buf);
	}
182

183
	result = palloc(strlen(buf) + 1);
184
	strcpy(result, buf);
185

186
	return result;
187
}	/* reltimeout() */
188 189


190 191 192 193 194
#define TMODULO(t,q,u) \
do { \
	q = (t / u); \
	if (q != 0) t -= (q * u); \
} while(0)
195

196
static void
197
reltime2tm(RelativeTime time, struct tm * tm)
198
{
199 200 201 202 203 204
	TMODULO(time, tm->tm_year, 31536000);
	TMODULO(time, tm->tm_mon, 2592000);
	TMODULO(time, tm->tm_mday, 86400);
	TMODULO(time, tm->tm_hour, 3600);
	TMODULO(time, tm->tm_min, 60);
	TMODULO(time, tm->tm_sec, 1);
205

206
	return;
207
}	/* reltime2tm() */
208

209
#ifdef NOT_USED
210 211
int
dummyfunc()
212
{
213 214 215 216 217 218 219 220 221 222 223 224
	char	   *timestring;
	long		quantity;
	int			i;
	int			unitnr;

	timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR),
									 UNITMAXLEN) + 1);
	if (timevalue == INVALID_RELTIME)
	{
		strcpy(timestring, INVALID_RELTIME_STR);
		return timestring;
	}
225

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
	if (timevalue == 0)
		i = 1;					/* unit = 'seconds' */
	else
		for (i = 12; i >= 0; i = i - 2)
			if ((timevalue % sec_tab[i]) == 0)
				break;			/* appropriate unit found */
	unitnr = i;
	quantity = (timevalue / sec_tab[unitnr]);
	if (quantity > 1 || quantity < -1)
		unitnr++;				/* adjust index for PLURAL of unit */
	if (quantity >= 0)
		sprintf(timestring, "%c %lu %s", RELTIME_LABEL,
				quantity, unit_tab[unitnr]);
	else
		sprintf(timestring, "%c %lu %s %s", RELTIME_LABEL,
				(quantity * -1), unit_tab[unitnr], RELTIME_PAST);
	return timestring;
243
}
244

245
#endif
246 247 248


/*
249
 *		tintervalin		- converts an interval string to an internal format
250
 */
251 252 253
TimeInterval
tintervalin(char *intervalstr)
{
254 255 256 257 258 259
	int			error;
	AbsoluteTime i_start,
				i_end,
				t1,
				t2;
	TimeInterval interval;
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

	interval = (TimeInterval) palloc(sizeof(TimeIntervalData));
	error = istinterval(intervalstr, &t1, &t2);
	if (error == 0)
		interval->status = T_INTERVAL_INVAL;
	if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
		interval->status = T_INTERVAL_INVAL;	/* undefined  */
	else
	{
		i_start = ABSTIMEMIN(t1, t2);
		i_end = ABSTIMEMAX(t1, t2);
		interval->data[0] = i_start;
		interval->data[1] = i_end;
		interval->status = T_INTERVAL_VALID;
	}
275
	return interval;
276 277 278 279
}


/*
280
 *		tintervalout	- converts an internal interval format to a string
281 282
 *
 */
283
char *
284 285
tintervalout(TimeInterval interval)
{
286 287
	char	   *i_str,
			   *p;
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303

	i_str = (char *) palloc(T_INTERVAL_LEN);	/* ['...' '...'] */
	strcpy(i_str, "[\"");
	if (interval->status == T_INTERVAL_INVAL)
		strcat(i_str, INVALID_INTERVAL_STR);
	else
	{
		p = nabstimeout(interval->data[0]);
		strcat(i_str, p);
		pfree(p);
		strcat(i_str, "\" \"");
		p = nabstimeout(interval->data[1]);
		strcat(i_str, p);
		pfree(p);
	}
	strcat(i_str, "\"]\0");
304
	return i_str;
305 306 307 308 309
}


/*****************************************************************************
 *	 PUBLIC ROUTINES														 *
310 311
 *****************************************************************************/

312
RelativeTime
313
timespan_reltime(TimeSpan *timespan)
314
{
315 316 317 318
	RelativeTime time;
	int			year,
				month;
	double		span;
319

320 321
	if (!PointerIsValid(timespan))
		time = INVALID_RELTIME;
322

323 324 325
	if (TIMESPAN_IS_INVALID(*timespan))
	{
		time = INVALID_RELTIME;
326

327 328 329 330 331 332 333
	}
	else
	{
		if (timespan->month == 0)
		{
			year = 0;
			month = 0;
334

335 336 337 338 339
		}
		else if (abs(timespan->month) >= 12)
		{
			year = (timespan->month / 12);
			month = (timespan->month % 12);
340

341 342 343 344 345 346
		}
		else
		{
			year = 0;
			month = timespan->month;
		}
347

348
		span = (((((double) 365 * year) + ((double) 30 * month)) * 86400) + timespan->time);
349 350

#ifdef DATEDEBUG
351 352
		printf("timespan_reltime- convert m%d s%f to %f [%d %d]\n",
			   timespan->month, timespan->time, span, INT_MIN, INT_MAX);
353 354
#endif

355 356
		time = (((span > INT_MIN) && (span < INT_MAX)) ? span : INVALID_RELTIME);
	}
357

358
	return time;
359
}	/* timespan_reltime() */
360 361


362
TimeSpan   *
363 364
reltime_timespan(RelativeTime reltime)
{
365 366 367
	TimeSpan   *result;
	int			year,
				month;
368

369
	if (!PointerIsValid(result = palloc(sizeof(TimeSpan))))
370
		elog(ERROR, "Memory allocation failed, can't convert reltime to timespan", NULL);
371

372 373
	switch (reltime)
	{
374 375 376
		case INVALID_RELTIME:
			TIMESPAN_INVALID(*result);
			break;
377

378 379 380
		default:
			TMODULO(reltime, year, 31536000);
			TMODULO(reltime, month, 2592000);
381

382 383
			result->time = reltime;
			result->month = ((12 * year) + month);
384
	}
385

386
	return result;
387
}	/* reltime_timespan() */
388 389


390
/*
391
 *		mktinterval		- creates a time interval with endpoints t1 and t2
392
 */
393 394
TimeInterval
mktinterval(AbsoluteTime t1, AbsoluteTime t2)
395
{
396 397 398
	AbsoluteTime tstart = ABSTIMEMIN(t1, t2),
				tend = ABSTIMEMAX(t1, t2);
	TimeInterval interval;
399 400 401 402 403 404 405 406 407 408 409 410

	interval = (TimeInterval) palloc(sizeof(TimeIntervalData));
	if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
		interval->status = T_INTERVAL_INVAL;
	else
	{
		interval->status = T_INTERVAL_VALID;
		interval->data[0] = tstart;
		interval->data[1] = tend;
	}

	return interval;
411 412 413
}

/*
414 415 416 417
 *		timepl, timemi and abstimemi use the formula
 *				abstime + reltime = abstime
 *		so		abstime - reltime = abstime
 *		and		abstime - abstime = reltime
418 419 420
 */

/*
421
 *		timepl			- returns the value of (abstime t1 + relime t2)
422
 */
423 424
AbsoluteTime
timepl(AbsoluteTime t1, RelativeTime t2)
425
{
426 427 428 429 430 431 432
	if (t1 == CURRENT_ABSTIME)
		t1 = GetCurrentTransactionStartTime();

	if (AbsoluteTimeIsReal(t1) &&
		RelativeTimeIsValid(t2) &&
		((t2 > 0) ? (t1 < NOEND_ABSTIME - t2)
		 : (t1 > NOSTART_ABSTIME - t2)))		/* prevent overflow */
433
		return t1 + t2;
434

435
	return INVALID_ABSTIME;
436 437 438 439
}


/*
440
 *		timemi			- returns the value of (abstime t1 - reltime t2)
441
 */
442 443
AbsoluteTime
timemi(AbsoluteTime t1, RelativeTime t2)
444
{
445 446 447 448 449 450 451
	if (t1 == CURRENT_ABSTIME)
		t1 = GetCurrentTransactionStartTime();

	if (AbsoluteTimeIsReal(t1) &&
		RelativeTimeIsValid(t2) &&
		((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2)
		 : (t1 < NOEND_ABSTIME + t2)))	/* prevent overflow */
452
		return t1 - t2;
453

454
	return INVALID_ABSTIME;
455 456 457 458
}


/*
459
 *		abstimemi		- returns the value of (abstime t1 - abstime t2)
460
 */
461 462
static RelativeTime
abstimemi(AbsoluteTime t1, AbsoluteTime t2)
463
{
464 465 466 467 468 469 470
	if (t1 == CURRENT_ABSTIME)
		t1 = GetCurrentTransactionStartTime();
	if (t2 == CURRENT_ABSTIME)
		t2 = GetCurrentTransactionStartTime();

	if (AbsoluteTimeIsReal(t1) &&
		AbsoluteTimeIsReal(t2))
471
		return t1 - t2;
472

473
	return INVALID_RELTIME;
474 475 476 477
}


/*
478
 *		ininterval		- returns 1, iff absolute date is in the interval
479
 */
480 481
int
ininterval(AbsoluteTime t, TimeInterval interval)
482
{
483 484 485
	if (interval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME)
		return (abstimege(t, interval->data[0]) &&
				abstimele(t, interval->data[1]));
486
	return 0;
487 488 489
}

/*
490
 *		intervalrel		- returns  relative time corresponding to interval
491
 */
492 493
RelativeTime
intervalrel(TimeInterval interval)
494
{
495
	if (interval->status == T_INTERVAL_VALID)
496
		return abstimemi(interval->data[1], interval->data[0]);
497
	else
498
		return INVALID_RELTIME;
499 500 501
}

/*
502
 *		timenow			- returns  time "now", internal format
503
 *
504
 *		Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992
505
 */
506 507
AbsoluteTime
timenow()
508
{
509
	time_t		sec;
510 511

	if (time(&sec) < 0)
512 513
		return INVALID_ABSTIME;
	return (AbsoluteTime) sec;
514 515 516
}

/*
517 518 519 520 521 522
 *		reltimeeq		- returns 1, iff arguments are equal
 *		reltimene		- returns 1, iff arguments are not equal
 *		reltimelt		- returns 1, iff t1 less than t2
 *		reltimegt		- returns 1, iff t1 greater than t2
 *		reltimele		- returns 1, iff t1 less than or equal to t2
 *		reltimege		- returns 1, iff t1 greater than or equal to t2
523
 */
524 525
bool
reltimeeq(RelativeTime t1, RelativeTime t2)
526
{
527 528
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
529
	return t1 == t2;
530 531
}

532 533
bool
reltimene(RelativeTime t1, RelativeTime t2)
534
{
535 536
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
537
	return t1 != t2;
538 539
}

540 541
bool
reltimelt(RelativeTime t1, RelativeTime t2)
542
{
543 544
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
545
	return t1 < t2;
546 547
}

548 549
bool
reltimegt(RelativeTime t1, RelativeTime t2)
550
{
551 552
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
553
	return t1 > t2;
554 555
}

556 557
bool
reltimele(RelativeTime t1, RelativeTime t2)
558
{
559 560
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
561
	return t1 <= t2;
562 563
}

564 565
bool
reltimege(RelativeTime t1, RelativeTime t2)
566
{
567 568
	if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
		return 0;
569
	return t1 >= t2;
570 571 572 573
}


/*
574 575
 *		intervalsame	- returns 1, iff interval i1 is same as interval i2
 *		Check begin and end time.
576
 */
577
bool
578
intervalsame(TimeInterval i1, TimeInterval i2)
579
{
580
	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
581
		return FALSE;			/* invalid interval */
582 583
	return (abstimeeq(i1->data[0], i2->data[0]) &&
			abstimeeq(i1->data[1], i2->data[1]));
584
}	/* intervalsame() */
585 586 587 588 589 590 591 592 593


/*
 *		intervaleq		- returns 1, iff interval i1 is equal to interval i2
 *		Check length of intervals.
 */
bool
intervaleq(TimeInterval i1, TimeInterval i2)
{
594 595 596 597
	AbsoluteTime t10,
				t11,
				t20,
				t21;
598 599

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
600
		return FALSE;			/* invalid interval */
601 602 603 604 605 606 607

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
608
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
609
		return FALSE;
610 611 612 613 614 615 616 617 618 619

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

620
	return (t11 - t10) == (t21 - t20);
621
}	/* intervaleq() */
622 623 624 625 626 627 628 629

/*
 *		intervalne		- returns 1, iff interval i1 is not equal to interval i2
 *		Check length of intervals.
 */
bool
intervalne(TimeInterval i1, TimeInterval i2)
{
630 631 632 633
	AbsoluteTime t10,
				t11,
				t20,
				t21;
634 635

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
636
		return FALSE;			/* invalid interval */
637 638 639 640 641 642 643

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
644
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
645
		return FALSE;
646 647 648 649 650 651 652 653 654 655

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

656
	return (t11 - t10) != (t21 - t20);
657
}	/* intervalne() */
658 659 660 661 662 663 664 665

/*
 *		intervallt		- returns TRUE, iff interval i1 is less than interval i2
 *		Check length of intervals.
 */
bool
intervallt(TimeInterval i1, TimeInterval i2)
{
666 667 668 669
	AbsoluteTime t10,
				t11,
				t20,
				t21;
670 671

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
672
		return FALSE;			/* invalid interval */
673 674 675 676 677 678 679

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
680
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
681
		return FALSE;
682 683 684 685 686 687 688 689 690 691

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

692
	return (t11 - t10) < (t21 - t20);
693
}	/* intervallt() */
694 695 696 697 698 699 700 701

/*
 *		intervalle		- returns TRUE, iff interval i1 is less than or equal to interval i2
 *		Check length of intervals.
 */
bool
intervalle(TimeInterval i1, TimeInterval i2)
{
702 703 704 705
	AbsoluteTime t10,
				t11,
				t20,
				t21;
706 707

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
708
		return FALSE;			/* invalid interval */
709 710 711 712 713 714 715

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
716
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
717
		return FALSE;
718 719 720 721 722 723 724 725 726 727

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

728
	return (t11 - t10) <= (t21 - t20);
729
}	/* intervalle() */
730 731 732 733 734 735 736 737

/*
 *		intervalgt		- returns TRUE, iff interval i1 is less than interval i2
 *		Check length of intervals.
 */
bool
intervalgt(TimeInterval i1, TimeInterval i2)
{
738 739 740 741
	AbsoluteTime t10,
				t11,
				t20,
				t21;
742 743

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
744
		return FALSE;			/* invalid interval */
745 746 747 748 749 750 751

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
752
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
753
		return FALSE;
754 755 756 757 758 759 760 761 762 763

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

764
	return (t11 - t10) > (t21 - t20);
765
}	/* intervalgt() */
766 767 768 769 770 771 772 773

/*
 *		intervalge		- returns TRUE, iff interval i1 is less than or equal to interval i2
 *		Check length of intervals.
 */
bool
intervalge(TimeInterval i1, TimeInterval i2)
{
774 775 776 777
	AbsoluteTime t10,
				t11,
				t20,
				t21;
778 779

	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
780
		return FALSE;			/* invalid interval */
781 782 783 784 785 786 787

	t10 = i1->data[0];
	t11 = i1->data[1];
	t20 = i2->data[0];
	t21 = i2->data[1];

	if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
788
		|| (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
789
		return FALSE;
790 791 792 793 794 795 796 797 798 799

	if (t10 == CURRENT_ABSTIME)
		t10 = GetCurrentTransactionStartTime();
	if (t11 == CURRENT_ABSTIME)
		t11 = GetCurrentTransactionStartTime();
	if (t20 == CURRENT_ABSTIME)
		t20 = GetCurrentTransactionStartTime();
	if (t21 == CURRENT_ABSTIME)
		t21 = GetCurrentTransactionStartTime();

800
	return (t11 - t10) >= (t21 - t20);
801
}	/* intervalge() */
802

803 804

/*
805 806
 *		intervalleneq	- returns 1, iff length of interval i is equal to
 *								reltime t
807
 */
808 809
bool
intervalleneq(TimeInterval i, RelativeTime t)
810
{
811
	RelativeTime rt;
812 813

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
814
		return 0;
815
	rt = intervalrel(i);
816
	return rt != INVALID_RELTIME && rt == t;
817 818 819
}

/*
820 821
 *		intervallenne	- returns 1, iff length of interval i is not equal
 *								to reltime t
822
 */
823 824
bool
intervallenne(TimeInterval i, RelativeTime t)
825
{
826
	RelativeTime rt;
827 828

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
829
		return 0;
830
	rt = intervalrel(i);
831
	return rt != INVALID_RELTIME && rt != t;
832 833 834
}

/*
835 836
 *		intervallenlt	- returns 1, iff length of interval i is less than
 *								reltime t
837
 */
838 839
bool
intervallenlt(TimeInterval i, RelativeTime t)
840
{
841
	RelativeTime rt;
842 843

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
844
		return 0;
845
	rt = intervalrel(i);
846
	return rt != INVALID_RELTIME && rt < t;
847 848 849
}

/*
850 851
 *		intervallengt	- returns 1, iff length of interval i is greater than
 *								reltime t
852
 */
853 854
bool
intervallengt(TimeInterval i, RelativeTime t)
855
{
856
	RelativeTime rt;
857 858

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
859
		return 0;
860
	rt = intervalrel(i);
861
	return rt != INVALID_RELTIME && rt > t;
862 863 864
}

/*
865 866
 *		intervallenle	- returns 1, iff length of interval i is less or equal
 *									than reltime t
867
 */
868 869 870
bool
intervallenle(TimeInterval i, RelativeTime t)
{
871
	RelativeTime rt;
872 873

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
874
		return 0;
875
	rt = intervalrel(i);
876
	return rt != INVALID_RELTIME && rt <= t;
877 878 879
}

/*
880 881
 *		intervallenge	- returns 1, iff length of interval i is greater or
 *								equal than reltime t
882
 */
883 884
bool
intervallenge(TimeInterval i, RelativeTime t)
885
{
886
	RelativeTime rt;
887 888

	if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
889
		return 0;
890
	rt = intervalrel(i);
891
	return rt != INVALID_RELTIME && rt >= t;
892 893 894
}

/*
895
 *		intervalct		- returns 1, iff interval i1 contains interval i2
896
 */
897 898
bool
intervalct(TimeInterval i1, TimeInterval i2)
899
{
900
	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
901
		return 0;
902 903
	return (abstimele(i1->data[0], i2->data[0]) &&
			abstimege(i1->data[1], i2->data[1]));
904 905 906
}

/*
907
 *		intervalov		- returns 1, iff interval i1 (partially) overlaps i2
908
 */
909 910
bool
intervalov(TimeInterval i1, TimeInterval i2)
911
{
912
	if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
913
		return 0;
914 915
	return (!(abstimelt(i1->data[1], i2->data[0]) ||
			  abstimegt(i1->data[0], i2->data[1])));
916 917 918
}

/*
919
 *		intervalstart	- returns  the start of interval i
920
 */
921 922
AbsoluteTime
intervalstart(TimeInterval i)
923
{
924 925
	if (i->status == T_INTERVAL_INVAL)
		return INVALID_ABSTIME;
926
	return i->data[0];
927 928 929
}

/*
930
 *		intervalend		- returns  the end of interval i
931
 */
932 933
AbsoluteTime
intervalend(TimeInterval i)
934
{
935 936
	if (i->status == T_INTERVAL_INVAL)
		return INVALID_ABSTIME;
937
	return i->data[1];
938 939 940
}


941 942
/*****************************************************************************
 *	 PRIVATE ROUTINES														 *
943 944
 *****************************************************************************/

945
#ifdef NOT_USED
946
/*
947 948 949 950
 *		isreltime		- returns 1, iff datestring is of type reltime
 *								  2, iff datestring is 'invalid time' identifier
 *								  0, iff datestring contains a syntax error
 *		VALID time	less or equal +/-  `@ 68 years'
951 952
 *
 */
953 954
int
isreltime(char *str)
955
{
956 957 958 959 960 961 962 963
	struct tm	tt,
			   *tm = &tt;
	double		fsec;
	int			dtype;
	char	   *field[MAXDATEFIELDS];
	int			nf,
				ftype[MAXDATEFIELDS];
	char		lowstr[MAXDATELEN + 1];
964 965 966 967 968 969 970 971 972 973 974 975 976

	if (!PointerIsValid(str))
		return 0;

	if (strlen(str) > MAXDATELEN)
		return 0;

	if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
		|| (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
		return 0;

	switch (dtype)
	{
977
		case (DTK_DELTA):
978
			return (abs(tm->tm_year) <= 68) ? 1 : 0;
979
			break;
980

981 982 983
		case (DTK_INVALID):
			return 2;
			break;
984

985 986 987
		default:
			return 0;
			break;
988
	}
989 990

	return 0;
991
}	/* isreltime() */
Bruce Momjian's avatar
Bruce Momjian committed
992

993
#endif
994

995
#ifdef NOT_USED
996 997
int
dummyfunc()
998
{
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
	char	   *p;
	char		c;
	int			i;
	char		unit[UNITMAXLEN];
	char		direction[DIRMAXLEN];
	int			localSign;
	int			localUnitNumber;
	long		localQuantity;

	if (!PointerIsValid(sign))
		sign = &localSign;

	if (!PointerIsValid(unitnr))
		unitnr = &localUnitNumber;

	if (!PointerIsValid(quantity))
		quantity = &localQuantity;

	unit[0] = '\0';
	direction[0] = '\0';
	p = timestring;
	/* skip leading blanks */
	while ((c = *p) != '\0')
	{
		if (c != ' ')
			break;
		p++;
	}
1027

1028 1029 1030
	/* Test whether 'invalid time' identifier or not */
	if (!strncmp(INVALID_RELTIME_STR, p, strlen(INVALID_RELTIME_STR) + 1))
		return 2;				/* correct 'invalid time' identifier found */
1031

1032 1033 1034 1035
	/* handle label of relative time */
	if (c != RELTIME_LABEL)
		return 0;				/* syntax error */
	c = *++p;
1036
	if (c != ' ')
1037
		return 0;				/* syntax error */
1038
	p++;
1039 1040 1041
	/* handle the quantity */
	*quantity = 0;
	for (;;)
1042
	{
1043 1044 1045 1046 1047 1048
		c = *p;
		if (isdigit(c))
		{
			*quantity = *quantity * 10 + (c - '0');
			p++;
		}
1049
		else
1050 1051 1052 1053 1054 1055
		{
			if (c == ' ')
				break;			/* correct quantity found */
			else
				return 0;		/* syntax error */
		}
1056
	}
1057

1058 1059 1060 1061
	/* handle unit */
	p++;
	i = 0;
	for (;;)
1062
	{
1063 1064 1065 1066 1067 1068 1069
		c = *p;
		if (c >= 'a' && c <= 'z' && i <= (UNITMAXLEN - 1))
		{
			unit[i] = c;
			p++;
			i++;
		}
1070
		else
1071 1072 1073 1074 1075 1076 1077
		{
			if ((c == ' ' || c == '\0')
				&& correct_unit(unit, unitnr))
				break;			/* correct unit found */
			else
				return 0;		/* syntax error */
		}
1078
	}
1079

1080 1081
	/* handle optional direction */
	if (c == ' ')
1082
		p++;
1083 1084 1085
	i = 0;
	*sign = 1;
	for (;;)
1086
	{
1087 1088
		c = *p;
		if (c >= 'a' && c <= 'z' && i <= (DIRMAXLEN - 1))
1089
		{
1090 1091 1092
			direction[i] = c;
			p++;
			i++;
1093
		}
1094
		else
1095
		{
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
			if ((c == ' ' || c == '\0') && i == 0)
			{
				*sign = 1;
				break;			/* no direction specified */
			}
			if ((c == ' ' || c == '\0') && i != 0)
			{
				direction[i] = '\0';
				correct_dir(direction, sign);
				break;			/* correct direction found */
			}
			else
				return 0;		/* syntax error */
1109
		}
1110
	}
1111

1112
	return 1;
1113 1114 1115
}

/*
1116
 *		correct_unit	- returns 1, iff unit is a correct unit description
1117
 *
1118 1119 1120 1121 1122
 *		output parameter:
 *				unptr: points to an integer which is the appropriate unit number
 *					   (see function isreltime())
 */
static int
1123
correct_unit(char *unit, int *unptr)
1124
{
1125
	int			j = 0;
1126 1127 1128 1129 1130 1131

	while (j < NUNITS)
	{
		if (strncmp(unit, unit_tab[j], strlen(unit_tab[j])) == 0)
		{
			*unptr = j;
1132
			return 1;
1133 1134
		}
		j++;
1135
	}
1136
	return 0;					/* invalid unit descriptor */
1137 1138 1139
}

/*
1140
 *		correct_dir		- returns 1, iff direction is a correct identifier
1141
 *
1142 1143 1144 1145 1146
 *		output parameter:
 *				signptr: points to -1 if dir corresponds to past tense
 *						 else  to 1
 */
static int
1147
correct_dir(char *direction, int *signptr)
1148 1149 1150
{
	*signptr = 1;
	if (strncmp(RELTIME_PAST, direction, strlen(RELTIME_PAST) + 1) == 0)
1151
	{
1152
		*signptr = -1;
1153
		return 1;
1154 1155
	}
	else
1156
		return 0;				/* invalid direction descriptor */
1157
}
1158

1159
#endif
1160 1161

/*
1162 1163 1164
 *		istinterval		- returns 1, iff i_string is a valid interval descr.
 *								  0, iff i_string is NOT a valid interval desc.
 *								  2, iff any time is INVALID_ABSTIME
1165
 *
1166 1167
 *		output parameter:
 *				i_start, i_end: interval margins
1168
 *
1169 1170
 *		Time interval:
 *		`[' {` '} `'' <AbsTime> `'' {` '} `'' <AbsTime> `'' {` '} `]'
1171
 *
1172
 *		OR	`Undefined Range'	(see also INVALID_INTERVAL_STR)
1173
 *
1174
 *		where <AbsTime> satisfies the syntax of absolute time.
1175
 *
1176 1177 1178 1179
 *		e.g.  [  '  Jan 18 1902'   'Jan 1 00:00:00 1970']
 */
static int
istinterval(char *i_string,
Bruce Momjian's avatar
Bruce Momjian committed
1180 1181
			AbsoluteTime *i_start,
			AbsoluteTime *i_end)
1182
{
1183
	char	   *p,
1184
			   *p1;
1185
	char		c;
1186 1187 1188 1189 1190 1191 1192 1193

	p = i_string;
	/* skip leading blanks up to '[' */
	while ((c = *p) != '\0')
	{
		if (IsSpace(c))
			p++;
		else if (c != '[')
1194
			return 0;			/* syntax error */
1195 1196
		else
			break;
1197
	}
1198 1199 1200 1201 1202 1203 1204
	p++;
	/* skip leading blanks up to "'" */
	while ((c = *p) != '\0')
	{
		if (IsSpace(c))
			p++;
		else if (c != '"')
1205
			return 0;			/* syntax error */
1206 1207
		else
			break;
1208
	}
1209 1210
	p++;
	if (strncmp(INVALID_INTERVAL_STR, p, strlen(INVALID_INTERVAL_STR)) == 0)
1211
		return 0;				/* undefined range, handled like a syntax
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
								 * err. */
	/* search for the end of the first date and change it to a NULL */
	p1 = p;
	while ((c = *p1) != '\0')
	{
		if (c == '"')
		{
			*p1 = '\0';
			break;
		}
		p1++;
	}
	/* get the first date */
	*i_start = nabstimein(p);	/* first absolute date */
	/* rechange NULL at the end of the first date to a "'" */
	*p1 = '"';
	p = ++p1;
	/* skip blanks up to "'", beginning of second date */
	while ((c = *p) != '\0')
	{
		if (IsSpace(c))
			p++;
		else if (c != '"')
1235
			return 0;			/* syntax error */
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
		else
			break;
	}
	p++;
	/* search for the end of the second date and change it to a NULL */
	p1 = p;
	while ((c = *p1) != '\0')
	{
		if (c == '"')
		{
			*p1 = '\0';
			break;
		}
		p1++;
	}
	/* get the second date */
	*i_end = nabstimein(p);		/* second absolute date */
	/* rechange NULL at the end of the first date to a ''' */
	*p1 = '"';
	p = ++p1;
	/* skip blanks up to ']' */
	while ((c = *p) != '\0')
	{
		if (IsSpace(c))
			p++;
		else if (c != ']')
1262
			return 0;			/* syntax error */
1263 1264 1265 1266 1267 1268
		else
			break;
	}
	p++;
	c = *p;
	if (c != '\0')
1269
		return 0;				/* syntax error */
1270
	/* it seems to be a valid interval */
1271
	return 1;
1272 1273 1274 1275 1276 1277 1278 1279 1280
}


/*****************************************************************************
 *
 *****************************************************************************/

/*
 * timeofday -
1281 1282 1283 1284
 *	   returns the current time as a text. similar to timenow() but returns
 *	   seconds with more precision (up to microsecs). (I need this to compare
 *	   the Wisconsin benchmark with Illustra whose TimeNow() shows current
 *	   time with precision up to microsecs.)			  - ay 3/95
1285
 */
1286
text *
1287
timeofday(void)
1288 1289
{

1290
	struct timeval tp;
1291
	struct timezone tpz;
1292 1293 1294 1295
	char		templ[500];
	char		buf[500];
	text	   *tm;
	int			len = 0;
1296 1297 1298

	gettimeofday(&tp, &tpz);
	strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%d %Y %Z",
1299
			 localtime((time_t *) &tp.tv_sec));
1300 1301 1302 1303 1304 1305 1306
	sprintf(buf, templ, tp.tv_usec);

	len = VARHDRSZ + strlen(buf);
	tm = (text *) palloc(len);
	VARSIZE(tm) = len;
	strncpy(VARDATA(tm), buf, strlen(buf));
	return tm;
1307
}