nabstime.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:12k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*
  2.  * nabstime.c
  3.  *   parse almost any absolute date getdate(3) can (& some it can't)
  4.  *
  5.  * Copyright (c) 1994, Regents of the University of California
  6.  *
  7.  *   $Id: nabstime.c,v 1.55.2.1 1999/08/02 05:24:54 scrappy Exp $
  8.  *
  9.  */
  10. #include <ctype.h>
  11. #include <sys/types.h>
  12. #include "postgres.h"
  13. #ifdef HAVE_FLOAT_H
  14. #include <float.h>
  15. #endif
  16. #ifdef HAVE_LIMITS_H
  17. #include <limits.h>
  18. #endif
  19. #ifndef USE_POSIX_TIME
  20. #include <sys/timeb.h>
  21. #endif
  22. #include "access/xact.h"
  23. #include "miscadmin.h"
  24. #include "utils/builtins.h"
  25. static AbsoluteTime tm2abstime(struct tm * tm, int tz);
  26. #define MIN_DAYNUM -24856 /* December 13, 1901 */
  27. #define MAX_DAYNUM 24854 /* January 18, 2038 */
  28. /* GetCurrentAbsoluteTime()
  29.  * Get the current system time. Set timezone parameters if not specified elsewhere.
  30.  * Define HasTZSet to allow clients to specify the default timezone.
  31.  *
  32.  * Returns the number of seconds since epoch (January 1 1970 GMT)
  33.  */
  34. AbsoluteTime
  35. GetCurrentAbsoluteTime(void)
  36. {
  37. time_t now;
  38. #ifdef USE_POSIX_TIME
  39. struct tm  *tm;
  40. now = time(NULL);
  41. #else /* ! USE_POSIX_TIME */
  42. struct timeb tb; /* the old V7-ism */
  43. ftime(&tb);
  44. now = tb.time;
  45. #endif
  46. if (!HasCTZSet)
  47. {
  48. #ifdef USE_POSIX_TIME
  49. #if defined(HAVE_TM_ZONE)
  50. tm = localtime(&now);
  51. CTimeZone = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
  52. CDayLight = (tm->tm_isdst > 0);
  53. #ifdef NOT_USED
  54. /*
  55.  * XXX is there a better way to get local timezone string w/o
  56.  * tzname? - tgl 97/03/18
  57.  */
  58. strftime(CTZName, MAXTZLEN, "%Z", tm);
  59. #endif
  60. /*
  61.  * XXX FreeBSD man pages indicate that this should work - thomas
  62.  * 1998-12-12
  63.  */
  64. strcpy(CTZName, tm->tm_zone);
  65. #elif defined(HAVE_INT_TIMEZONE)
  66. tm = localtime(&now);
  67. CDayLight = tm->tm_isdst;
  68. CTimeZone =
  69. #ifdef __CYGWIN32__
  70. (tm->tm_isdst ? (_timezone - 3600) : _timezone);
  71. #else
  72. (tm->tm_isdst ? (timezone - 3600) : timezone);
  73. #endif
  74. strcpy(CTZName, tzname[tm->tm_isdst]);
  75. #else
  76. #error USE_POSIX_TIME defined but no time zone available
  77. #endif
  78. #else /* ! USE_POSIX_TIME */
  79. CTimeZone = tb.timezone * 60;
  80. CDayLight = (tb.dstflag != 0);
  81. /*
  82.  * XXX does this work to get the local timezone string in V7? -
  83.  * tgl 97/03/18
  84.  */
  85. strftime(CTZName, MAXTZLEN, "%Z", localtime(&now));
  86. #endif
  87. };
  88. #ifdef DATEDEBUG
  89. printf("GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTCn",
  90.    CTZName, CTimeZone);
  91. #endif
  92. return (AbsoluteTime) now;
  93. } /* GetCurrentAbsoluteTime() */
  94. void
  95. GetCurrentTime(struct tm * tm)
  96. {
  97. int tz;
  98. abstime2tm(GetCurrentTransactionStartTime(), &tz, tm, NULL);
  99. return;
  100. } /* GetCurrentTime() */
  101. void
  102. abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn)
  103. {
  104. #ifdef USE_POSIX_TIME
  105. struct tm  *tx;
  106. #else /* ! USE_POSIX_TIME */
  107. struct timeb tb; /* the old V7-ism */
  108. ftime(&tb);
  109. #endif
  110. #ifdef USE_POSIX_TIME
  111. if (tzp != NULL)
  112. tx = localtime((time_t *) &time);
  113. else
  114. {
  115. tx = gmtime((time_t *) &time);
  116. };
  117. #endif
  118. #if defined(DATEDEBUG)
  119. #if defined(HAVE_TM_ZONE)
  120. printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s dst=%dn",
  121.    tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
  122.    tx->tm_zone, tx->tm_isdst);
  123. #elif defined(HAVE_INT_TIMEZONE)
  124. printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02d %s %s dst=%dn",
  125.    tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, tx->tm_sec,
  126.    tzname[0], tzname[1], tx->tm_isdst);
  127. #endif
  128. #endif
  129. #ifdef USE_POSIX_TIME
  130. tm->tm_year = tx->tm_year + 1900;
  131. tm->tm_mon = tx->tm_mon + 1;
  132. tm->tm_mday = tx->tm_mday;
  133. tm->tm_hour = tx->tm_hour;
  134. tm->tm_min = tx->tm_min;
  135. tm->tm_sec = tx->tm_sec;
  136. tm->tm_isdst = tx->tm_isdst;
  137. #if defined(HAVE_TM_ZONE)
  138. tm->tm_gmtoff = tx->tm_gmtoff;
  139. tm->tm_zone = tx->tm_zone;
  140. if (tzp != NULL)
  141. *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
  142. /* XXX FreeBSD man pages indicate that this should work - tgl 97/04/23 */
  143. if (tzn != NULL)
  144. strcpy(tzn, tm->tm_zone);
  145. #elif defined(HAVE_INT_TIMEZONE)
  146. if (tzp != NULL)
  147. #ifdef __CYGWIN__
  148. *tzp = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
  149. #else
  150. *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
  151. #endif
  152. if (tzn != NULL)
  153. strcpy(tzn, tzname[tm->tm_isdst]);
  154. #else
  155. #error POSIX time support is broken
  156. #endif
  157. #else /* ! USE_POSIX_TIME */
  158. if (tzp != NULL)
  159. *tzp = tb.timezone * 60;
  160. /*
  161.  * XXX does this work to get the local timezone string in V7? - tgl
  162.  * 97/03/18
  163.  */
  164. if (tzn != NULL)
  165. strftime(tzn, MAXTZLEN, "%Z", localtime(&now));
  166. #endif
  167. return;
  168. } /* abstime2tm() */
  169. /* tm2abstime()
  170.  * Convert a tm structure to abstime.
  171.  * Note that tm has full year (not 1900-based) and 1-based month.
  172.  */
  173. static AbsoluteTime
  174. tm2abstime(struct tm * tm, int tz)
  175. {
  176. int day,
  177. sec;
  178. /* validate, before going out of range on some members */
  179. if (tm->tm_year < 1901 || tm->tm_year > 2038
  180. || tm->tm_mon < 1 || tm->tm_mon > 12
  181. || tm->tm_mday < 1 || tm->tm_mday > 31
  182. || tm->tm_hour < 0 || tm->tm_hour >= 24
  183. || tm->tm_min < 0 || tm->tm_min > 59
  184. || tm->tm_sec < 0 || tm->tm_sec > 59)
  185. return INVALID_ABSTIME;
  186. day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(1970, 1, 1));
  187. /* check for time out of range */
  188. if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM))
  189. return INVALID_ABSTIME;
  190. /* convert to seconds */
  191. sec = tm->tm_sec + tz + (tm->tm_min + (day * 24 + tm->tm_hour) * 60) * 60;
  192. /* check for overflow */
  193. if ((day == MAX_DAYNUM && sec < 0) ||
  194. (day == MIN_DAYNUM && sec > 0))
  195. return INVALID_ABSTIME;
  196. /* check for reserved values (e.g. "current" on edge of usual range */
  197. if (!AbsoluteTimeIsReal(sec))
  198. return INVALID_ABSTIME;
  199. return sec;
  200. } /* tm2abstime() */
  201. /* nabstimein()
  202.  * Decode date/time string and return abstime.
  203.  */
  204. AbsoluteTime
  205. nabstimein(char *str)
  206. {
  207. AbsoluteTime result;
  208. double fsec;
  209. int tz = 0;
  210. struct tm date,
  211.    *tm = &date;
  212. char    *field[MAXDATEFIELDS];
  213. char lowstr[MAXDATELEN + 1];
  214. int dtype;
  215. int nf,
  216. ftype[MAXDATEFIELDS];
  217. if (!PointerIsValid(str))
  218. elog(ERROR, "Bad (null) abstime external representation", NULL);
  219. if (strlen(str) > MAXDATELEN)
  220. elog(ERROR, "Bad (length) abstime external representation '%s'", str);
  221. if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
  222.   || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
  223. elog(ERROR, "Bad abstime external representation '%s'", str);
  224. #ifdef DATEDEBUG
  225. printf("nabstimein- %d fields are type %d (DTK_DATE=%d)n", nf, dtype, DTK_DATE);
  226. #endif
  227. switch (dtype)
  228. {
  229. case DTK_DATE:
  230. result = tm2abstime(tm, tz);
  231. break;
  232. case DTK_EPOCH:
  233. result = EPOCH_ABSTIME;
  234. break;
  235. case DTK_CURRENT:
  236. result = CURRENT_ABSTIME;
  237. break;
  238. case DTK_LATE:
  239. result = NOEND_ABSTIME;
  240. break;
  241. case DTK_EARLY:
  242. result = NOSTART_ABSTIME;
  243. break;
  244. case DTK_INVALID:
  245. result = INVALID_ABSTIME;
  246. break;
  247. default:
  248. elog(ERROR, "Bad abstime (internal coding error) '%s'", str);
  249. result = INVALID_ABSTIME;
  250. break;
  251. };
  252. return result;
  253. } /* nabstimein() */
  254. /* nabstimeout()
  255.  * Given an AbsoluteTime return the English text version of the date
  256.  */
  257. char *
  258. nabstimeout(AbsoluteTime time)
  259. {
  260. char    *result;
  261. int tz;
  262. double fsec = 0;
  263. struct tm tt,
  264.    *tm = &tt;
  265. char buf[MAXDATELEN + 1];
  266. char zone[MAXDATELEN + 1],
  267.    *tzn = zone;
  268. switch (time)
  269. {
  270. case EPOCH_ABSTIME:
  271. strcpy(buf, EPOCH);
  272. break;
  273. case INVALID_ABSTIME:
  274. strcpy(buf, INVALID);
  275. break;
  276. case CURRENT_ABSTIME:
  277. strcpy(buf, DCURRENT);
  278. break;
  279. case NOEND_ABSTIME:
  280. strcpy(buf, LATE);
  281. break;
  282. case NOSTART_ABSTIME:
  283. strcpy(buf, EARLY);
  284. break;
  285. default:
  286. abstime2tm(time, &tz, tm, tzn);
  287. EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
  288. break;
  289. }
  290. result = palloc(strlen(buf) + 1);
  291. strcpy(result, buf);
  292. return result;
  293. } /* nabstimeout() */
  294. /*
  295.  * AbsoluteTimeIsBefore -- true iff time1 is before time2.
  296.  * AbsoluteTimeIsBefore -- true iff time1 is after time2.
  297.  */
  298. bool
  299. AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2)
  300. {
  301. Assert(AbsoluteTimeIsValid(time1));
  302. Assert(AbsoluteTimeIsValid(time2));
  303. if (time1 == CURRENT_ABSTIME)
  304. time1 = GetCurrentTransactionStartTime();
  305. if (time2 == CURRENT_ABSTIME)
  306. time2 = GetCurrentTransactionStartTime();
  307. return time1 < time2;
  308. }
  309. #ifdef NOT_USED
  310. bool
  311. AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
  312. {
  313. Assert(AbsoluteTimeIsValid(time1));
  314. Assert(AbsoluteTimeIsValid(time2));
  315. if (time1 == CURRENT_ABSTIME)
  316. time1 = GetCurrentTransactionStartTime();
  317. if (time2 == CURRENT_ABSTIME)
  318. time2 = GetCurrentTransactionStartTime();
  319. return time1 > time2;
  320. }
  321. #endif
  322. /* abstime_finite()
  323.  */
  324. bool
  325. abstime_finite(AbsoluteTime abstime)
  326. {
  327. return ((abstime != INVALID_ABSTIME)
  328.   && (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME));
  329. } /* abstime_finite() */
  330. /*
  331.  * abstimeeq - returns 1, iff arguments are equal
  332.  * abstimene - returns 1, iff arguments are not equal
  333.  * abstimelt - returns 1, iff t1 less than t2
  334.  * abstimegt - returns 1, iff t1 greater than t2
  335.  * abstimele - returns 1, iff t1 less than or equal to t2
  336.  * abstimege - returns 1, iff t1 greater than or equal to t2
  337.  */
  338. bool
  339. abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
  340. {
  341. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  342. return FALSE;
  343. if (t1 == CURRENT_ABSTIME)
  344. t1 = GetCurrentTransactionStartTime();
  345. if (t2 == CURRENT_ABSTIME)
  346. t2 = GetCurrentTransactionStartTime();
  347. return t1 == t2;
  348. }
  349. bool
  350. abstimene(AbsoluteTime t1, AbsoluteTime t2)
  351. {
  352. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  353. return FALSE;
  354. if (t1 == CURRENT_ABSTIME)
  355. t1 = GetCurrentTransactionStartTime();
  356. if (t2 == CURRENT_ABSTIME)
  357. t2 = GetCurrentTransactionStartTime();
  358. return t1 != t2;
  359. }
  360. bool
  361. abstimelt(AbsoluteTime t1, AbsoluteTime t2)
  362. {
  363. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  364. return FALSE;
  365. if (t1 == CURRENT_ABSTIME)
  366. t1 = GetCurrentTransactionStartTime();
  367. if (t2 == CURRENT_ABSTIME)
  368. t2 = GetCurrentTransactionStartTime();
  369. return t1 < t2;
  370. }
  371. bool
  372. abstimegt(AbsoluteTime t1, AbsoluteTime t2)
  373. {
  374. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  375. return FALSE;
  376. if (t1 == CURRENT_ABSTIME)
  377. t1 = GetCurrentTransactionStartTime();
  378. if (t2 == CURRENT_ABSTIME)
  379. t2 = GetCurrentTransactionStartTime();
  380. return t1 > t2;
  381. }
  382. bool
  383. abstimele(AbsoluteTime t1, AbsoluteTime t2)
  384. {
  385. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  386. return FALSE;
  387. if (t1 == CURRENT_ABSTIME)
  388. t1 = GetCurrentTransactionStartTime();
  389. if (t2 == CURRENT_ABSTIME)
  390. t2 = GetCurrentTransactionStartTime();
  391. return t1 <= t2;
  392. }
  393. bool
  394. abstimege(AbsoluteTime t1, AbsoluteTime t2)
  395. {
  396. if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
  397. return FALSE;
  398. if (t1 == CURRENT_ABSTIME)
  399. t1 = GetCurrentTransactionStartTime();
  400. if (t2 == CURRENT_ABSTIME)
  401. t2 = GetCurrentTransactionStartTime();
  402. return t1 >= t2;
  403. }
  404. /* datetime_abstime()
  405.  * Convert datetime to abstime.
  406.  */
  407. AbsoluteTime
  408. datetime_abstime(DateTime *datetime)
  409. {
  410. AbsoluteTime result;
  411. double fsec;
  412. struct tm tt,
  413.    *tm = &tt;
  414. if (!PointerIsValid(datetime))
  415. {
  416. result = INVALID_ABSTIME;
  417. }
  418. else if (DATETIME_IS_INVALID(*datetime))
  419. {
  420. result = INVALID_ABSTIME;
  421. }
  422. else if (DATETIME_IS_NOBEGIN(*datetime))
  423. {
  424. result = NOSTART_ABSTIME;
  425. }
  426. else if (DATETIME_IS_NOEND(*datetime))
  427. {
  428. result = NOEND_ABSTIME;
  429. }
  430. else
  431. {
  432. if (DATETIME_IS_RELATIVE(*datetime))
  433. {
  434. datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL);
  435. result = tm2abstime(tm, 0);
  436. }
  437. else if (datetime2tm(*datetime, NULL, tm, &fsec, NULL) == 0)
  438. {
  439. result = tm2abstime(tm, 0);
  440. }
  441. else
  442. {
  443. result = INVALID_ABSTIME;
  444. };
  445. };
  446. return result;
  447. } /* datetime_abstime() */
  448. /* abstime_datetime()
  449.  * Convert abstime to datetime.
  450.  */
  451. DateTime   *
  452. abstime_datetime(AbsoluteTime abstime)
  453. {
  454. DateTime   *result;
  455. if (!PointerIsValid(result = palloc(sizeof(DateTime))))
  456. elog(ERROR, "Unable to allocate space to convert abstime to datetime", NULL);
  457. switch (abstime)
  458. {
  459. case INVALID_ABSTIME:
  460. DATETIME_INVALID(*result);
  461. break;
  462. case NOSTART_ABSTIME:
  463. DATETIME_NOBEGIN(*result);
  464. break;
  465. case NOEND_ABSTIME:
  466. DATETIME_NOEND(*result);
  467. break;
  468. case EPOCH_ABSTIME:
  469. DATETIME_EPOCH(*result);
  470. break;
  471. case CURRENT_ABSTIME:
  472. DATETIME_CURRENT(*result);
  473. break;
  474. default:
  475. *result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400);
  476. break;
  477. };
  478. return result;
  479. } /* abstime_datetime() */