📄 date.c
字号:
/*------------------------------------------------------------------------- * * date.c * Utilities for the built-in type "AbsoluteTime" (defined in nabstime). * Functions for the built-in type "RelativeTime". * Functions for the built-in type "TimeInterval". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.32.2.1 1999/08/02 05:24:51 scrappy Exp $ * * NOTES * This code is actually (almost) unused. * It needs to be integrated with Time and struct trange. * * 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. * * XXX This code has been cleaned up some - avi 07/07/93 * *------------------------------------------------------------------------- */#include <ctype.h>#include <time.h>#include <sys/time.h>#include <sys/types.h>#include "postgres.h"#ifdef HAVE_FLOAT_H#include <float.h>#endif#ifdef HAVE_LIMITS_H#include <limits.h>#endif#include "access/xact.h"#include "miscadmin.h"#include "utils/builtins.h"#include "utils/dt.h"#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)/* * Unix epoch is Jan 1 00:00:00 1970. Postgres knows about times * sixty-eight years on either side of that. */#define IsSpace(C) ((C) == ' ')#define T_INTERVAL_INVAL 0 /* data represents no valid interval */#define T_INTERVAL_VALID 1 /* data represents a valid interval *//* * ['Mon May 10 23:59:12 1943 PST' 'Sun Jan 14 03:14:21 1973 PST'] * 0 1 2 3 4 5 6 * 1234567890123456789012345678901234567890123456789012345678901234 * * we allocate some extra -- timezones are usually 3 characters but * this is not in the POSIX standard... */#define T_INTERVAL_LEN 80#define INVALID_INTERVAL_STR "Undefined Range"#define INVALID_INTERVAL_STR_LEN (sizeof(INVALID_INTERVAL_STR)-1)#define ABSTIMEMIN(t1, t2) abstimele((t1),(t2)) ? (t1) : (t2)#define ABSTIMEMAX(t1, t2) abstimelt((t1),(t2)) ? (t2) : (t1)#ifdef NOT_USEDstatic char *unit_tab[] = { "second", "seconds", "minute", "minutes", "hour", "hours", "day", "days", "week", "weeks","month", "months", "year", "years"};#define UNITMAXLEN 7 /* max length of a unit name */#define NUNITS 14 /* number of different units *//* table of seconds per unit (month = 30 days, year = 365 days) */static int sec_tab[] = { 1, 1, 60, 60, 3600, 3600, 86400, 86400, 604800, 604800,2592000, 2592000, 31536000, 31536000};#endif/* * Function prototypes -- internal to this file only */static void reltime2tm(RelativeTime time, struct tm * tm);#ifdef NOT_USEDstatic int correct_unit(char *unit, int *unptr);static int correct_dir(char *direction, int *signptr);#endifstatic int istinterval(char *i_string, AbsoluteTime *i_start, AbsoluteTime *i_end);/***************************************************************************** * USER I/O ROUTINES * *****************************************************************************//* * reltimein - converts a reltime string in an internal format */RelativeTimereltimein(char *str){ RelativeTime result; struct tm tt, *tm = &tt; double fsec; int dtype; char *field[MAXDATEFIELDS]; int nf, ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; if (!PointerIsValid(str)) elog(ERROR, "Bad (null) date external representation", NULL); if (strlen(str) > MAXDATELEN) elog(ERROR, "Bad (length) reltime external representation '%s'", str); if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) elog(ERROR, "Bad reltime external representation '%s'", str);#ifdef DATEDEBUG printf("reltimein- %d fields are type %d (DTK_DATE=%d)\n", nf, dtype, DTK_DATE);#endif switch (dtype) { 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)); return result; default: return INVALID_RELTIME; } elog(ERROR, "Bad reltime (internal coding error) '%s'", str); return INVALID_RELTIME;} /* reltimein() *//* * reltimeout - converts the internal format to a reltime string */char *reltimeout(RelativeTime time){ char *result; struct tm tt, *tm = &tt; char buf[MAXDATELEN + 1]; if (time == INVALID_RELTIME) { strcpy(buf, INVALID_RELTIME_STR); } else { reltime2tm(time, tm); EncodeTimeSpan(tm, 0, DateStyle, buf); } result = palloc(strlen(buf) + 1); strcpy(result, buf); return result;} /* reltimeout() */#define TMODULO(t,q,u) \do { \ q = (t / u); \ if (q != 0) t -= (q * u); \} while(0)static voidreltime2tm(RelativeTime time, struct tm * tm){ 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); return;} /* reltime2tm() */#ifdef NOT_USEDintdummyfunc(){ 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; } 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;}#endif/* * tintervalin - converts an interval string to an internal format */TimeIntervaltintervalin(char *intervalstr){ int error; AbsoluteTime i_start, i_end, t1, t2; TimeInterval interval; 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; } return interval;}/* * tintervalout - converts an internal interval format to a string * */char *tintervalout(TimeInterval interval){ char *i_str, *p; 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"); return i_str;}/***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************/RelativeTimetimespan_reltime(TimeSpan *timespan){ RelativeTime time; int year, month; double span; if (!PointerIsValid(timespan)) time = INVALID_RELTIME; if (TIMESPAN_IS_INVALID(*timespan)) { time = INVALID_RELTIME; } else { if (timespan->month == 0) { year = 0; month = 0; } else if (abs(timespan->month) >= 12) { year = (timespan->month / 12); month = (timespan->month % 12); } else { year = 0; month = timespan->month; } span = (((((double) 365 * year) + ((double) 30 * month)) * 86400) + timespan->time);#ifdef DATEDEBUG printf("timespan_reltime- convert m%d s%f to %f [%d %d]\n", timespan->month, timespan->time, span, INT_MIN, INT_MAX);#endif time = (((span > INT_MIN) && (span < INT_MAX)) ? span : INVALID_RELTIME); } return time;} /* timespan_reltime() */TimeSpan *reltime_timespan(RelativeTime reltime){ TimeSpan *result; int year, month; if (!PointerIsValid(result = palloc(sizeof(TimeSpan)))) elog(ERROR, "Memory allocation failed, can't convert reltime to timespan", NULL); switch (reltime) { case INVALID_RELTIME: TIMESPAN_INVALID(*result); break; default: TMODULO(reltime, year, 31536000); TMODULO(reltime, month, 2592000); result->time = reltime; result->month = ((12 * year) + month); } return result;} /* reltime_timespan() *//* * mktinterval - creates a time interval with endpoints t1 and t2 */TimeIntervalmktinterval(AbsoluteTime t1, AbsoluteTime t2){ AbsoluteTime tstart = ABSTIMEMIN(t1, t2), tend = ABSTIMEMAX(t1, t2); TimeInterval interval; 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;}/* * timepl, timemi and abstimemi use the formula * abstime + reltime = abstime * so abstime - reltime = abstime * and abstime - abstime = reltime *//* * timepl - returns the value of (abstime t1 + relime t2) */AbsoluteTimetimepl(AbsoluteTime t1, RelativeTime t2){ if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (AbsoluteTimeIsReal(t1) && RelativeTimeIsValid(t2) && ((t2 > 0) ? (t1 < NOEND_ABSTIME - t2) : (t1 > NOSTART_ABSTIME - t2))) /* prevent overflow */ return t1 + t2; return INVALID_ABSTIME;}/* * timemi - returns the value of (abstime t1 - reltime t2) */AbsoluteTimetimemi(AbsoluteTime t1, RelativeTime t2){ if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (AbsoluteTimeIsReal(t1) && RelativeTimeIsValid(t2) && ((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2) : (t1 < NOEND_ABSTIME + t2))) /* prevent overflow */ return t1 - t2; return INVALID_ABSTIME;}/* * abstimemi - returns the value of (abstime t1 - abstime t2) */static RelativeTimeabstimemi(AbsoluteTime t1, AbsoluteTime t2){ if (t1 == CURRENT_ABSTIME) t1 = GetCurrentTransactionStartTime(); if (t2 == CURRENT_ABSTIME) t2 = GetCurrentTransactionStartTime(); if (AbsoluteTimeIsReal(t1) && AbsoluteTimeIsReal(t2)) return t1 - t2; return INVALID_RELTIME;}/* * ininterval - returns 1, iff absolute date is in the interval */intininterval(AbsoluteTime t, TimeInterval interval){ if (interval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME) return (abstimege(t, interval->data[0]) && abstimele(t, interval->data[1])); return 0;}/* * intervalrel - returns relative time corresponding to interval */RelativeTimeintervalrel(TimeInterval interval){ if (interval->status == T_INTERVAL_VALID) return abstimemi(interval->data[1], interval->data[0]); else return INVALID_RELTIME;}/* * timenow - returns time "now", internal format * * Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992 */AbsoluteTimetimenow(){ time_t sec; if (time(&sec) < 0) return INVALID_ABSTIME; return (AbsoluteTime) sec;}/* * 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 */boolreltimeeq(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 == t2;}boolreltimene(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 != t2;}boolreltimelt(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 < t2;}boolreltimegt(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 > t2;}boolreltimele(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 <= t2;}boolreltimege(RelativeTime t1, RelativeTime t2){ if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME) return 0; return t1 >= t2;}/* * intervalsame - returns 1, iff interval i1 is same as interval i2 * Check begin and end time. */boolintervalsame(TimeInterval i1, TimeInterval i2){ if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) return FALSE; /* invalid interval */ return (abstimeeq(i1->data[0], i2->data[0]) && abstimeeq(i1->data[1], i2->data[1]));} /* intervalsame() *//* * intervaleq - returns 1, iff interval i1 is equal to interval i2 * Check length of intervals. */boolintervaleq(TimeInterval i1, TimeInterval i2){ AbsoluteTime t10, t11, t20, t21; if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) return FALSE; /* invalid interval */ t10 = i1->data[0]; t11 = i1->data[1]; t20 = i2->data[0]; t21 = i2->data[1]; if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME)) return FALSE; if (t10 == CURRENT_ABSTIME) t10 = GetCurrentTransactionStartTime(); if (t11 == CURRENT_ABSTIME) t11 = GetCurrentTransactionStartTime(); if (t20 == CURRENT_ABSTIME) t20 = GetCurrentTransactionStartTime(); if (t21 == CURRENT_ABSTIME) t21 = GetCurrentTransactionStartTime(); return (t11 - t10) == (t21 - t20);} /* intervaleq() *//* * intervalne - returns 1, iff interval i1 is not equal to interval i2 * Check length of intervals. */boolintervalne(TimeInterval i1, TimeInterval i2){ AbsoluteTime t10, t11, t20, t21; if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL) return FALSE; /* invalid interval */ t10 = i1->data[0]; t11 = i1->data[1]; t20 = i2->data[0]; t21 = i2->data[1]; if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME)) return FALSE; if (t10 == CURRENT_ABSTIME) t10 = GetCurrentTransactionStartTime(); if (t11 == CURRENT_ABSTIME) t11 = GetCurrentTransactionStartTime(); if (t20 == CURRENT_ABSTIME) t20 = GetCurrentTransactionStartTime(); if (t21 == CURRENT_ABSTIME) t21 = GetCurrentTransactionStartTime(); return (t11 - t10) != (t21 - t20);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -