📄 dt.c
字号:
/*------------------------------------------------------------------------- * * dt.c * Functions for the built-in type "dt". * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/dt.c,v 1.72.2.1 1999/08/02 05:24:51 scrappy Exp $ * *------------------------------------------------------------------------- */#include <ctype.h>#include <math.h>#include <sys/types.h>#include <errno.h>#include "postgres.h"#ifdef HAVE_FLOAT_H#include <float.h>#endif#ifdef HAVE_LIMITS_H#include <limits.h>#endif#ifndef USE_POSIX_TIME#include <sys/timeb.h>#endif#include "miscadmin.h"#include "utils/builtins.h"static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);static int DecodeNumber(int flen, char *field, int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);static int DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);static int DecodeSpecial(int field, char *lowtoken, int *val);static int DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec);static int DecodeTimezone(char *str, int *tzp);static int DecodeUnits(int field, char *lowtoken, int *val);static int EncodeSpecialDateTime(DateTime dt, char *str);static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);static DateTime dt2local(DateTime dt, int timezone);static void dt2time(DateTime dt, int *hour, int *min, double *sec);static int j2day(int jd);static double time2t(const int hour, const int min, const double sec);static int timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec);static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span);#define USE_DATE_CACHE 1#define ROUND_ALL 0int day_tab[2][13] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday", NULL};/* TMODULO() * Macro to replace modf(), which is broken on some platforms. */#define TMODULO(t,q,u) \do { \ q = ((t < 0)? ceil(t / u): floor(t / u)); \ if (q != 0) \ t -= rint(q * u); \} while(0)static void GetEpochTime(struct tm * tm);#define UTIME_MINYEAR (1901)#define UTIME_MINMONTH (12)#define UTIME_MINDAY (14)#define UTIME_MAXYEAR (2038)#define UTIME_MAXMONTH (01)#define UTIME_MAXDAY (18)#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \ || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \ && ((y < UTIME_MAXYEAR) \ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \ || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))/***************************************************************************** * USER I/O ROUTINES * *****************************************************************************//* datetime_in() * Convert a string to internal form. */DateTime *datetime_in(char *str){ DateTime *result; double fsec; struct tm tt, *tm = &tt; int tz; int dtype; int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; if (!PointerIsValid(str)) elog(ERROR, "Bad (null) datetime external representation", NULL); if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) elog(ERROR, "Bad datetime external representation '%s'", str); result = palloc(sizeof(DateTime)); switch (dtype) { case DTK_DATE: if (tm2datetime(tm, fsec, &tz, result) != 0) elog(ERROR, "Datetime out of range '%s'", str);#ifdef DATEDEBUG printf("datetime_in- date is %f\n", *result);#endif break; case DTK_EPOCH: DATETIME_EPOCH(*result); break; case DTK_CURRENT: DATETIME_CURRENT(*result); break; case DTK_LATE: DATETIME_NOEND(*result); break; case DTK_EARLY: DATETIME_NOBEGIN(*result); break; case DTK_INVALID: DATETIME_INVALID(*result); break; default: elog(ERROR, "Internal coding error, can't input datetime '%s'", str); } return result;} /* datetime_in() *//* datetime_out() * Convert a datetime to external form. */char *datetime_out(DateTime *dt){ char *result; int tz; struct tm tt, *tm = &tt; double fsec; char *tzn; char buf[MAXDATELEN + 1]; if (!PointerIsValid(dt)) return NULL; if (DATETIME_IS_RESERVED(*dt)) { EncodeSpecialDateTime(*dt, buf); } else if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) == 0) { EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf); } else EncodeSpecialDateTime(DT_INVALID, buf); result = palloc(strlen(buf) + 1); strcpy(result, buf); return result;} /* datetime_out() *//* timespan_in() * Convert a string to internal form. * * External format(s): * Uses the generic date/time parsing and decoding routines. */TimeSpan *timespan_in(char *str){ TimeSpan *span; double fsec; struct tm tt, *tm = &tt; int dtype; int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; tm->tm_year = 0; tm->tm_mon = 0; tm->tm_mday = 0; tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; fsec = 0; if (!PointerIsValid(str)) elog(ERROR, "Bad (null) timespan external representation", NULL); if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0)) elog(ERROR, "Bad timespan external representation '%s'", str); span = palloc(sizeof(TimeSpan)); switch (dtype) { case DTK_DELTA: if (tm2timespan(tm, fsec, span) != 0) {#if NOT_USED TIMESPAN_INVALID(span);#endif elog(ERROR, "Bad timespan external representation '%s'", str); } break; default: elog(ERROR, "Internal coding error, can't input timespan '%s'", str); } return span;} /* timespan_in() *//* timespan_out() * Convert a time span to external form. */char *timespan_out(TimeSpan *span){ char *result; struct tm tt, *tm = &tt; double fsec; char buf[MAXDATELEN + 1]; if (!PointerIsValid(span)) return NULL; if (timespan2tm(*span, tm, &fsec) != 0) return NULL; if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0) elog(ERROR, "Unable to format timespan", NULL); result = palloc(strlen(buf) + 1); strcpy(result, buf); return result;} /* timespan_out() *//***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************/booldatetime_finite(DateTime *datetime){ if (!PointerIsValid(datetime)) return FALSE; return !DATETIME_NOT_FINITE(*datetime);} /* datetime_finite() */booltimespan_finite(TimeSpan *timespan){ if (!PointerIsValid(timespan)) return FALSE; return !TIMESPAN_NOT_FINITE(*timespan);} /* timespan_finite() *//*---------------------------------------------------------- * Relational operators for datetime. *---------------------------------------------------------*/static voidGetEpochTime(struct tm * tm){ struct tm *t0; time_t epoch = 0; t0 = gmtime(&epoch); tm->tm_year = t0->tm_year; tm->tm_mon = t0->tm_mon; tm->tm_mday = t0->tm_mday; tm->tm_hour = t0->tm_hour; tm->tm_min = t0->tm_min; tm->tm_sec = t0->tm_sec; if (tm->tm_year < 1900) tm->tm_year += 1900; tm->tm_mon++;#ifdef DATEDEBUG printf("GetEpochTime- %04d-%02d-%02d %02d:%02d:%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);#endif return;} /* GetEpochTime() */DateTimeSetDateTime(DateTime dt){ struct tm tt; if (DATETIME_IS_CURRENT(dt)) { GetCurrentTime(&tt); tm2datetime(&tt, 0, NULL, &dt); dt = dt2local(dt, -CTimeZone);#ifdef DATEDEBUG printf("SetDateTime- current time is %f\n", dt);#endif } else { /* if (DATETIME_IS_EPOCH(dt1)) */ GetEpochTime(&tt); tm2datetime(&tt, 0, NULL, &dt);#ifdef DATEDEBUG printf("SetDateTime- epoch time is %f\n", dt);#endif } return dt;} /* SetDateTime() *//* datetime_relop - is datetime1 relop datetime2 */booldatetime_eq(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); return dt1 == dt2;} /* datetime_eq() */booldatetime_ne(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); return dt1 != dt2;} /* datetime_ne() */booldatetime_lt(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); return dt1 < dt2;} /* datetime_lt() */booldatetime_gt(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);#ifdef DATEDEBUG printf("datetime_gt- %f %s greater than %f\n", dt1, ((dt1 > dt2) ? "is" : "is not"), dt2);#endif return dt1 > dt2;} /* datetime_gt() */booldatetime_le(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); return dt1 <= dt2;} /* datetime_le() */booldatetime_ge(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return FALSE; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2)) return FALSE; if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); return dt1 >= dt2;} /* datetime_ge() *//* datetime_cmp - 3-state comparison for datetime * collate invalid datetime at the end */intdatetime_cmp(DateTime *datetime1, DateTime *datetime2){ DateTime dt1, dt2; if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2)) return 0; dt1 = *datetime1; dt2 = *datetime2; if (DATETIME_IS_INVALID(dt1)) { return (DATETIME_IS_INVALID(dt2) ? 0 : 1); } else if (DATETIME_IS_INVALID(dt2)) { return -1; } else { if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1); if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2); } return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));} /* datetime_cmp() *//* timespan_relop - is timespan1 relop timespan2 */booltimespan_eq(TimeSpan *timespan1, TimeSpan *timespan2){ if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) return FALSE; if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2)) return FALSE; return ((timespan1->time == timespan2->time) && (timespan1->month == timespan2->month));} /* timespan_eq() */booltimespan_ne(TimeSpan *timespan1, TimeSpan *timespan2){ if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2)) return FALSE; if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -