1 /*-------------------------------------------------------------------------
4 * parse almost any absolute date getdate(3) can (& some it can't)
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.42 1998/02/26 04:37:12 momjian Exp $
12 *-------------------------------------------------------------------------
17 #include <sys/types.h>
20 #include <miscadmin.h>
27 #ifndef USE_POSIX_TIME
28 #include <sys/timeb.h>
30 #include "utils/builtins.h"
31 #include "access/xact.h"
33 static AbsoluteTime tm2abstime(struct tm * tm, int tz);
35 #define MIN_DAYNUM -24856 /* December 13, 1901 */
36 #define MAX_DAYNUM 24854 /* January 18, 2038 */
39 /* GetCurrentAbsoluteTime()
40 * Get the current system time. Set timezone parameters if not specified elsewhere.
41 * Define HasTZSet to allow clients to specify the default timezone.
43 * Returns the number of seconds since epoch (January 1 1970 GMT)
46 GetCurrentAbsoluteTime(void)
54 #else /* ! USE_POSIX_TIME */
55 struct timeb tb; /* the old V7-ism */
64 #if defined(HAVE_TZSET) && defined(HAVE_INT_TIMEZONE)
67 CDayLight = tm->tm_isdst;
68 CTimeZone = (tm->tm_isdst ? (timezone - 3600) : timezone);
69 strcpy(CTZName, tzname[tm->tm_isdst]);
70 #else /* !HAVE_TZSET */
73 CTimeZone = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
74 CDayLight = (tm->tm_isdst > 0);
77 * XXX is there a better way to get local timezone string w/o
78 * tzname? - tgl 97/03/18
80 strftime(CTZName, MAXTZLEN, "%Z", tm);
83 * XXX FreeBSD man pages indicate that this should work - tgl
86 strcpy(CTZName, tm->tm_zone);
88 #else /* ! USE_POSIX_TIME */
89 CTimeZone = tb.timezone * 60;
90 CDayLight = (tb.dstflag != 0);
93 * XXX does this work to get the local timezone string in V7? -
96 strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
101 printf("GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTC\n",
105 return ((AbsoluteTime) now);
106 } /* GetCurrentAbsoluteTime() */
110 GetCurrentTime(struct tm * tm)
114 abstime2tm(GetCurrentTransactionStartTime(), &tz, tm, NULL);
117 } /* GetCurrentTime() */
121 abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn)
123 #ifdef USE_POSIX_TIME
126 #else /* ! USE_POSIX_TIME */
127 struct timeb tb; /* the old V7-ism */
132 #ifdef USE_POSIX_TIME
135 tx = localtime((time_t *) &time);
139 tx = gmtime((time_t *) &time);
143 #if defined(DATEDEBUG)
144 #if defined(HAVE_INT_TIMEZONE)
145 printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s %s dst=%d\n",
146 tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
147 tzname[0], tzname[1], tx->tm_isdst);
149 printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s dst=%d\n",
150 tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
151 tx->tm_zone, tx->tm_isdst);
155 #ifdef USE_POSIX_TIME
157 tm->tm_year = tx->tm_year + 1900;
158 tm->tm_mon = tx->tm_mon + 1;
159 tm->tm_mday = tx->tm_mday;
160 tm->tm_hour = tx->tm_hour;
161 tm->tm_min = tx->tm_min;
162 tm->tm_sec = tx->tm_sec;
163 tm->tm_isdst = tx->tm_isdst;
165 #ifdef HAVE_INT_TIMEZONE
167 *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
169 strcpy(tzn, tzname[tm->tm_isdst]);
170 #else /* !HAVE_INT_TIMEZONE */
171 tm->tm_gmtoff = tx->tm_gmtoff;
172 tm->tm_zone = tx->tm_zone;
175 *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
176 /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
178 strcpy(tzn, tm->tm_zone);
180 #else /* ! USE_POSIX_TIME */
182 *tzp = tb.timezone * 60;
185 * XXX does this work to get the local timezone string in V7? - tgl
189 strftime(tzn, MAXTZLEN, "%Z", localtime(&now));
197 * Convert a tm structure to abstime.
198 * Note that tm has full year (not 1900-based) and 1-based month.
201 tm2abstime(struct tm * tm, int tz)
206 /* validate, before going out of range on some members */
207 if (tm->tm_year < 1901 || tm->tm_year > 2038
208 || tm->tm_mon < 1 || tm->tm_mon > 12
209 || tm->tm_mday < 1 || tm->tm_mday > 31
210 || tm->tm_hour < 0 || tm->tm_hour >= 24
211 || tm->tm_min < 0 || tm->tm_min > 59
212 || tm->tm_sec < 0 || tm->tm_sec > 59)
213 return (INVALID_ABSTIME);
215 day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(1970, 1, 1));
217 /* check for time out of range */
218 if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM))
219 return (INVALID_ABSTIME);
221 /* convert to seconds */
222 sec = tm->tm_sec + tz + (tm->tm_min + (day * 24 + tm->tm_hour) * 60) * 60;
224 /* check for overflow */
225 if ((day == MAX_DAYNUM && sec < 0) ||
226 (day == MIN_DAYNUM && sec > 0))
227 return (INVALID_ABSTIME);
229 /* check for reserved values (e.g. "current" on edge of usual range */
230 if (!AbsoluteTimeIsReal(sec))
231 return (INVALID_ABSTIME);
238 * Decode date/time string and return abstime.
241 nabstimein(char *str)
250 char *field[MAXDATEFIELDS];
251 char lowstr[MAXDATELEN + 1];
254 ftype[MAXDATEFIELDS];
256 if (!PointerIsValid(str))
257 elog(ERROR, "Bad (null) abstime external representation", NULL);
259 if (strlen(str) > MAXDATELEN)
260 elog(ERROR, "Bad (length) abstime external representation '%s'", str);
262 if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
263 || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
264 elog(ERROR, "Bad abstime external representation '%s'", str);
267 printf("nabstimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE);
273 result = tm2abstime(tm, tz);
277 result = EPOCH_ABSTIME;
281 result = CURRENT_ABSTIME;
285 result = NOEND_ABSTIME;
289 result = NOSTART_ABSTIME;
293 result = INVALID_ABSTIME;
297 elog(ERROR, "Bad abstime (internal coding error) '%s'", str);
298 result = INVALID_ABSTIME;
307 * Given an AbsoluteTime return the English text version of the date
310 nabstimeout(AbsoluteTime time)
317 char buf[MAXDATELEN + 1];
318 char zone[MAXDATELEN + 1],
326 case INVALID_ABSTIME:
327 strcpy(buf, INVALID);
329 case CURRENT_ABSTIME:
330 strcpy(buf, DCURRENT);
335 case NOSTART_ABSTIME:
339 abstime2tm(time, &tz, tm, tzn);
342 EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
346 result = palloc(strlen(buf) + 1);
350 } /* nabstimeout() */
354 * AbsoluteTimeIsBefore -- true iff time1 is before time2.
355 * AbsoluteTimeIsBefore -- true iff time1 is after time2.
358 AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2)
360 Assert(AbsoluteTimeIsValid(time1));
361 Assert(AbsoluteTimeIsValid(time2));
363 if (time1 == CURRENT_ABSTIME)
364 time1 = GetCurrentTransactionStartTime();
366 if (time2 == CURRENT_ABSTIME)
367 time2 = GetCurrentTransactionStartTime();
369 return (time1 < time2);
373 AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
375 Assert(AbsoluteTimeIsValid(time1));
376 Assert(AbsoluteTimeIsValid(time2));
378 if (time1 == CURRENT_ABSTIME)
379 time1 = GetCurrentTransactionStartTime();
381 if (time2 == CURRENT_ABSTIME)
382 time2 = GetCurrentTransactionStartTime();
384 return (time1 > time2);
391 abstime_finite(AbsoluteTime abstime)
393 return ((abstime != INVALID_ABSTIME)
394 && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME));
395 } /* abstime_finite() */
399 * abstimeeq - returns 1, iff arguments are equal
400 * abstimene - returns 1, iff arguments are not equal
401 * abstimelt - returns 1, iff t1 less than t2
402 * abstimegt - returns 1, iff t1 greater than t2
403 * abstimele - returns 1, iff t1 less than or equal to t2
404 * abstimege - returns 1, iff t1 greater than or equal to t2
407 abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
409 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
411 if (t1 == CURRENT_ABSTIME)
412 t1 = GetCurrentTransactionStartTime();
413 if (t2 == CURRENT_ABSTIME)
414 t2 = GetCurrentTransactionStartTime();
420 abstimene(AbsoluteTime t1, AbsoluteTime t2)
422 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
424 if (t1 == CURRENT_ABSTIME)
425 t1 = GetCurrentTransactionStartTime();
426 if (t2 == CURRENT_ABSTIME)
427 t2 = GetCurrentTransactionStartTime();
433 abstimelt(AbsoluteTime t1, AbsoluteTime t2)
435 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
437 if (t1 == CURRENT_ABSTIME)
438 t1 = GetCurrentTransactionStartTime();
439 if (t2 == CURRENT_ABSTIME)
440 t2 = GetCurrentTransactionStartTime();
446 abstimegt(AbsoluteTime t1, AbsoluteTime t2)
448 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
450 if (t1 == CURRENT_ABSTIME)
451 t1 = GetCurrentTransactionStartTime();
452 if (t2 == CURRENT_ABSTIME)
453 t2 = GetCurrentTransactionStartTime();
459 abstimele(AbsoluteTime t1, AbsoluteTime t2)
461 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
463 if (t1 == CURRENT_ABSTIME)
464 t1 = GetCurrentTransactionStartTime();
465 if (t2 == CURRENT_ABSTIME)
466 t2 = GetCurrentTransactionStartTime();
472 abstimege(AbsoluteTime t1, AbsoluteTime t2)
474 if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
476 if (t1 == CURRENT_ABSTIME)
477 t1 = GetCurrentTransactionStartTime();
478 if (t2 == CURRENT_ABSTIME)
479 t2 = GetCurrentTransactionStartTime();
485 /* datetime_abstime()
486 * Convert datetime to abstime.
489 datetime_abstime(DateTime *datetime)
497 if (!PointerIsValid(datetime))
499 result = INVALID_ABSTIME;
502 else if (DATETIME_IS_INVALID(*datetime))
504 result = INVALID_ABSTIME;
507 else if (DATETIME_IS_NOBEGIN(*datetime))
509 result = NOSTART_ABSTIME;
512 else if (DATETIME_IS_NOEND(*datetime))
514 result = NOEND_ABSTIME;
519 if (DATETIME_IS_RELATIVE(*datetime))
521 datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL);
522 result = tm2abstime(tm, 0);
525 else if (datetime2tm(*datetime, NULL, tm, &fsec, NULL) == 0)
527 result = tm2abstime(tm, 0);
532 result = INVALID_ABSTIME;
537 } /* datetime_abstime() */
539 /* abstime_datetime()
540 * Convert abstime to datetime.
543 abstime_datetime(AbsoluteTime abstime)
547 if (!PointerIsValid(result = palloc(sizeof(DateTime))))
548 elog(ERROR, "Unable to allocate space to convert abstime to datetime", NULL);
552 case INVALID_ABSTIME:
553 DATETIME_INVALID(*result);
556 case NOSTART_ABSTIME:
557 DATETIME_NOBEGIN(*result);
561 DATETIME_NOEND(*result);
565 DATETIME_EPOCH(*result);
568 case CURRENT_ABSTIME:
569 DATETIME_CURRENT(*result);
573 *result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400);
578 } /* abstime_datetime() */