mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: [HACKERS] More date time functions Here are some additional patches mostly related to the date and time data types. It includes some type conversion routines to move between the different date types and some other date manipulation routines such as date_part(units,datetime). I noticed Edmund Mergl et al's neat trick for getting function overloading for builtin functions, so started to use that for the date and time stuff. Later, if someone figures out how to get function overloading directly for internal C code, then we can move to that technique. These patches include documentation updates (don't faint!) for the built-in man page. Doesn't yet include mention of timestamp, since I don't know much about it and since it may change a bit to become a _real_ ANSI timestamp which would include parser support for the declaration syntax (what do you think, Dan?). The patches were developed on the 970330 release, but have been rebuilt off of the 970402 release. The first patch below is to get libpq to compile, on my Linux box, but is not related to the rest of the patches and you can choose not to apply that one at this time. Thanks in advance, scrappy!
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.6 1997/03/14 23:19:57 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.7 1997/04/02 18:33:09 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This code is actually (almost) unused.
|
||||
@@ -32,15 +32,14 @@
|
||||
|
||||
#include "postgres.h"
|
||||
#include "miscadmin.h"
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#include "access/xact.h"
|
||||
#include "utils/builtins.h" /* where function declarations go */
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/dt.h"
|
||||
|
||||
#ifndef USE_NEW_TIME_CODE
|
||||
#define USE_NEW_TIME_CODE 1
|
||||
#endif
|
||||
|
||||
#define INVALID_RELTIME_STR "Undefined RelTime"
|
||||
#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1)
|
||||
#define RELTIME_LABEL '@'
|
||||
@@ -235,6 +234,55 @@ char *tintervalout(TimeInterval interval)
|
||||
* PUBLIC ROUTINES *
|
||||
*****************************************************************************/
|
||||
|
||||
RelativeTime
|
||||
timespan_reltime(TimeSpan *timespan)
|
||||
{
|
||||
RelativeTime time;
|
||||
double span;
|
||||
|
||||
if (!PointerIsValid(timespan))
|
||||
time = INVALID_RELTIME;
|
||||
|
||||
if (TIMESPAN_IS_INVALID(*timespan)) {
|
||||
time = INVALID_RELTIME;
|
||||
|
||||
} else {
|
||||
span = ((((double) 30*86400)*timespan->month) + 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;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN,"Memory allocation failed, can't convert reltime to timespan",NULL);
|
||||
|
||||
switch(reltime) {
|
||||
case INVALID_RELTIME:
|
||||
TIMESPAN_INVALID(*result);
|
||||
break;
|
||||
|
||||
default:
|
||||
result->time = reltime;
|
||||
result->month = 0;
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* reltime_timespan() */
|
||||
|
||||
|
||||
/*
|
||||
* mktinterval - creates a time interval with endpoints t1 and t2
|
||||
*/
|
||||
|
||||
@@ -7,18 +7,19 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.1 1997/03/14 23:20:01 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.2 1997/04/02 18:33:22 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h> /* for sprintf() */
|
||||
#include <string.h>
|
||||
|
||||
#include <postgres.h>
|
||||
#include <miscadmin.h>
|
||||
#include <utils/builtins.h>
|
||||
#include <utils/nabstime.h>
|
||||
#include <utils/datetime.h>
|
||||
#include "postgres.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/nabstime.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "access/xact.h"
|
||||
|
||||
static int day_tab[2][12] = {
|
||||
{31,28,31,30,31,30,31,31,30,31,30,31},
|
||||
@@ -72,36 +73,23 @@ printf( "date_in- input string is %s\n", str);
|
||||
elog(WARN,"Bad date external representation %s",str);
|
||||
|
||||
switch (dtype) {
|
||||
#if FALSE
|
||||
case DTK_DATE:
|
||||
date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday);
|
||||
time = time2j(tm->tm_hour,tm->tm_min,(double)tm->tm_sec);
|
||||
if (tzp != 0) {
|
||||
j2local(&date, &time, -(tzp*60));
|
||||
} else {
|
||||
j2local(&date, &time, -timezone);
|
||||
};
|
||||
break;
|
||||
#endif
|
||||
|
||||
case DTK_CURRENT:
|
||||
GetCurrentTime(tm);
|
||||
break;
|
||||
|
||||
case DTK_EPOCH:
|
||||
tm->tm_year = 1970;
|
||||
tm->tm_mon = 1;
|
||||
tm->tm_mday = 1;
|
||||
case DTK_DATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(WARN,"Unrecognized date external representation %s",str);
|
||||
};
|
||||
|
||||
#if FALSE
|
||||
if (tm->tm_year < 70)
|
||||
tm->tm_year += 2000;
|
||||
else if (tm->tm_year < 100)
|
||||
tm->tm_year += 1900;
|
||||
#endif
|
||||
|
||||
if (tm->tm_year < 0 || tm->tm_year > 32767)
|
||||
elog(WARN, "date_in: year must be limited to values 0 through 32767 in '%s'", str);
|
||||
if (tm->tm_mon < 1 || tm->tm_mon > 12)
|
||||
@@ -256,6 +244,82 @@ date_mii(DateADT dateVal, int4 days)
|
||||
return(date_pli(dateVal, -days));
|
||||
} /* date_mii() */
|
||||
|
||||
|
||||
/* date_datetime()
|
||||
* Convert date to datetime data type.
|
||||
*/
|
||||
DateTime *
|
||||
date_datetime(int4 dateVal)
|
||||
{
|
||||
DateTime *result;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Memory allocation failed, can't convert date to datetime",NULL);
|
||||
|
||||
*result = (dateVal - date2j( 2000, 1, 1));
|
||||
*result *= 86400;
|
||||
|
||||
return(result);
|
||||
} /* date_datetime() */
|
||||
|
||||
|
||||
/* datetime_date()
|
||||
* Convert datetime to date data type.
|
||||
*/
|
||||
DateADT
|
||||
datetime_date(DateTime *datetime)
|
||||
{
|
||||
DateADT result;
|
||||
|
||||
if (!PointerIsValid(datetime))
|
||||
elog(WARN,"Unable to convert null datetime to date",NULL);
|
||||
|
||||
result = (*datetime / 86400);
|
||||
|
||||
return(result);
|
||||
} /* datetime_date() */
|
||||
|
||||
|
||||
/* abstime_date()
|
||||
* Convert abstime to date data type.
|
||||
*/
|
||||
DateADT
|
||||
abstime_date(AbsoluteTime abstime)
|
||||
{
|
||||
DateADT result;
|
||||
struct tt, *tm = &tt;
|
||||
|
||||
switch (abstime) {
|
||||
case INVALID_ABSTIME:
|
||||
case NOSTART_ABSTIME:
|
||||
case NOEND_ABSTIME:
|
||||
elog(WARN,"Unable to convert reserved abstime value to date",NULL);
|
||||
break;
|
||||
|
||||
case EPOCH_ABSTIME:
|
||||
result = date2j(1970,1,1) - date2j(2000,1,1);
|
||||
break;
|
||||
|
||||
case CURRENT_ABSTIME:
|
||||
GetCurrentTime(tm);
|
||||
result = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1);
|
||||
break;
|
||||
|
||||
default:
|
||||
#if FALSE
|
||||
tm = localtime((time_t *) &abstime);
|
||||
tm->tm_year += 1900;
|
||||
tm->tm_mon += 1;
|
||||
/* XXX must shift to local time before converting - tgl 97/04/01 */
|
||||
#endif
|
||||
abstime2tm(abstime, &CTimeZone, tm);
|
||||
result = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1);
|
||||
break;
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* abstime_date() */
|
||||
|
||||
#else
|
||||
|
||||
bool
|
||||
@@ -392,69 +456,15 @@ date_smaller(int4 dateVal1, int4 dateVal2)
|
||||
int32
|
||||
date_mi(int4 dateVal1, int4 dateVal2)
|
||||
{
|
||||
#if USE_NEW_TIME_CODE
|
||||
|
||||
DateADT *date1, *date2;
|
||||
int days;
|
||||
|
||||
date1 = (DateADT *) &dateVal1;
|
||||
date2 = (DateADT *) &dateVal2;
|
||||
|
||||
days = (date2j(date1->year, date1->month, date1->day)
|
||||
- date2j(date2->year, date2->month, date2->day));
|
||||
|
||||
#else
|
||||
|
||||
DateADT dv1, dv2;
|
||||
DateADT *date1, *date2;
|
||||
int32 days = 0;
|
||||
int i;
|
||||
|
||||
/* This circumlocution allows us to assume that date1 is always
|
||||
before date2. */
|
||||
dv1 = date_smaller (dateVal1, dateVal2);
|
||||
dv2 = date_larger (dateVal1, dateVal2);
|
||||
date1 = (DateADT *) &dv1;
|
||||
date2 = (DateADT *) &dv2;
|
||||
|
||||
/* Sum number of days in each full year between date1 and date2. */
|
||||
for (i = date1->year + 1; i < date2->year; ++i)
|
||||
days += isleap(i) ? 366 : 365;
|
||||
|
||||
if (days)
|
||||
{
|
||||
/* We need to wrap around the year. Add in number of days in each
|
||||
full month from date1 to end of year. */
|
||||
for (i = date1->month + 1; i <= 12; ++i)
|
||||
days += day_tab[isleap(date1->year)][i - 1];
|
||||
|
||||
/* Add in number of days in each full month from start of year to
|
||||
date2. */
|
||||
for (i = 1; i < date2->month; ++i)
|
||||
days += day_tab[isleap(date2->year)][i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add in number of days in each full month from date1 to date2. */
|
||||
for (i = date1->month + 1; i < date2->month; ++i)
|
||||
days += day_tab[isleap(date1->year)][i - 1];
|
||||
}
|
||||
|
||||
if (days || date1->month != date2->month)
|
||||
{
|
||||
/* Add in number of days left in month for date1. */
|
||||
days += day_tab[isleap(date1->year)][date1->month - 1] - date1->day;
|
||||
|
||||
/* Add in day of month of date2. */
|
||||
days += date2->day;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Everything's in the same month, so just subtract the days! */
|
||||
days = date2->day - date1->day;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return (days);
|
||||
}
|
||||
|
||||
@@ -463,8 +473,6 @@ date_mi(int4 dateVal1, int4 dateVal2)
|
||||
int4
|
||||
date_pli(int4 dateVal, int32 days)
|
||||
{
|
||||
#if USE_NEW_TIME_CODE
|
||||
|
||||
DateADT *date1 = (DateADT *) &dateVal;
|
||||
int date, year, month, day;
|
||||
|
||||
@@ -474,41 +482,6 @@ date_pli(int4 dateVal, int32 days)
|
||||
date1->month = month;
|
||||
date1->day = day;
|
||||
|
||||
#else
|
||||
|
||||
DateADT *date1 = (DateADT *) &dateVal;
|
||||
/* Use separate day variable because date1->day is a narrow type. */
|
||||
int32 day = date1->day + days;
|
||||
|
||||
if (days > 0) {
|
||||
/* Loop as long as day has wrapped around end of month. */
|
||||
while (day > day_tab[isleap(date1->year)][date1->month - 1]) {
|
||||
day -= day_tab[isleap(date1->year)][date1->month - 1];
|
||||
if (++date1->month > 12) {
|
||||
/* Month wrapped around. */
|
||||
date1->month = 1;
|
||||
++date1->year;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Loop as long as day has wrapped around beginning of month. */
|
||||
while (day < 1) {
|
||||
/* Decrement month first, because a negative day number
|
||||
should be held as relative to the previous month's end. */
|
||||
if (--date1->month < 1) {
|
||||
/* Month wrapped around. */
|
||||
date1->month = 12;
|
||||
--date1->year;
|
||||
}
|
||||
|
||||
day += day_tab[isleap(date1->year)][date1->month - 1];
|
||||
}
|
||||
}
|
||||
date1->day = day;
|
||||
|
||||
#endif
|
||||
|
||||
return (dateVal);
|
||||
} /* date_pli() */
|
||||
|
||||
@@ -519,8 +492,93 @@ date_mii(int4 dateVal, int32 days)
|
||||
return (date_pli(dateVal, -days));
|
||||
}
|
||||
|
||||
DateTime *
|
||||
date_datetime(int4 dateVal)
|
||||
{
|
||||
DateTime *result;
|
||||
DateADT *date = (DateADT *) &dateVal;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Memory allocation failed, can't convert date to datetime",NULL);
|
||||
|
||||
*result = (date2j(date->year, date->month, date->day) - date2j( 2000, 1, 1));
|
||||
*result *= 86400;
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "date_datetime- convert %04d-%02d-%02d to %f\n",
|
||||
date->year, date->month, date->day, *result);
|
||||
#endif
|
||||
|
||||
return(result);
|
||||
} /* date_datetime() */
|
||||
|
||||
int4
|
||||
datetime_date(DateTime *datetime)
|
||||
{
|
||||
int4 result;
|
||||
int year, month, day;
|
||||
DateADT *date = (DateADT *) &result;
|
||||
|
||||
if (!PointerIsValid(datetime))
|
||||
elog(WARN,"Unable to convert null datetime to date",NULL);
|
||||
|
||||
j2date( ((*datetime / 86400) + date2j( 2000, 1, 1)), &year, &month, &day);
|
||||
date->year = year;
|
||||
date->month = month;
|
||||
date->day = day;
|
||||
|
||||
return(result);
|
||||
} /* datetime_date() */
|
||||
|
||||
int4
|
||||
abstime_date(AbsoluteTime abstime)
|
||||
{
|
||||
int4 result;
|
||||
DateADT *date = (DateADT *) &result;
|
||||
struct tm tt, *tm = &tt;
|
||||
|
||||
switch (abstime) {
|
||||
case INVALID_ABSTIME:
|
||||
case NOSTART_ABSTIME:
|
||||
case NOEND_ABSTIME:
|
||||
elog(WARN,"Unable to convert reserved abstime value to date",NULL);
|
||||
break;
|
||||
|
||||
case EPOCH_ABSTIME:
|
||||
date->year = 1970;
|
||||
date->month = 1;
|
||||
date->day = 1;
|
||||
break;
|
||||
|
||||
case CURRENT_ABSTIME:
|
||||
#if FALSE
|
||||
GetCurrentTime(tm);
|
||||
#endif
|
||||
abstime = GetCurrentTransactionStartTime() + CTimeZone;
|
||||
date->year = tm->tm_year;
|
||||
date->month = tm->tm_mon;
|
||||
date->day = tm->tm_mday;
|
||||
break;
|
||||
|
||||
default:
|
||||
#if FALSE
|
||||
tm = localtime((time_t *) &abstime);
|
||||
tm->tm_year += 1900;
|
||||
tm->tm_mon += 1;
|
||||
#endif
|
||||
abstime2tm(abstime, &CTimeZone, tm);
|
||||
date->year = tm->tm_year;
|
||||
date->month = tm->tm_mon;
|
||||
date->day = tm->tm_mday;
|
||||
break;
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* abstime_date() */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Time ADT
|
||||
*****************************************************************************/
|
||||
@@ -583,15 +641,14 @@ time_out(TimeADT *time)
|
||||
return NULL;
|
||||
|
||||
if (time->sec == 0.0) {
|
||||
sprintf(buf, "%02d:%02d",
|
||||
(int)time->hr, (int)time->min);
|
||||
sprintf(buf, "%02d:%02d", (int)time->hr, (int)time->min);
|
||||
} else {
|
||||
if (((int) time->sec) == time->sec) {
|
||||
sprintf(buf, "%02d:%02d:%02d",
|
||||
(int)time->hr, (int)time->min, (int)time->sec);
|
||||
(int)time->hr, (int)time->min, (int)time->sec);
|
||||
} else {
|
||||
sprintf(buf, "%02d:%02d:%09.6f",
|
||||
(int)time->hr, (int)time->min, time->sec);
|
||||
(int)time->hr, (int)time->min, time->sec);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -666,6 +723,29 @@ time_cmp(TimeADT *time1, TimeADT *time2)
|
||||
return((*time1 < *time2)? -1: (((*time1 < *time2)? 1: 0)));
|
||||
} /* time_cmp() */
|
||||
|
||||
|
||||
/* datetime_datetime()
|
||||
* Convert date and time to datetime data type.
|
||||
*/
|
||||
DateTime *
|
||||
datetime_datetime(DateADT date, TimeADT *time)
|
||||
{
|
||||
DateTime *result;
|
||||
|
||||
if (!PointerIsValid(time)) {
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Memory allocation failed, can't convert to datetime",NULL);
|
||||
|
||||
DATETIME_INVALID(*result);
|
||||
|
||||
} else {
|
||||
result = date_datetime(date);
|
||||
*result += *time;
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* datetime_datetime() */
|
||||
|
||||
#else
|
||||
|
||||
bool
|
||||
@@ -734,6 +814,34 @@ time_cmp(TimeADT *time1, TimeADT *time2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DateTime *
|
||||
datetime_datetime(int4 dateVal, TimeADT *time)
|
||||
{
|
||||
DateTime *result;
|
||||
#ifdef DATEDEBUG
|
||||
DateADT *date = (DateADT *) &dateVal;
|
||||
#endif
|
||||
|
||||
if (!PointerIsValid(time)) {
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Memory allocation failed, can't convert to datetime",NULL);
|
||||
|
||||
DATETIME_INVALID(*result);
|
||||
|
||||
} else {
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime_datetime- convert %04d-%02d-%02d %02d:%02d:%05.2f\n",
|
||||
date->year, date->month, date->day, time->hr, time->min, time->sec);
|
||||
#endif
|
||||
|
||||
result = date_datetime(dateVal);
|
||||
*result += (((time->hr*60)+time->min)*60+time->sec);
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* datetime_datetime() */
|
||||
|
||||
#endif
|
||||
|
||||
int32 /* RelativeTime */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.13 1997/03/28 07:16:59 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.14 1997/04/02 18:33:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "postgres.h"
|
||||
#include <miscadmin.h>
|
||||
#include "miscadmin.h"
|
||||
#ifdef HAVE_FLOAT_H
|
||||
# include <float.h>
|
||||
#endif
|
||||
@@ -34,6 +34,10 @@
|
||||
#define USE_DATE_CACHE 1
|
||||
|
||||
|
||||
#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
|
||||
|
||||
int mdays[] = {31, 28, 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};
|
||||
|
||||
@@ -55,26 +59,26 @@ datetime_in(char *str)
|
||||
|
||||
double fsec;
|
||||
struct tm tt, *tm = &tt;
|
||||
int tzp;
|
||||
int tz;
|
||||
int dtype;
|
||||
int nf;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN];
|
||||
char lowstr[MAXDATELEN+1];
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
elog(WARN, "Bad (null) datetime external representation", NULL);
|
||||
elog(WARN,"Bad (null) datetime external representation",NULL);
|
||||
|
||||
if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
||||
|| (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
|
||||
|| (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
||||
elog(WARN,"Bad datetime external representation %s",str);
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN, "Memory allocation failed, can't input datetime '%s'",str);
|
||||
elog(WARN,"Memory allocation failed, can't input datetime '%s'",str);
|
||||
|
||||
switch (dtype) {
|
||||
case DTK_DATE:
|
||||
*result = tm2datetime( tm, fsec, tzp);
|
||||
*result = tm2datetime( tm, fsec, &tz);
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime_in- date is %f\n", *result);
|
||||
@@ -103,7 +107,7 @@ printf( "datetime_in- date is %f\n", *result);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(WARN, "Internal coding error, can't input datetime '%s'",str);
|
||||
elog(WARN,"Internal coding error, can't input datetime '%s'",str);
|
||||
};
|
||||
|
||||
return(result);
|
||||
@@ -118,7 +122,7 @@ datetime_out(DateTime *dt)
|
||||
char *result;
|
||||
struct tm tt, *tm = &tt;
|
||||
double fsec;
|
||||
char buf[MAXDATELEN];
|
||||
char buf[MAXDATELEN+1];
|
||||
|
||||
if (!PointerIsValid(dt))
|
||||
return(NULL);
|
||||
@@ -126,7 +130,7 @@ datetime_out(DateTime *dt)
|
||||
if (DATETIME_IS_RESERVED(*dt)) {
|
||||
EncodeSpecialDateTime(*dt, buf);
|
||||
|
||||
} else if (datetime2tm( *dt, tm, &fsec) == 0) {
|
||||
} else if (datetime2tm( *dt, &CTimeZone, tm, &fsec) == 0) {
|
||||
EncodeDateTime(tm, fsec, DateStyle, buf);
|
||||
|
||||
} else {
|
||||
@@ -134,7 +138,7 @@ datetime_out(DateTime *dt)
|
||||
};
|
||||
|
||||
if (!PointerIsValid(result = PALLOC(strlen(buf)+1)))
|
||||
elog(WARN, "Memory allocation failed, can't output datetime", NULL);
|
||||
elog(WARN,"Memory allocation failed, can't output datetime",NULL);
|
||||
|
||||
strcpy( result, buf);
|
||||
|
||||
@@ -159,7 +163,7 @@ timespan_in(char *str)
|
||||
int nf;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN];
|
||||
char lowstr[MAXDATELEN+1];
|
||||
|
||||
tm->tm_year = 0;
|
||||
tm->tm_mon = 0;
|
||||
@@ -170,14 +174,14 @@ timespan_in(char *str)
|
||||
fsec = 0;
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
elog(WARN, "Bad (null) timespan external representation", NULL);
|
||||
elog(WARN,"Bad (null) timespan external representation",NULL);
|
||||
|
||||
if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
||||
|| (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
|
||||
elog(WARN,"Bad timespan external representation %s",str);
|
||||
|
||||
if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN, "Memory allocation failed, can't input timespan '%s'",str);
|
||||
elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
|
||||
|
||||
switch (dtype) {
|
||||
case DTK_DELTA:
|
||||
@@ -189,7 +193,7 @@ timespan_in(char *str)
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(WARN, "Internal coding error, can't input timespan '%s'",str);
|
||||
elog(WARN,"Internal coding error, can't input timespan '%s'",str);
|
||||
};
|
||||
|
||||
return(span);
|
||||
@@ -205,7 +209,7 @@ timespan_out(TimeSpan *span)
|
||||
|
||||
struct tm tt, *tm = &tt;
|
||||
double fsec;
|
||||
char buf[MAXDATELEN];
|
||||
char buf[MAXDATELEN+1];
|
||||
|
||||
if (!PointerIsValid(span))
|
||||
return(NULL);
|
||||
@@ -229,6 +233,26 @@ timespan_out(TimeSpan *span)
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
bool
|
||||
datetime_finite(DateTime *datetime)
|
||||
{
|
||||
if (!PointerIsValid(datetime))
|
||||
return FALSE;
|
||||
|
||||
return(! DATETIME_NOT_FINITE(*datetime));
|
||||
} /* datetime_finite() */
|
||||
|
||||
|
||||
bool
|
||||
timespan_finite(TimeSpan *timespan)
|
||||
{
|
||||
if (!PointerIsValid(timespan))
|
||||
return FALSE;
|
||||
|
||||
return(! TIMESPAN_NOT_FINITE(*timespan));
|
||||
} /* timespan_finite() */
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* Relational operators for datetime.
|
||||
*---------------------------------------------------------*/
|
||||
@@ -267,14 +291,14 @@ SetDateTime( DateTime dt) {
|
||||
|
||||
if (DATETIME_IS_CURRENT(dt)) {
|
||||
GetCurrentTime(&tt);
|
||||
dt = tm2datetime( &tt, 0, 0);
|
||||
dt = tm2datetime( &tt, 0, NULL);
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "SetDateTime- current time is %f\n", dt);
|
||||
#endif
|
||||
} else { /* if (DATETIME_IS_EPOCH(dt1)) */
|
||||
GetEpochTime(&tt);
|
||||
dt = tm2datetime( &tt, 0, 0);
|
||||
dt = tm2datetime( &tt, 0, NULL);
|
||||
#ifdef DATEDEBUG
|
||||
printf( "SetDateTime- epoch time is %f\n", dt);
|
||||
#endif
|
||||
@@ -520,7 +544,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
||||
dt2 = *datetime2;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN, "Memory allocation failed, can't subtract dates",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
|
||||
|
||||
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
||||
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
||||
@@ -538,46 +562,83 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
||||
} /* datetime_sub() */
|
||||
|
||||
|
||||
/* datetime_add_span()
|
||||
* Add a timespan to a datetime data type.
|
||||
* Note that timespan has provisions for qualitative year/month
|
||||
* units, so try to do the right thing with them.
|
||||
* To add a month, increment the month, and use the same day of month.
|
||||
* Then, if the next month has fewer days, set the day of month
|
||||
* to the last day of month.
|
||||
*/
|
||||
DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
|
||||
{
|
||||
DateTime *result;
|
||||
|
||||
#if FALSE
|
||||
double date, time;
|
||||
int year, mon, mday;
|
||||
#endif
|
||||
|
||||
if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN, "Memory allocation failed, can't add dates",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't add dates",NULL);
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "date_add- add %f to %d %f\n", *datetime, span->month, span->time);
|
||||
printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->time);
|
||||
#endif
|
||||
|
||||
*result = *datetime;
|
||||
if (DATETIME_IS_RELATIVE(*result)) *result = SetDateTime(*result);
|
||||
if (DATETIME_NOT_FINITE(*datetime)) {
|
||||
*result = *datetime;
|
||||
|
||||
if (span->month != 0) {
|
||||
time = JROUND(modf( (*result/86400), &date)*86400);
|
||||
date += date2j(2000,1,1);
|
||||
} else if (TIMESPAN_IS_INVALID(*span)) {
|
||||
DATETIME_INVALID(*result);
|
||||
|
||||
j2date( ((int) date), &year, &mon, &mday);
|
||||
mon += span->month;
|
||||
if (mon > 12) {
|
||||
year += mon / 12;
|
||||
mon %= 12;
|
||||
} else if (mon < 0) {
|
||||
year += mon / 12;
|
||||
mon %= 12;
|
||||
year -= 1;
|
||||
mon += 12;
|
||||
} else {
|
||||
*result = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
||||
|
||||
if (span->month != 0) {
|
||||
struct tm tt, *tm = &tt;
|
||||
double fsec;
|
||||
|
||||
if (datetime2tm( *result, NULL, tm, &fsec) == 0) {
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||
#endif
|
||||
tm->tm_mon += span->month;
|
||||
if (tm->tm_mon > 12) {
|
||||
tm->tm_year += (tm->tm_mon / 12);
|
||||
tm->tm_mon = (tm->tm_mon % 12);
|
||||
} else if (tm->tm_mon < 1) {
|
||||
tm->tm_year += ((tm->tm_mon / 12) - 1);
|
||||
tm->tm_mon = ((tm->tm_mon % 12) + 12);
|
||||
};
|
||||
|
||||
/* adjust for end of month boundary problems... */
|
||||
if (tm->tm_mday > mdays[ tm->tm_mon-1]) {
|
||||
if ((tm->tm_mon == 2) && isleap( tm->tm_year)) {
|
||||
tm->tm_mday = (mdays[ tm->tm_mon-1]+1);
|
||||
} else {
|
||||
tm->tm_mday = mdays[ tm->tm_mon-1];
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||
#endif
|
||||
*result = tm2datetime( tm, fsec, NULL);
|
||||
|
||||
} else {
|
||||
DATETIME_INVALID(*result);
|
||||
};
|
||||
};
|
||||
*result += ((date2j( year, mon, mday)-date2j(2000,1,1))*86400);
|
||||
*result += time;
|
||||
};
|
||||
|
||||
*result = JROUND(*result + span->time);
|
||||
#if FALSE
|
||||
*result = JROUND(*result + span->time);
|
||||
#endif
|
||||
*result += span->time;
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* datetime_add_span() */
|
||||
@@ -607,13 +668,13 @@ TimeSpan *timespan_um(TimeSpan *timespan)
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN, "Memory allocation failed, can't subtract dates",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
|
||||
|
||||
result->time = -(timespan->time);
|
||||
result->month = -(timespan->month);
|
||||
|
||||
return(result);
|
||||
} /* datetime_sub() */
|
||||
} /* timespan_um() */
|
||||
|
||||
|
||||
TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
|
||||
@@ -624,7 +685,7 @@ TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN, "Memory allocation failed, can't add timespans",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't add timespans",NULL);
|
||||
|
||||
result->month = (span1->month + span2->month);
|
||||
result->time = JROUND(span1->time + span2->time);
|
||||
@@ -640,7 +701,7 @@ TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2)
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
||||
elog(WARN, "Memory allocation failed, can't subtract timespans",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't subtract timespans",NULL);
|
||||
|
||||
result->month = (span1->month - span2->month);
|
||||
result->time = JROUND(span1->time - span2->time);
|
||||
@@ -654,6 +715,125 @@ TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2)
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
|
||||
/* datetime_text()
|
||||
* Convert datetime to text data type.
|
||||
*/
|
||||
text *
|
||||
datetime_text(DateTime *datetime)
|
||||
{
|
||||
text *result;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
if (!PointerIsValid(datetime))
|
||||
return NULL;
|
||||
|
||||
str = datetime_out(datetime);
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
return NULL;
|
||||
|
||||
len = (strlen(str)+VARHDRSZ);
|
||||
|
||||
if (!PointerIsValid(result = PALLOC(len)))
|
||||
elog(WARN,"Memory allocation failed, can't convert datetime to text",NULL);
|
||||
|
||||
VARSIZE(result) = len;
|
||||
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
||||
|
||||
PFREE(str);
|
||||
|
||||
return(result);
|
||||
} /* datetime_text() */
|
||||
|
||||
|
||||
/* text_datetime()
|
||||
* Convert text string to datetime.
|
||||
* Text type is not null terminated, so use temporary string
|
||||
* then call the standard input routine.
|
||||
*/
|
||||
DateTime *
|
||||
text_datetime(text *str)
|
||||
{
|
||||
DateTime *result;
|
||||
int i;
|
||||
char *sp, *dp, dstr[MAXDATELEN+1];
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
return NULL;
|
||||
|
||||
sp = VARDATA(str);
|
||||
dp = dstr;
|
||||
for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++;
|
||||
*dp = '\0';
|
||||
|
||||
result = datetime_in(dstr);
|
||||
|
||||
return(result);
|
||||
} /* text_datetime() */
|
||||
|
||||
|
||||
/* timespan_text()
|
||||
* Convert timespan to text data type.
|
||||
*/
|
||||
text *
|
||||
timespan_text(TimeSpan *timespan)
|
||||
{
|
||||
text *result;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
if (!PointerIsValid(timespan))
|
||||
return NULL;
|
||||
|
||||
str = timespan_out(timespan);
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
return NULL;
|
||||
|
||||
len = (strlen(str)+VARHDRSZ);
|
||||
|
||||
if (!PointerIsValid(result = PALLOC(len)))
|
||||
elog(WARN,"Memory allocation failed, can't convert timespan to text",NULL);
|
||||
|
||||
VARSIZE(result) = len;
|
||||
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
||||
|
||||
PFREE(str);
|
||||
|
||||
return(result);
|
||||
} /* timespan_text() */
|
||||
|
||||
|
||||
/* text_timespan()
|
||||
* Convert text string to timespan.
|
||||
* Text type may not be null terminated, so copy to temporary string
|
||||
* then call the standard input routine.
|
||||
*/
|
||||
TimeSpan *
|
||||
text_timespan(text *str)
|
||||
{
|
||||
TimeSpan *result;
|
||||
int i;
|
||||
char *sp, *dp, dstr[MAXDATELEN+1];
|
||||
|
||||
if (!PointerIsValid(str))
|
||||
return NULL;
|
||||
|
||||
sp = VARDATA(str);
|
||||
dp = dstr;
|
||||
for (i = 0; i < (VARSIZE(str)-VARHDRSZ); i++) *dp++ = *sp++;
|
||||
*dp = '\0';
|
||||
|
||||
result = timespan_in(dstr);
|
||||
|
||||
return(result);
|
||||
} /* text_timespan() */
|
||||
|
||||
|
||||
/* datetime_part()
|
||||
* Extract specified field from datetime.
|
||||
*/
|
||||
float64
|
||||
datetime_part(text *units, DateTime *datetime)
|
||||
{
|
||||
@@ -662,7 +842,7 @@ datetime_part(text *units, DateTime *datetime)
|
||||
DateTime dt;
|
||||
int type, val;
|
||||
int i;
|
||||
char *up, *lp, lowunits[MAXDATELEN];
|
||||
char *up, *lp, lowunits[MAXDATELEN+1];
|
||||
double fsec;
|
||||
struct tm tt, *tm = &tt;
|
||||
|
||||
@@ -670,7 +850,7 @@ datetime_part(text *units, DateTime *datetime)
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(float64data)))
|
||||
elog(WARN, "Memory allocation failed, can't get date part",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't get date part",NULL);
|
||||
|
||||
up = VARDATA(units);
|
||||
lp = lowunits;
|
||||
@@ -694,7 +874,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
|
||||
|
||||
dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
||||
|
||||
if (datetime2tm( dt, tm, &fsec) == 0) {
|
||||
if (datetime2tm( dt, &CTimeZone, tm, &fsec) == 0) {
|
||||
switch (val) {
|
||||
case DTK_TZ:
|
||||
*result = CTimeZone;
|
||||
@@ -768,6 +948,9 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
|
||||
} /* datetime_part() */
|
||||
|
||||
|
||||
/* timespan_part()
|
||||
* Extract specified field from timespan.
|
||||
*/
|
||||
float64
|
||||
timespan_part(text *units, TimeSpan *timespan)
|
||||
{
|
||||
@@ -775,7 +958,7 @@ timespan_part(text *units, TimeSpan *timespan)
|
||||
|
||||
int type, val;
|
||||
int i;
|
||||
char *up, *lp, lowunits[MAXDATELEN];
|
||||
char *up, *lp, lowunits[MAXDATELEN+1];
|
||||
double fsec;
|
||||
struct tm tt, *tm = &tt;
|
||||
|
||||
@@ -783,7 +966,7 @@ timespan_part(text *units, TimeSpan *timespan)
|
||||
return NULL;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(float64data)))
|
||||
elog(WARN, "Memory allocation failed, can't get date part",NULL);
|
||||
elog(WARN,"Memory allocation failed, can't get date part",NULL);
|
||||
|
||||
up = VARDATA(units);
|
||||
lp = lowunits;
|
||||
@@ -879,10 +1062,6 @@ printf( "timespan_part- units %s type=%d value=%d\n", lowunits, type, val);
|
||||
* PRIVATE ROUTINES *
|
||||
*****************************************************************************/
|
||||
|
||||
#if USE_NEW_TIME_CODE
|
||||
#define DATE_MAXLEN 47
|
||||
#endif
|
||||
|
||||
/* definitions for squeezing values into "value" */
|
||||
#define ABS_SIGNBIT 0200
|
||||
#define VALMASK 0177
|
||||
@@ -1218,11 +1397,12 @@ int j2day( int date)
|
||||
* Also, month is one-based, _not_ zero-based.
|
||||
*/
|
||||
int
|
||||
datetime2tm( DateTime dt, struct tm *tm, double *fsec)
|
||||
datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec)
|
||||
{
|
||||
double date, time, sec;
|
||||
|
||||
time = (modf( dt2local( dt, CTimeZone)/86400, &date)*86400);
|
||||
if (tzp != NULL) dt = dt2local( dt, *tzp);
|
||||
time = (modf( dt/86400, &date)*86400);
|
||||
date += date2j(2000,1,1);
|
||||
if (time < 0) {
|
||||
time += 86400;
|
||||
@@ -1233,7 +1413,8 @@ datetime2tm( DateTime dt, struct tm *tm, double *fsec)
|
||||
if (date < 0) return -1;
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time);
|
||||
printf( "datetime2tm- date is %f (%f %f)\n",
|
||||
((tzp != NULL)? dt2local(dt, -(*tzp)): dt), date, time);
|
||||
#endif
|
||||
|
||||
j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
||||
@@ -1254,8 +1435,8 @@ printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, t
|
||||
tm->tm_isdst = -1;
|
||||
|
||||
#ifdef DATEDEBUG
|
||||
printf( "datetime2tm- timezone is %s; offset is %d; daylight is %d\n",
|
||||
CTZName, CTimeZone, CDayLight);
|
||||
printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
|
||||
CTZName, ((tzp != NULL)? *tzp: 0), CTimeZone, CDayLight);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -1268,7 +1449,7 @@ printf( "datetime2tm- timezone is %s; offset is %d; daylight is %d\n",
|
||||
* Also, month is one-based, _not_ zero-based.
|
||||
*/
|
||||
DateTime
|
||||
tm2datetime( struct tm *tm, double fsec, int tzp) {
|
||||
tm2datetime( struct tm *tm, double fsec, int *tzp) {
|
||||
|
||||
DateTime result;
|
||||
double date, time;
|
||||
@@ -1284,7 +1465,7 @@ tm2datetime( struct tm *tm, double fsec, int tzp) {
|
||||
printf( "tm2datetime- date is %f (%f %f %d)\n", result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
|
||||
printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
|
||||
#endif
|
||||
if (tzp != 0) result = dt2local(result, -tzp);
|
||||
if (tzp != NULL) result = dt2local(result, -(*tzp));
|
||||
|
||||
return(result);
|
||||
} /* tm2datetime() */
|
||||
@@ -1832,40 +2013,17 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm *tm)
|
||||
|
||||
*tmask = 0;
|
||||
|
||||
/* look first for text fields, since that will be unambiguous month */
|
||||
for (i = 0; i < nf; i++) {
|
||||
str = field[i];
|
||||
len = strlen(str);
|
||||
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
if (isdigit(*str)) {
|
||||
if (DecodeNumber( len, str, fmask, &dmask, tm, &fsec) != 0)
|
||||
return -1;
|
||||
|
||||
} else if (isalpha(*str)) {
|
||||
if (isalpha(*field[i])) {
|
||||
type = DecodeSpecial( i, field[i], &val);
|
||||
if (type == IGNORE) continue;
|
||||
|
||||
dmask = DTK_M(type);
|
||||
switch (type) {
|
||||
case YEAR:
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeDate- year field %s value is %d\n", field[i], val);
|
||||
#endif
|
||||
tm->tm_mon = val;
|
||||
break;
|
||||
|
||||
case MONTH:
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeDate- month field %s value is %d\n", field[i], val);
|
||||
#endif
|
||||
tm->tm_mon = val;
|
||||
break;
|
||||
|
||||
case DAY:
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeDate- month field %s value is %d\n", field[i], val);
|
||||
#endif
|
||||
tm->tm_mon = val;
|
||||
break;
|
||||
@@ -1876,7 +2034,25 @@ printf( "DecodeDate- illegal field %s value is %d\n", field[i], val);
|
||||
#endif
|
||||
return -1;
|
||||
};
|
||||
if (fmask & dmask) return -1;
|
||||
|
||||
fmask |= dmask;
|
||||
*tmask |= dmask;
|
||||
|
||||
/* mark this field as being completed */
|
||||
field[i] = NULL;
|
||||
};
|
||||
};
|
||||
|
||||
/* now pick up remaining numeric fields */
|
||||
for (i = 0; i < nf; i++) {
|
||||
if (field[i] == NULL) continue;
|
||||
|
||||
if ((len = strlen(field[i])) <= 0)
|
||||
return -1;
|
||||
|
||||
if (DecodeNumber( len, field[i], fmask, &dmask, tm, &fsec) != 0)
|
||||
return -1;
|
||||
|
||||
if (fmask & dmask) return -1;
|
||||
|
||||
@@ -1955,6 +2131,19 @@ printf( "DecodeNumber- %s is %d fmask=%08x tmask=%08x\n", str, val, fmask, *tmas
|
||||
printf( "DecodeNumber- match %d (%s) as year\n", val, str);
|
||||
#endif
|
||||
*tmask = DTK_M(YEAR);
|
||||
|
||||
/* already have a year? then see if we can substitute... */
|
||||
if (fmask & DTK_M(YEAR)) {
|
||||
if ((!(fmask & DTK_M(DAY)))
|
||||
&& ((tm->tm_year >= 1) && (tm->tm_year <= 31))) {
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeNumber- misidentified year previously; swap with day %d\n", tm->tm_mday);
|
||||
#endif
|
||||
tm->tm_mday = tm->tm_year;
|
||||
*tmask = DTK_M(DAY);
|
||||
};
|
||||
};
|
||||
|
||||
tm->tm_year = val;
|
||||
|
||||
/* special case day of year? */
|
||||
@@ -1966,7 +2155,7 @@ printf( "DecodeNumber- match %d (%s) as year\n", val, str);
|
||||
&tm->tm_year,&tm->tm_mon,&tm->tm_mday);
|
||||
|
||||
/* already have year? then could be month */
|
||||
} else if ((fmask && DTK_M(YEAR)) && (! (fmask & DTK_M(MONTH)))
|
||||
} else if ((fmask & DTK_M(YEAR)) && (! (fmask & DTK_M(MONTH)))
|
||||
&& ((val >= 1) && (val <= 12))) {
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeNumber- match %d (%s) as month\n", val, str);
|
||||
@@ -1975,11 +2164,7 @@ printf( "DecodeNumber- match %d (%s) as month\n", val, str);
|
||||
tm->tm_mon = val;
|
||||
|
||||
/* no year and EuroDates enabled? then could be day */
|
||||
#if USE_EURODATES
|
||||
} else if ((EuroDates || (fmask & DTK_M(MONTH)))
|
||||
#else
|
||||
} else if ((fmask & DTK_M(MONTH))
|
||||
#endif
|
||||
&& (! ((fmask & DTK_M(YEAR)) && (fmask & DTK_M(DAY))))
|
||||
&& ((val >= 1) && (val <= 31))) {
|
||||
#ifdef DATEDEBUG
|
||||
@@ -1996,6 +2181,14 @@ printf( "DecodeNumber- (2) match %d (%s) as month\n", val, str);
|
||||
*tmask = DTK_M(MONTH);
|
||||
tm->tm_mon = val;
|
||||
|
||||
} else if ((! (fmask & DTK_M(DAY)))
|
||||
&& ((val >= 1) && (val <= 31))) {
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeNumber- (2) match %d (%s) as day\n", val, str);
|
||||
#endif
|
||||
*tmask = DTK_M(DAY);
|
||||
tm->tm_mday = val;
|
||||
|
||||
} else if (! (fmask & DTK_M(YEAR))) {
|
||||
#ifdef DATEDEBUG
|
||||
printf( "DecodeNumber- (2) match %d (%s) as year\n", val, str);
|
||||
@@ -2467,7 +2660,7 @@ int EncodeDateTime(struct tm *tm, double fsec, int style, char *str)
|
||||
int day, hour, min;
|
||||
double sec;
|
||||
#ifdef DATEDEBUG
|
||||
char buf[MAXDATELEN];
|
||||
char buf[MAXDATELEN+1];
|
||||
#endif
|
||||
|
||||
sec = (tm->tm_sec + fsec);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.21 1997/03/28 07:12:53 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.22 1997/04/02 18:33:50 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -27,6 +27,7 @@
|
||||
#ifndef USE_POSIX_TIME
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
#include "utils/builtins.h"
|
||||
#include "access/xact.h"
|
||||
|
||||
|
||||
@@ -90,11 +91,19 @@ printf( "GetCurrentAbsoluteTime- timezone is %s -> %d seconds from UTC\n",
|
||||
void
|
||||
GetCurrentTime(struct tm *tm)
|
||||
{
|
||||
time_t now;
|
||||
abstime2tm( GetCurrentTransactionStartTime(), &CTimeZone, tm);
|
||||
|
||||
return;
|
||||
} /* GetCurrentTime() */
|
||||
|
||||
|
||||
void
|
||||
abstime2tm(AbsoluteTime time, int *tzp, struct tm *tm)
|
||||
{
|
||||
struct tm *tt;
|
||||
|
||||
now = GetCurrentTransactionStartTime()-CTimeZone;
|
||||
tt = gmtime( &now);
|
||||
if (tzp != NULL) time -= *tzp;
|
||||
tt = gmtime((time_t *) &time);
|
||||
|
||||
tm->tm_year = tt->tm_year+1900;
|
||||
tm->tm_mon = tt->tm_mon+1;
|
||||
@@ -105,11 +114,13 @@ GetCurrentTime(struct tm *tm)
|
||||
tm->tm_isdst = tt->tm_isdst;
|
||||
|
||||
return;
|
||||
} /* GetCurrentTime() */
|
||||
} /* abstime2tm() */
|
||||
|
||||
|
||||
AbsoluteTime tm2abstime( struct tm *tm, int tz);
|
||||
|
||||
/* tm2abstime()
|
||||
* Convert a tm structure to abstime.
|
||||
* Note that tm has full year (not 1900-based) and 1-based month.
|
||||
*/
|
||||
AbsoluteTime
|
||||
tm2abstime( struct tm *tm, int tz)
|
||||
{
|
||||
@@ -122,13 +133,13 @@ tm2abstime( struct tm *tm, int tz)
|
||||
|| tm->tm_hour < 0 || tm->tm_hour >= 24
|
||||
|| tm->tm_min < 0 || tm->tm_min > 59
|
||||
|| tm->tm_sec < 0 || tm->tm_sec > 59)
|
||||
return INVALID_ABSTIME;
|
||||
return(INVALID_ABSTIME);
|
||||
|
||||
day = (date2j( tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j( 1970, 1, 1));
|
||||
|
||||
/* check for time out of range */
|
||||
if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM))
|
||||
return INVALID_ABSTIME;
|
||||
return(INVALID_ABSTIME);
|
||||
|
||||
/* convert to seconds */
|
||||
sec = tm->tm_sec + tz + (tm->tm_min +(day*24 + tm->tm_hour)*60)*60;
|
||||
@@ -136,7 +147,7 @@ tm2abstime( struct tm *tm, int tz)
|
||||
/* check for overflow */
|
||||
if ((day == MAX_DAYNUM && sec < 0) ||
|
||||
(day == MIN_DAYNUM && sec > 0))
|
||||
return INVALID_ABSTIME;
|
||||
return(INVALID_ABSTIME);
|
||||
|
||||
/* daylight correction */
|
||||
if (tm->tm_isdst < 0) { /* unknown; find out */
|
||||
@@ -147,7 +158,7 @@ tm2abstime( struct tm *tm, int tz)
|
||||
|
||||
/* check for reserved values (e.g. "current" on edge of usual range */
|
||||
if (!AbsoluteTimeIsReal(sec))
|
||||
return INVALID_ABSTIME;
|
||||
return(INVALID_ABSTIME);
|
||||
|
||||
return sec;
|
||||
} /* tm2abstime() */
|
||||
@@ -369,6 +380,16 @@ AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
|
||||
}
|
||||
|
||||
|
||||
/* abstime_finite()
|
||||
*/
|
||||
bool
|
||||
abstime_finite(AbsoluteTime abstime)
|
||||
{
|
||||
return((abstime != INVALID_ABSTIME)
|
||||
&& (abstime != NOSTART_ABSTIME) && (abstime != NOEND_ABSTIME));
|
||||
} /* abstime_datetime() */
|
||||
|
||||
|
||||
/*
|
||||
* abstimeeq - returns 1, iff arguments are equal
|
||||
* abstimene - returns 1, iff arguments are not equal
|
||||
@@ -381,7 +402,7 @@ bool
|
||||
abstimeeq(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -394,7 +415,7 @@ bool
|
||||
abstimene(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -407,7 +428,7 @@ bool
|
||||
abstimelt(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -420,7 +441,7 @@ bool
|
||||
abstimegt(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -433,7 +454,7 @@ bool
|
||||
abstimele(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -446,7 +467,7 @@ bool
|
||||
abstimege(AbsoluteTime t1, AbsoluteTime t2)
|
||||
{
|
||||
if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
|
||||
return 0;
|
||||
return(FALSE);
|
||||
if (t1 == CURRENT_ABSTIME)
|
||||
t1 = GetCurrentTransactionStartTime();
|
||||
if (t2 == CURRENT_ABSTIME)
|
||||
@@ -455,6 +476,7 @@ abstimege(AbsoluteTime t1, AbsoluteTime t2)
|
||||
return(t1 >= t2);
|
||||
}
|
||||
|
||||
|
||||
/* datetime_abstime()
|
||||
* Convert datetime to abstime.
|
||||
*/
|
||||
@@ -480,10 +502,10 @@ datetime_abstime(DateTime *datetime)
|
||||
|
||||
} else {
|
||||
if (DATETIME_IS_RELATIVE(*datetime)) {
|
||||
datetime2tm( SetDateTime(*datetime), tm, &fsec);
|
||||
datetime2tm( SetDateTime(*datetime), &CTimeZone, tm, &fsec);
|
||||
result = tm2abstime( tm, 0);
|
||||
|
||||
} else if (datetime2tm( *datetime, tm, &fsec) == 0) {
|
||||
} else if (datetime2tm( *datetime, &CTimeZone, tm, &fsec) == 0) {
|
||||
result = tm2abstime( tm, 0);
|
||||
|
||||
} else {
|
||||
@@ -493,3 +515,42 @@ datetime_abstime(DateTime *datetime)
|
||||
|
||||
return(result);
|
||||
} /* datetime_abstime() */
|
||||
|
||||
/* abstime_datetime()
|
||||
* Convert datetime to abstime.
|
||||
*/
|
||||
DateTime *
|
||||
abstime_datetime(AbsoluteTime abstime)
|
||||
{
|
||||
DateTime *result;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Unable to allocate space to convert abstime to datetime",NULL);
|
||||
|
||||
switch (abstime) {
|
||||
case INVALID_ABSTIME:
|
||||
DATETIME_INVALID(*result);
|
||||
break;
|
||||
|
||||
case NOSTART_ABSTIME:
|
||||
DATETIME_NOBEGIN(*result);
|
||||
break;
|
||||
|
||||
case NOEND_ABSTIME:
|
||||
DATETIME_NOEND(*result);
|
||||
break;
|
||||
|
||||
case EPOCH_ABSTIME:
|
||||
DATETIME_EPOCH(*result);
|
||||
break;
|
||||
|
||||
case CURRENT_ABSTIME:
|
||||
DATETIME_CURRENT(*result);
|
||||
break;
|
||||
|
||||
default:
|
||||
*result = abstime + ((date2j( 1970, 1, 1) - date2j( 2000, 1, 1))*86400);
|
||||
};
|
||||
|
||||
return(result);
|
||||
} /* abstime_datetime() */
|
||||
|
||||
@@ -88,3 +88,23 @@ timestampge(time_t t1, time_t t2)
|
||||
{
|
||||
return difftime(t1, t2) <= 0;
|
||||
}
|
||||
|
||||
DateTime *
|
||||
timestamp_datetime(time_t timestamp)
|
||||
{
|
||||
DateTime *result;
|
||||
|
||||
double fsec = 0;
|
||||
struct tm *tm;
|
||||
|
||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
||||
elog(WARN,"Memory allocation failed, can't convert timestamp to datetime",NULL);
|
||||
|
||||
tm = localtime((time_t *) ×tamp);
|
||||
tm->tm_year += 1900;
|
||||
tm->tm_mon += 1;
|
||||
|
||||
*result = tm2datetime(tm, fsec, NULL);
|
||||
|
||||
return(result);
|
||||
} /* timestamp_datetime() */
|
||||
|
||||
Reference in New Issue
Block a user