1996-07-09 06:22:35 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* dt.c--
|
1997-09-07 05:04:48 +00:00
|
|
|
* Functions for the built-in type "dt".
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1997-09-08 21:56:23 +00:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.40 1997/09/08 21:48:23 momjian Exp $
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1997-03-14 23:21:12 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
1997-03-16 05:32:03 +00:00
|
|
|
#include <errno.h>
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1996-11-03 06:54:38 +00:00
|
|
|
#include "postgres.h"
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#include "miscadmin.h"
|
1997-03-25 20:00:52 +00:00
|
|
|
#ifdef HAVE_FLOAT_H
|
1997-09-07 05:04:48 +00:00
|
|
|
#include <float.h>
|
1997-03-25 20:00:52 +00:00
|
|
|
#endif
|
1997-03-28 06:53:50 +00:00
|
|
|
#ifdef HAVE_LIMITS_H
|
1997-09-07 05:04:48 +00:00
|
|
|
#include <limits.h>
|
1997-03-28 06:53:50 +00:00
|
|
|
#endif
|
1997-03-18 16:36:50 +00:00
|
|
|
#ifndef USE_POSIX_TIME
|
|
|
|
#include <sys/timeb.h>
|
|
|
|
#endif
|
1997-03-14 23:21:12 +00:00
|
|
|
#include "utils/builtins.h"
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
|
1997-09-07 05:04:48 +00:00
|
|
|
static int
|
|
|
|
DecodeNumber(int flen, char *field,
|
|
|
|
int fmask, int *tmask, struct tm * tm, double *fsec);
|
|
|
|
static int
|
|
|
|
DecodeNumberField(int len, char *str,
|
|
|
|
int fmask, int *tmask, struct tm * tm, double *fsec);
|
1997-09-08 02:41:22 +00:00
|
|
|
static int DecodeSpecial(int field, char *lowtoken, int *val);
|
1997-09-07 05:04:48 +00:00
|
|
|
static int
|
|
|
|
DecodeTime(char *str, int fmask, int *tmask,
|
|
|
|
struct tm * tm, double *fsec);
|
1997-09-08 02:41:22 +00:00
|
|
|
static int DecodeTimezone(char *str, int *tzp);
|
|
|
|
static int DecodeUnits(int field, char *lowtoken, int *val);
|
|
|
|
static int EncodeSpecialDateTime(DateTime dt, char *str);
|
1997-09-08 21:56:23 +00:00
|
|
|
static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
|
1997-09-07 05:04:48 +00:00
|
|
|
static DateTime dt2local(DateTime dt, int timezone);
|
1997-09-08 02:41:22 +00:00
|
|
|
static void dt2time(DateTime dt, int *hour, int *min, double *sec);
|
|
|
|
static int j2day(int jd);
|
1997-09-08 21:56:23 +00:00
|
|
|
static int timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec);
|
|
|
|
static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span);
|
1997-08-19 21:40:56 +00:00
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
#define USE_DATE_CACHE 1
|
1997-05-11 15:11:47 +00:00
|
|
|
#define ROUND_ALL 0
|
1997-03-14 23:21:12 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
1997-09-07 05:04:48 +00:00
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
|
1997-09-07 05:04:48 +00:00
|
|
|
"Thursday", "Friday", "Saturday", NULL};
|
1996-07-09 06:22:35 +00:00
|
|
|
|
1997-05-30 15:02:51 +00:00
|
|
|
/* TMODULO()
|
|
|
|
* Macro to replace modf(), which is broken on some platforms.
|
|
|
|
*/
|
|
|
|
#define TMODULO(t,q,u) {q = ((t < 0)? ceil(t / u): floor(t / u)); \
|
1997-09-07 05:04:48 +00:00
|
|
|
if (q != 0) t -= rint(q * u);}
|
1997-06-20 17:12:54 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
static void GetEpochTime(struct tm * tm);
|
1997-06-20 17:12:54 +00:00
|
|
|
|
|
|
|
#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))))))
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* USER I/O ROUTINES *
|
1996-07-09 06:22:35 +00:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
/* datetime_in()
|
|
|
|
* Convert a string to internal form.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-03-14 23:21:12 +00:00
|
|
|
datetime_in(char *str)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
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];
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
elog(WARN, "Bad (null) datetime external representation", NULL);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|
|
|
|
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
|
|
|
elog(WARN, "Bad datetime external representation %s", str);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(DateTime);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
switch (dtype)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DATE:
|
|
|
|
if (tm2datetime(tm, fsec, &tz, result) != 0)
|
|
|
|
elog(WARN, "Datetime out of range %s", str);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("datetime_in- date is %f\n", *result);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_EPOCH:
|
|
|
|
DATETIME_EPOCH(*result);
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_CURRENT:
|
|
|
|
DATETIME_CURRENT(*result);
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_LATE:
|
|
|
|
DATETIME_NOEND(*result);
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_EARLY:
|
|
|
|
DATETIME_NOBEGIN(*result);
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_INVALID:
|
|
|
|
DATETIME_INVALID(*result);
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Internal coding error, can't input datetime '%s'", str);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_in() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
/* datetime_out()
|
|
|
|
* Convert a datetime to external form.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
char *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_out(DateTime *dt)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
char *result;
|
|
|
|
int tz;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
double fsec;
|
|
|
|
char *tzn;
|
|
|
|
char buf[MAXDATELEN + 1];
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(dt))
|
|
|
|
return (NULL);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RESERVED(*dt))
|
|
|
|
{
|
|
|
|
EncodeSpecialDateTime(*dt, buf);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) == 0)
|
|
|
|
{
|
|
|
|
EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EncodeSpecialDateTime(DT_INVALID, buf);
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOC(strlen(buf) + 1);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
strcpy(result, buf);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_out() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* timespan_in()
|
|
|
|
* Convert a string to internal form.
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1997-03-14 23:21:12 +00:00
|
|
|
* External format(s):
|
1997-09-07 05:04:48 +00:00
|
|
|
* Uses the generic date/time parsing and decoding routines.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-03-14 23:21:12 +00:00
|
|
|
timespan_in(char *str)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *span;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
double fsec;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
int dtype;
|
|
|
|
int nf;
|
|
|
|
char *field[MAXDATEFIELDS];
|
|
|
|
int ftype[MAXDATEFIELDS];
|
|
|
|
char lowstr[MAXDATELEN + 1];
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
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;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
elog(WARN, "Bad (null) timespan external representation", NULL);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
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);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span = PALLOCTYPE(TimeSpan);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
switch (dtype)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DELTA:
|
|
|
|
if (tm2timespan(tm, fsec, span) != 0)
|
|
|
|
{
|
1997-03-25 08:11:24 +00:00
|
|
|
#if FALSE
|
1997-09-08 02:41:22 +00:00
|
|
|
TIMESPAN_INVALID(span);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
elog(WARN, "Bad timespan external representation %s", str);
|
|
|
|
}
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Internal coding error, can't input timespan '%s'", str);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (span);
|
|
|
|
} /* timespan_in() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
/* timespan_out()
|
|
|
|
* Convert a time span to external form.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
char *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_out(TimeSpan *span)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
char *result;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
double fsec;
|
|
|
|
char buf[MAXDATELEN + 1];
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(span))
|
|
|
|
return (NULL);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (timespan2tm(*span, tm, &fsec) != 0)
|
|
|
|
return (NULL);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
|
|
|
|
elog(WARN, "Unable to format timespan", NULL);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOC(strlen(buf) + 1);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
strcpy(result, buf);
|
|
|
|
return (result);
|
|
|
|
} /* timespan_out() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* PUBLIC ROUTINES *
|
1997-03-25 08:11:24 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_finite(DateTime *datetime)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime))
|
|
|
|
return FALSE;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (!DATETIME_NOT_FINITE(*datetime));
|
|
|
|
} /* datetime_finite() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
#ifdef NOT_USED
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_finite(TimeSpan *timespan)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return (!TIMESPAN_NOT_FINITE(*timespan));
|
|
|
|
} /* timespan_finite() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
#endif
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-03-25 08:11:24 +00:00
|
|
|
/*----------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* Relational operators for datetime.
|
1997-03-25 08:11:24 +00:00
|
|
|
*---------------------------------------------------------*/
|
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
static void
|
1997-09-07 05:04:48 +00:00
|
|
|
GetEpochTime(struct tm * tm)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm *t0;
|
|
|
|
time_t epoch = 0;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
t0 = gmtime(&epoch);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
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;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_year < 1900)
|
|
|
|
tm->tm_year += 1900;
|
|
|
|
tm->tm_mon++;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
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);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return;
|
|
|
|
} /* GetEpochTime() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
DateTime
|
1997-09-07 05:04:48 +00:00
|
|
|
SetDateTime(DateTime dt)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm tt;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_CURRENT(dt))
|
|
|
|
{
|
|
|
|
GetCurrentTime(&tt);
|
|
|
|
tm2datetime(&tt, 0, NULL, &dt);
|
|
|
|
dt = dt2local(dt, -CTimeZone);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("SetDateTime- current time is %f\n", dt);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* if (DATETIME_IS_EPOCH(dt1)) */
|
|
|
|
GetEpochTime(&tt);
|
|
|
|
tm2datetime(&tt, 0, NULL, &dt);
|
1997-03-25 08:11:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("SetDateTime- epoch time is %f\n", dt);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt);
|
|
|
|
} /* SetDateTime() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* datetime_relop - is datetime1 relop datetime2
|
1997-03-25 08:11:24 +00:00
|
|
|
*/
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_eq(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 == dt2);
|
|
|
|
} /* datetime_eq() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_ne(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 != dt2);
|
|
|
|
} /* datetime_ne() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_lt(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 < dt2);
|
|
|
|
} /* datetime_lt() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_gt(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime_gt- %f %s greater than %f\n", dt1, ((dt1 > dt2) ? "is" : "is not"), dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 > dt2);
|
|
|
|
} /* datetime_gt() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_le(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 <= dt2);
|
|
|
|
} /* datetime_le() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_ge(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (dt1 >= dt2);
|
|
|
|
} /* datetime_ge() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* datetime_cmp - 3-state comparison for datetime
|
|
|
|
* collate invalid datetime at the end
|
1997-09-04 18:43:59 +00:00
|
|
|
*/
|
|
|
|
int
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_cmp(DateTime *datetime1, DateTime *datetime2)
|
1997-09-04 18:43:59 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return 0;
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1))
|
|
|
|
{
|
|
|
|
return ((DATETIME_IS_INVALID(dt2) ? 0 : 1));
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (DATETIME_IS_INVALID(dt2))
|
|
|
|
{
|
|
|
|
return (-1);
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
|
|
|
}
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0)));
|
|
|
|
} /* datetime_cmp() */
|
1997-09-04 18:43:59 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* timespan_relop - is timespan1 relop timespan2
|
1997-03-25 08:11:24 +00:00
|
|
|
*/
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_eq(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return ((timespan1->time == timespan2->time)
|
|
|
|
&& (timespan1->month == timespan2->month));
|
|
|
|
} /* timespan_eq() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_ne(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-04-27 02:58:38 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return ((timespan1->time != timespan2->time)
|
|
|
|
|| (timespan1->month != timespan2->month));
|
|
|
|
} /* timespan_ne() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_lt(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-04-27 02:58:38 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (span1 < span2);
|
|
|
|
} /* timespan_lt() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_gt(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-04-27 02:58:38 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (span1 > span2);
|
|
|
|
} /* timespan_gt() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_le(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-04-27 02:58:38 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (span1 <= span2);
|
|
|
|
} /* timespan_le() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_ge(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return FALSE;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
return FALSE;
|
1997-04-27 02:58:38 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (span1 >= span2);
|
|
|
|
} /* timespan_ge() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* timespan_cmp - 3-state comparison for timespan
|
1997-09-04 18:43:59 +00:00
|
|
|
*/
|
|
|
|
int
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_cmp(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-09-04 18:43:59 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return 0;
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1))
|
|
|
|
{
|
|
|
|
return (TIMESPAN_IS_INVALID(*timespan2) ? 0 : 1);
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
{
|
|
|
|
return (-1);
|
|
|
|
}
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-09-04 18:43:59 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);
|
|
|
|
} /* timespan_cmp() */
|
1997-09-04 18:43:59 +00:00
|
|
|
|
|
|
|
|
1997-03-25 08:11:24 +00:00
|
|
|
/*----------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* "Arithmetic" operators on date/times.
|
|
|
|
* datetime_foo returns foo as an object (pointer) that
|
|
|
|
* can be passed between languages.
|
|
|
|
* datetime_xx is an internal routine which returns the
|
|
|
|
* actual value.
|
1997-03-25 08:11:24 +00:00
|
|
|
*---------------------------------------------------------*/
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_smaller(DateTime *datetime1, DateTime *datetime2)
|
1997-04-27 19:20:16 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return NULL;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(DateTime);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1))
|
|
|
|
{
|
|
|
|
*result = dt2;
|
|
|
|
}
|
|
|
|
else if (DATETIME_IS_INVALID(dt2))
|
|
|
|
{
|
|
|
|
*result = dt1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*result = ((dt2 < dt1) ? dt2 : dt1);
|
|
|
|
}
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_smaller() */
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_larger(DateTime *datetime1, DateTime *datetime2)
|
1997-04-27 19:20:16 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return NULL;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(DateTime);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1))
|
|
|
|
{
|
|
|
|
*result = dt2;
|
|
|
|
}
|
|
|
|
else if (DATETIME_IS_INVALID(dt2))
|
|
|
|
{
|
|
|
|
*result = dt1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*result = ((dt2 > dt1) ? dt2 : dt1);
|
|
|
|
}
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_larger() */
|
1997-04-27 19:20:16 +00:00
|
|
|
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_mi(DateTime *datetime1, DateTime *datetime2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-01 06:13:21 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime_mi- evaluate %f - %f\n", dt1, dt2);
|
1997-09-01 06:13:21 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_INVALID(dt1)
|
|
|
|
|| DATETIME_IS_INVALID(dt2))
|
|
|
|
{
|
|
|
|
DATETIME_INVALID(result->time);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->time = JROUND(dt1 - dt2);
|
|
|
|
}
|
|
|
|
result->month = 0;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_mi() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-08-21 23:57:00 +00:00
|
|
|
/* datetime_pl_span()
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
* Add a timespan to a datetime data type.
|
|
|
|
* Note that timespan has provisions for qualitative year/month
|
1997-09-07 05:04:48 +00:00
|
|
|
* units, so try to do the right thing with them.
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
* 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
|
1997-09-07 05:04:48 +00:00
|
|
|
* to the last day of month.
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_pl_span(DateTime *datetime, TimeSpan *span)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
|
|
|
DateTime dt;
|
|
|
|
int tz;
|
|
|
|
char *tzn;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(DateTime);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime_pl_span- add %f to %d %f\n", *datetime, span->month, span->time);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_NOT_FINITE(*datetime))
|
|
|
|
{
|
|
|
|
*result = *datetime;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (TIMESPAN_IS_INVALID(*span))
|
|
|
|
{
|
|
|
|
DATETIME_INVALID(*result);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
|
1997-06-20 17:12:54 +00:00
|
|
|
|
|
|
|
#ifdef ROUND_ALL
|
1997-09-07 05:04:48 +00:00
|
|
|
dt = JROUND(dt + span->time);
|
1997-06-20 17:12:54 +00:00
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
dt += span->time;
|
1997-06-20 17:12:54 +00:00
|
|
|
#endif
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (span->month != 0)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
double fsec;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0)
|
|
|
|
{
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime_pl_span- date was %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);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_mon += span->month;
|
|
|
|
if (tm->tm_mon > 12)
|
|
|
|
{
|
|
|
|
tm->tm_year += ((tm->tm_mon - 1) / 12);
|
|
|
|
tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1);
|
|
|
|
}
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
1997-07-01 00:22:46 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime_pl_span- date becomes %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);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm2datetime(tm, fsec, &tz, &dt) != 0)
|
|
|
|
elog(WARN, "Unable to add datetime and timespan", NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DATETIME_INVALID(dt);
|
|
|
|
}
|
|
|
|
}
|
1997-05-13 04:26:07 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*result = dt;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_pl_span() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_mi_span(DateTime *datetime, TimeSpan *span)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
|
|
|
TimeSpan tspan;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime) || !PointerIsValid(span))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tspan.month = -span->month;
|
|
|
|
tspan.time = -span->time;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = datetime_pl_span(datetime, &tspan);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_mi_span() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_um(TimeSpan *timespan)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result->time = -(timespan->time);
|
|
|
|
result->month = -(timespan->month);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_um() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-04-27 19:20:16 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return NULL;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1))
|
|
|
|
{
|
|
|
|
result->time = timespan2->time;
|
|
|
|
result->month = timespan2->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
{
|
|
|
|
result->time = timespan1->time;
|
|
|
|
result->month = timespan1->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-04-27 19:20:16 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("timespan_smaller- months %d %d times %f %f spans %f %f\n",
|
|
|
|
timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2);
|
1997-04-27 19:20:16 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (span2 < span1)
|
|
|
|
{
|
|
|
|
result->time = timespan2->time;
|
|
|
|
result->month = timespan2->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->time = timespan1->time;
|
|
|
|
result->month = timespan1->month;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_smaller() */
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
|
1997-04-27 19:20:16 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
double span1,
|
|
|
|
span2;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
|
|
|
return NULL;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan1))
|
|
|
|
{
|
|
|
|
result->time = timespan2->time;
|
|
|
|
result->month = timespan2->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (TIMESPAN_IS_INVALID(*timespan2))
|
|
|
|
{
|
|
|
|
result->time = timespan1->time;
|
|
|
|
result->month = timespan1->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
span1 = timespan1->time;
|
|
|
|
if (timespan1->month != 0)
|
|
|
|
span1 += (timespan1->month * (30.0 * 86400));
|
|
|
|
span2 = timespan2->time;
|
|
|
|
if (timespan2->month != 0)
|
|
|
|
span2 += (timespan2->month * (30.0 * 86400));
|
1997-04-27 19:20:16 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("timespan_larger- months %d %d times %f %f spans %f %f\n",
|
|
|
|
timespan1->month, timespan2->month, timespan1->time, timespan2->time, span1, span2);
|
1997-04-27 19:20:16 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (span2 > span1)
|
|
|
|
{
|
|
|
|
result->time = timespan2->time;
|
|
|
|
result->month = timespan2->month;
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->time = timespan1->time;
|
|
|
|
result->month = timespan1->month;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-04-27 19:20:16 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_larger() */
|
1997-04-27 19:20:16 +00:00
|
|
|
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_pl(TimeSpan *span1, TimeSpan *span2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result->month = (span1->month + span2->month);
|
|
|
|
result->time = JROUND(span1->time + span2->time);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_pl() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_mi(TimeSpan *span1, TimeSpan *span2)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
|
|
|
return NULL;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOCTYPE(TimeSpan);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result->month = (span1->month - span2->month);
|
|
|
|
result->time = JROUND(span1->time - span2->time);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_mi() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_div(TimeSpan *span1, float8 *arg2)
|
1997-08-21 23:57:00 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
1997-08-21 23:57:00 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((!PointerIsValid(span1)) || (!PointerIsValid(arg2)))
|
|
|
|
return NULL;
|
1997-08-21 23:57:00 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
|
|
|
elog(WARN, "Memory allocation failed, can't subtract timespans", NULL);
|
1997-08-21 23:57:00 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (*arg2 == 0.0)
|
|
|
|
elog(WARN, "timespan_div: divide by 0.0 error");
|
1997-08-21 23:57:00 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result->month = rint(span1->month / *arg2);
|
|
|
|
result->time = JROUND(span1->time / *arg2);
|
1997-08-21 23:57:00 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_div() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-07-01 00:22:46 +00:00
|
|
|
/* datetime_age()
|
|
|
|
* Calculate time difference while retaining year/month fields.
|
|
|
|
* Note that this does not result in an accurate absolute time span
|
1997-09-07 05:04:48 +00:00
|
|
|
* since year and month are out of context once the arithmetic
|
|
|
|
* is done.
|
1997-07-01 00:22:46 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_age(DateTime *datetime1, DateTime *datetime2)
|
1997-07-01 00:22:46 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
|
|
|
|
|
|
|
DateTime dt1,
|
|
|
|
dt2;
|
|
|
|
double fsec,
|
|
|
|
fsec1,
|
|
|
|
fsec2;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
struct tm tt1,
|
|
|
|
*tm1 = &tt1;
|
|
|
|
struct tm tt2,
|
|
|
|
*tm2 = &tt2;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = PALLOCTYPE(TimeSpan);
|
|
|
|
|
|
|
|
dt1 = *datetime1;
|
|
|
|
dt2 = *datetime2;
|
|
|
|
|
|
|
|
if (DATETIME_IS_RELATIVE(dt1))
|
|
|
|
dt1 = SetDateTime(dt1);
|
|
|
|
if (DATETIME_IS_RELATIVE(dt2))
|
|
|
|
dt2 = SetDateTime(dt2);
|
|
|
|
|
|
|
|
if (DATETIME_IS_INVALID(dt1)
|
|
|
|
|| DATETIME_IS_INVALID(dt2))
|
|
|
|
{
|
|
|
|
DATETIME_INVALID(result->time);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else if ((datetime2tm(dt1, NULL, tm1, &fsec1, NULL) == 0)
|
|
|
|
&& (datetime2tm(dt2, NULL, tm2, &fsec2, NULL) == 0))
|
|
|
|
{
|
|
|
|
fsec = (fsec1 - fsec2);
|
|
|
|
tm->tm_sec = (tm1->tm_sec - tm2->tm_sec);
|
|
|
|
tm->tm_min = (tm1->tm_min - tm2->tm_min);
|
|
|
|
tm->tm_hour = (tm1->tm_hour - tm2->tm_hour);
|
|
|
|
tm->tm_mday = (tm1->tm_mday - tm2->tm_mday);
|
|
|
|
tm->tm_mon = (tm1->tm_mon - tm2->tm_mon);
|
|
|
|
tm->tm_year = (tm1->tm_year - tm2->tm_year);
|
|
|
|
|
|
|
|
/* flip sign if necessary... */
|
|
|
|
if (dt1 < dt2)
|
|
|
|
{
|
|
|
|
fsec = -fsec;
|
|
|
|
tm->tm_sec = -tm->tm_sec;
|
|
|
|
tm->tm_min = -tm->tm_min;
|
|
|
|
tm->tm_hour = -tm->tm_hour;
|
|
|
|
tm->tm_mday = -tm->tm_mday;
|
|
|
|
tm->tm_mon = -tm->tm_mon;
|
|
|
|
tm->tm_year = -tm->tm_year;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_sec < 0)
|
|
|
|
{
|
|
|
|
tm->tm_sec += 60;
|
|
|
|
tm->tm_min--;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_min < 0)
|
|
|
|
{
|
|
|
|
tm->tm_min += 60;
|
|
|
|
tm->tm_hour--;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_hour < 0)
|
|
|
|
{
|
|
|
|
tm->tm_hour += 24;
|
|
|
|
tm->tm_mday--;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_mday < 0)
|
|
|
|
{
|
|
|
|
if (dt1 < dt2)
|
|
|
|
{
|
|
|
|
tm->tm_mday += mdays[tm1->tm_mon - 1];
|
|
|
|
if (isleap(tm1->tm_year) && (tm1->tm_mon == 2))
|
|
|
|
tm->tm_mday++;
|
|
|
|
tm->tm_mon--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_mday += mdays[tm2->tm_mon - 1];
|
|
|
|
if (isleap(tm2->tm_year) && (tm2->tm_mon == 2))
|
|
|
|
tm->tm_mday++;
|
|
|
|
tm->tm_mon--;
|
|
|
|
}
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_mon < 0)
|
|
|
|
{
|
|
|
|
tm->tm_mon += 12;
|
|
|
|
tm->tm_year--;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* recover sign if necessary... */
|
|
|
|
if (dt1 < dt2)
|
|
|
|
{
|
|
|
|
fsec = -fsec;
|
|
|
|
tm->tm_sec = -tm->tm_sec;
|
|
|
|
tm->tm_min = -tm->tm_min;
|
|
|
|
tm->tm_hour = -tm->tm_hour;
|
|
|
|
tm->tm_mday = -tm->tm_mday;
|
|
|
|
tm->tm_mon = -tm->tm_mon;
|
|
|
|
tm->tm_year = -tm->tm_year;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm2timespan(tm, fsec, result) != 0)
|
|
|
|
{
|
|
|
|
elog(WARN, "Unable to decode datetime", NULL);
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
result->time = (fsec2 - fsec1);
|
|
|
|
result->time += (tm2->tm_sec - tm1->tm_sec);
|
|
|
|
result->time += 60 * (tm2->tm_min - tm1->tm_min);
|
|
|
|
result->time += 3600 * (tm2->tm_hour - tm1->tm_hour);
|
|
|
|
result->time += 86400 * (tm2->tm_mday - tm1->tm_mday);
|
|
|
|
|
|
|
|
result->month = 12 * (tm2->tm_year - tm1->tm_year);
|
|
|
|
result->month += (tm2->tm_mon - tm1->tm_mon);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Unable to decode datetime", NULL);
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_age() */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
|
1997-03-25 08:11:24 +00:00
|
|
|
/*----------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* Conversion operators.
|
1997-03-25 08:11:24 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
/* datetime_text()
|
|
|
|
* Convert datetime to text data type.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
text *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_text(DateTime *datetime)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
text *result;
|
|
|
|
char *str;
|
|
|
|
int len;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(datetime))
|
|
|
|
return NULL;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
str = datetime_out(datetime);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
return NULL;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
len = (strlen(str) + VARHDRSZ);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOC(len);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
VARSIZE(result) = len;
|
|
|
|
memmove(VARDATA(result), str, (len - VARHDRSZ));
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
PFREE(str);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_text() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* text_datetime()
|
|
|
|
* Convert text string to datetime.
|
|
|
|
* Text type is not null terminated, so use temporary string
|
1997-09-07 05:04:48 +00:00
|
|
|
* then call the standard input routine.
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
text_datetime(text *str)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
|
|
|
int i;
|
|
|
|
char *sp,
|
|
|
|
*dp,
|
|
|
|
dstr[MAXDATELEN + 1];
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
return NULL;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
sp = VARDATA(str);
|
|
|
|
dp = dstr;
|
|
|
|
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
*dp = '\0';
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = datetime_in(dstr);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* text_datetime() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* timespan_text()
|
|
|
|
* Convert timespan to text data type.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
text *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_text(TimeSpan *timespan)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
text *result;
|
|
|
|
char *str;
|
|
|
|
int len;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(timespan))
|
|
|
|
return NULL;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
str = timespan_out(timespan);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
return NULL;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
len = (strlen(str) + VARHDRSZ);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOC(len);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
VARSIZE(result) = len;
|
|
|
|
memmove(VARDATA(result), str, (len - VARHDRSZ));
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
PFREE(str);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_text() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* text_timespan()
|
|
|
|
* Convert text string to timespan.
|
|
|
|
* Text type may not be null terminated, so copy to temporary string
|
1997-09-07 05:04:48 +00:00
|
|
|
* then call the standard input routine.
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
#ifdef NOT_USED
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
text_timespan(text *str)
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
|
|
|
int i;
|
|
|
|
char *sp,
|
|
|
|
*dp,
|
|
|
|
dstr[MAXDATELEN + 1];
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!PointerIsValid(str))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sp = VARDATA(str);
|
|
|
|
dp = dstr;
|
|
|
|
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
|
|
|
|
*dp++ = *sp++;
|
|
|
|
*dp = '\0';
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = timespan_in(dstr);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* text_timespan() */
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
#endif
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-07-01 00:22:46 +00:00
|
|
|
/* datetime_trunc()
|
|
|
|
* Extract specified field from datetime.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_trunc(text *units, DateTime *datetime)
|
1997-07-01 00:22:46 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
DateTime *result;
|
|
|
|
|
|
|
|
DateTime dt;
|
|
|
|
int tz;
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
double fsec;
|
|
|
|
char *tzn;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = PALLOCTYPE(DateTime);
|
|
|
|
|
|
|
|
up = VARDATA(units);
|
|
|
|
lp = lowunits;
|
|
|
|
for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
|
|
|
|
*lp++ = tolower(*up++);
|
|
|
|
*lp = '\0';
|
|
|
|
|
|
|
|
type = DecodeUnits(0, lowunits, &val);
|
1997-07-01 00:22:46 +00:00
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
{
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
strcpy(lowunits, "(unknown)");
|
|
|
|
printf("datetime_trunc- units %s type=%d value=%d\n", lowunits, type, val);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_NOT_FINITE(*datetime))
|
|
|
|
{
|
1997-07-01 00:22:46 +00:00
|
|
|
#if FALSE
|
|
|
|
/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
|
1997-09-07 05:04:48 +00:00
|
|
|
elog(WARN, "Datetime is not finite", NULL);
|
|
|
|
#endif
|
|
|
|
*result = 0;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
|
|
|
|
|
|
|
|
if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0))
|
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLENIUM:
|
|
|
|
tm->tm_year = (tm->tm_year / 1000) * 1000;
|
|
|
|
case DTK_CENTURY:
|
|
|
|
tm->tm_year = (tm->tm_year / 100) * 100;
|
|
|
|
case DTK_DECADE:
|
|
|
|
tm->tm_year = (tm->tm_year / 10) * 10;
|
|
|
|
case DTK_YEAR:
|
|
|
|
tm->tm_mon = 1;
|
|
|
|
case DTK_QUARTER:
|
|
|
|
tm->tm_mon = (3 * (tm->tm_mon / 4)) + 1;
|
|
|
|
case DTK_MONTH:
|
|
|
|
tm->tm_mday = 1;
|
|
|
|
case DTK_DAY:
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
case DTK_HOUR:
|
|
|
|
tm->tm_min = 0;
|
|
|
|
case DTK_MINUTE:
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
case DTK_SECOND:
|
|
|
|
fsec = 0;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLISEC:
|
|
|
|
fsec = rint(fsec * 1000) / 1000;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MICROSEC:
|
|
|
|
fsec = rint(fsec * 1000) / 1000;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Datetime units %s not supported", lowunits);
|
|
|
|
result = NULL;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
{
|
1997-07-01 00:22:46 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_isdst = -1;
|
|
|
|
tm->tm_year -= 1900;
|
|
|
|
tm->tm_mon -= 1;
|
|
|
|
tm->tm_isdst = -1;
|
|
|
|
mktime(tm);
|
|
|
|
tm->tm_year += 1900;
|
|
|
|
tm->tm_mon += 1;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
tz = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !HAVE_INT_TIMEZONE */
|
|
|
|
tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !USE_POSIX_TIME */
|
|
|
|
tz = CTimeZone;
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
tz = 0;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm2datetime(tm, fsec, &tz, result) != 0)
|
|
|
|
elog(WARN, "Unable to truncate datetime to %s", lowunits);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if ((type == RESERV) && (val == DTK_EPOCH))
|
|
|
|
{
|
|
|
|
DATETIME_EPOCH(*result);
|
|
|
|
*result = dt - SetDateTime(*result);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Datetime units %s not recognized", lowunits);
|
|
|
|
result = NULL;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_trunc() */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
/* timespan_trunc()
|
|
|
|
* Extract specified field from timespan.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_trunc(text *units, TimeSpan *timespan)
|
1997-07-01 00:22:46 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
TimeSpan *result;
|
|
|
|
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
double fsec;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = PALLOCTYPE(TimeSpan);
|
|
|
|
|
|
|
|
up = VARDATA(units);
|
|
|
|
lp = lowunits;
|
|
|
|
for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
|
|
|
|
*lp++ = tolower(*up++);
|
|
|
|
*lp = '\0';
|
|
|
|
|
|
|
|
type = DecodeUnits(0, lowunits, &val);
|
1997-07-01 00:22:46 +00:00
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
{
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
strcpy(lowunits, "(unknown)");
|
|
|
|
printf("timespan_trunc- units %s type=%d value=%d\n", lowunits, type, val);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan))
|
|
|
|
{
|
1997-07-01 00:22:46 +00:00
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
elog(WARN, "Timespan is not finite", NULL);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
result = NULL;
|
|
|
|
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else if (type == UNITS)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (timespan2tm(*timespan, tm, &fsec) == 0)
|
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLENIUM:
|
|
|
|
tm->tm_year = (tm->tm_year / 1000) * 1000;
|
|
|
|
case DTK_CENTURY:
|
|
|
|
tm->tm_year = (tm->tm_year / 100) * 100;
|
|
|
|
case DTK_DECADE:
|
|
|
|
tm->tm_year = (tm->tm_year / 10) * 10;
|
|
|
|
case DTK_YEAR:
|
|
|
|
tm->tm_mon = 0;
|
|
|
|
case DTK_QUARTER:
|
|
|
|
tm->tm_mon = (3 * (tm->tm_mon / 4));
|
|
|
|
case DTK_MONTH:
|
|
|
|
tm->tm_mday = 0;
|
|
|
|
case DTK_DAY:
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
case DTK_HOUR:
|
|
|
|
tm->tm_min = 0;
|
|
|
|
case DTK_MINUTE:
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
case DTK_SECOND:
|
|
|
|
fsec = 0;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLISEC:
|
|
|
|
fsec = rint(fsec * 1000) / 1000;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MICROSEC:
|
|
|
|
fsec = rint(fsec * 1000) / 1000;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Timespan units %s not supported", lowunits);
|
|
|
|
result = NULL;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tm2timespan(tm, fsec, result) != 0)
|
|
|
|
elog(WARN, "Unable to truncate timespan to %s", lowunits);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(NOTICE, "Timespan out of range", NULL);
|
|
|
|
result = NULL;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#if FALSE
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else if ((type == RESERV) && (val == DTK_EPOCH))
|
|
|
|
{
|
|
|
|
*result = timespan->time;
|
|
|
|
if (timespan->month != 0)
|
|
|
|
{
|
|
|
|
*result += ((365.25 * 86400) * (timespan->month / 12));
|
|
|
|
*result += ((30 * 86400) * (timespan->month % 12));
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Timespan units %s not recognized", units);
|
|
|
|
result = NULL;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_trunc() */
|
1997-07-01 00:22:46 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
/* datetime_part()
|
|
|
|
* Extract specified field from datetime.
|
|
|
|
*/
|
1997-03-25 08:11:24 +00:00
|
|
|
float64
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_part(text *units, DateTime *datetime)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
float64 result;
|
|
|
|
|
|
|
|
DateTime dt;
|
|
|
|
int tz;
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
double fsec;
|
|
|
|
char *tzn;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = PALLOCTYPE(float64data);
|
|
|
|
|
|
|
|
up = VARDATA(units);
|
|
|
|
lp = lowunits;
|
|
|
|
for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
|
|
|
|
*lp++ = tolower(*up++);
|
|
|
|
*lp = '\0';
|
|
|
|
|
|
|
|
type = DecodeUnits(0, lowunits, &val);
|
|
|
|
if (type == IGNORE)
|
|
|
|
{
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
strcpy(lowunits, "(unknown)");
|
|
|
|
printf("datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_NOT_FINITE(*datetime))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#if FALSE
|
1997-06-20 17:12:54 +00:00
|
|
|
/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
|
1997-09-07 05:04:48 +00:00
|
|
|
elog(WARN, "Datetime is not finite", NULL);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*result = 0;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
|
|
|
|
|
|
|
|
if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0))
|
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TZ:
|
|
|
|
*result = tz;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MICROSEC:
|
|
|
|
*result = (fsec * 1000000);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLISEC:
|
|
|
|
*result = (fsec * 1000);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_SECOND:
|
|
|
|
*result = (tm->tm_sec + fsec);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MINUTE:
|
|
|
|
*result = tm->tm_min;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_HOUR:
|
|
|
|
*result = tm->tm_hour;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DAY:
|
|
|
|
*result = tm->tm_mday;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MONTH:
|
|
|
|
*result = tm->tm_mon;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_QUARTER:
|
|
|
|
*result = (tm->tm_mon / 4) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_YEAR:
|
|
|
|
*result = tm->tm_year;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DECADE:
|
|
|
|
*result = (tm->tm_year / 10) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_CENTURY:
|
|
|
|
*result = (tm->tm_year / 100) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLENIUM:
|
|
|
|
*result = (tm->tm_year / 1000) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Datetime units %s not supported", lowunits);
|
|
|
|
*result = 0;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (type == RESERV)
|
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_EPOCH:
|
|
|
|
DATETIME_EPOCH(*result);
|
|
|
|
*result = dt - SetDateTime(*result);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DOW:
|
|
|
|
if (datetime2tm(dt, &tz, tm, &fsec, &tzn) != 0)
|
|
|
|
elog(WARN, "Unable to encode datetime", NULL);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
*result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Datetime units %s not supported", lowunits);
|
|
|
|
*result = 0;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Datetime units %s not recognized", lowunits);
|
|
|
|
*result = 0;
|
|
|
|
}
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_part() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* timespan_part()
|
|
|
|
* Extract specified field from timespan.
|
|
|
|
*/
|
|
|
|
float64
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan_part(text *units, TimeSpan *timespan)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
float64 result;
|
|
|
|
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowunits[MAXDATELEN + 1];
|
|
|
|
double fsec;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
result = PALLOCTYPE(float64data);
|
|
|
|
|
|
|
|
up = VARDATA(units);
|
|
|
|
lp = lowunits;
|
|
|
|
for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
|
|
|
|
*lp++ = tolower(*up++);
|
|
|
|
*lp = '\0';
|
|
|
|
|
|
|
|
type = DecodeUnits(0, lowunits, &val);
|
|
|
|
if (type == IGNORE)
|
|
|
|
{
|
|
|
|
type = DecodeSpecial(0, lowunits, &val);
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#ifdef DATEDEBUG
|
|
|
|
if (type == IGNORE)
|
|
|
|
strcpy(lowunits, "(unknown)");
|
|
|
|
printf("timespan_part- units %s type=%d value=%d\n", lowunits, type, val);
|
|
|
|
#endif
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (TIMESPAN_IS_INVALID(*timespan))
|
|
|
|
{
|
|
|
|
#if FALSE
|
|
|
|
elog(WARN, "Timespan is not finite", NULL);
|
|
|
|
#endif
|
1997-03-25 08:11:24 +00:00
|
|
|
*result = 0;
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (type == UNITS)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (timespan2tm(*timespan, tm, &fsec) == 0)
|
|
|
|
{
|
|
|
|
switch (val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MICROSEC:
|
|
|
|
*result = (fsec * 1000000);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLISEC:
|
|
|
|
*result = (fsec * 1000);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_SECOND:
|
|
|
|
*result = (tm->tm_sec + fsec);
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MINUTE:
|
|
|
|
*result = tm->tm_min;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_HOUR:
|
|
|
|
*result = tm->tm_hour;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DAY:
|
|
|
|
*result = tm->tm_mday;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MONTH:
|
|
|
|
*result = tm->tm_mon;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_QUARTER:
|
|
|
|
*result = (tm->tm_mon / 4) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_YEAR:
|
|
|
|
*result = tm->tm_year;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DECADE:
|
|
|
|
*result = (tm->tm_year / 10) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_CENTURY:
|
|
|
|
*result = (tm->tm_year / 100) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_MILLENIUM:
|
|
|
|
*result = (tm->tm_year / 1000) + 1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
elog(WARN, "Timespan units %s not yet supported", units);
|
|
|
|
result = NULL;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(NOTICE, "Timespan out of range", NULL);
|
|
|
|
*result = 0;
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if ((type == RESERV) && (val == DTK_EPOCH))
|
|
|
|
{
|
|
|
|
*result = timespan->time;
|
|
|
|
if (timespan->month != 0)
|
|
|
|
{
|
|
|
|
*result += ((365.25 * 86400) * (timespan->month / 12));
|
|
|
|
*result += ((30 * 86400) * (timespan->month % 12));
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Timespan units %s not recognized", units);
|
1997-07-01 00:22:46 +00:00
|
|
|
*result = 0;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* timespan_part() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* datetime_zone()
|
|
|
|
* Encode datetime type with specified time zone.
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
text *
|
1997-09-08 21:56:23 +00:00
|
|
|
datetime_zone(text *zone, DateTime *datetime)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
text *result;
|
|
|
|
|
|
|
|
DateTime dt;
|
|
|
|
int tz;
|
|
|
|
int type,
|
|
|
|
val;
|
|
|
|
int i;
|
|
|
|
char *up,
|
|
|
|
*lp,
|
|
|
|
lowzone[MAXDATELEN + 1];
|
|
|
|
char *tzn,
|
|
|
|
upzone[MAXDATELEN + 1];
|
|
|
|
double fsec;
|
|
|
|
struct tm tt,
|
|
|
|
*tm = &tt;
|
|
|
|
char buf[MAXDATELEN + 1];
|
|
|
|
int len;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
if ((!PointerIsValid(zone)) || (!PointerIsValid(datetime)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
up = VARDATA(zone);
|
|
|
|
lp = lowzone;
|
|
|
|
for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++)
|
|
|
|
*lp++ = tolower(*up++);
|
|
|
|
*lp = '\0';
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
type = DecodeSpecial(0, lowzone, &val);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
strcpy(lowzone, "(unknown)");
|
|
|
|
printf("datetime_zone- zone %s type=%d value=%d\n", lowzone, type, val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_NOT_FINITE(*datetime))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
|
|
|
* could return null but Postgres doesn't like that currently. -
|
|
|
|
* tgl 97/06/12
|
|
|
|
*/
|
|
|
|
elog(WARN, "Datetime is not finite", NULL);
|
|
|
|
result = NULL;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if ((type == TZ) || (type == DTZ))
|
|
|
|
{
|
|
|
|
tm->tm_isdst = ((type == DTZ) ? 1 : 0);
|
|
|
|
tz = val * 60;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
|
|
|
|
dt = dt2local(dt, tz);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (datetime2tm(dt, NULL, tm, &fsec, NULL) != 0)
|
|
|
|
elog(WARN, "Datetime not legal", NULL);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
up = upzone;
|
|
|
|
lp = lowzone;
|
|
|
|
for (i = 0; *lp != '\0'; i++)
|
|
|
|
*up++ = toupper(*lp++);
|
|
|
|
*up = '\0';
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tzn = upzone;
|
|
|
|
EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
len = (strlen(buf) + VARHDRSZ);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
result = PALLOC(len);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
VARSIZE(result) = len;
|
|
|
|
memmove(VARDATA(result), buf, (len - VARHDRSZ));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
elog(WARN, "Time zone %s not recognized", lowzone);
|
|
|
|
result = NULL;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (result);
|
|
|
|
} /* datetime_zone() */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* PRIVATE ROUTINES *
|
1996-07-09 06:22:35 +00:00
|
|
|
*****************************************************************************/
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
/* definitions for squeezing values into "value" */
|
1997-09-07 05:04:48 +00:00
|
|
|
#define ABS_SIGNBIT (char) 0200
|
|
|
|
#define VALMASK (char) 0177
|
|
|
|
#define NEG(n) ((n)|ABS_SIGNBIT)
|
1997-03-14 23:21:12 +00:00
|
|
|
#define SIGNEDCHAR(c) ((c)&ABS_SIGNBIT? -((c)&VALMASK): (c))
|
1997-09-07 05:04:48 +00:00
|
|
|
#define FROMVAL(tp) (-SIGNEDCHAR((tp)->value) * 10) /* uncompress */
|
1997-03-14 23:21:12 +00:00
|
|
|
#define TOVAL(tp, v) ((tp)->value = ((v) < 0? NEG((-(v))/10): (v)/10))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to keep this table reasonably small, we divide the lexval for TZ and DTZ
|
|
|
|
* entries by 10 and truncate the text field at MAXTOKLEN characters.
|
|
|
|
* the text field is not guaranteed to be NULL-terminated.
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
static datetkn datetktbl[] = {
|
1997-09-07 05:04:48 +00:00
|
|
|
/* text token lexval */
|
|
|
|
{EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
|
|
|
|
{"acsst", DTZ, 63}, /* Cent. Australia */
|
|
|
|
{"acst", TZ, 57}, /* Cent. Australia */
|
|
|
|
{DA_D, ADBC, AD}, /* "ad" for years >= 0 */
|
|
|
|
{"abstime", IGNORE, 0}, /* "abstime" for pre-v6.1 "Invalid
|
|
|
|
* Abstime" */
|
|
|
|
{"adt", DTZ, NEG(18)}, /* Atlantic Daylight Time */
|
|
|
|
{"aesst", DTZ, 66}, /* E. Australia */
|
|
|
|
{"aest", TZ, 60}, /* Australia Eastern Std Time */
|
|
|
|
{"ahst", TZ, 60}, /* Alaska-Hawaii Std Time */
|
|
|
|
{"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
|
|
|
|
{"am", AMPM, AM},
|
|
|
|
{"apr", MONTH, 4},
|
|
|
|
{"april", MONTH, 4},
|
|
|
|
{"ast", TZ, NEG(24)}, /* Atlantic Std Time (Canada) */
|
|
|
|
{"at", IGNORE, 0}, /* "at" (throwaway) */
|
|
|
|
{"aug", MONTH, 8},
|
|
|
|
{"august", MONTH, 8},
|
|
|
|
{"awsst", DTZ, 54}, /* W. Australia */
|
|
|
|
{"awst", TZ, 48}, /* W. Australia */
|
|
|
|
{DB_C, ADBC, BC}, /* "bc" for years < 0 */
|
|
|
|
{"bst", TZ, 6}, /* British Summer Time */
|
|
|
|
{"bt", TZ, 18}, /* Baghdad Time */
|
|
|
|
{"cadt", DTZ, 63}, /* Central Australian DST */
|
|
|
|
{"cast", TZ, 57}, /* Central Australian ST */
|
|
|
|
{"cat", TZ, NEG(60)}, /* Central Alaska Time */
|
|
|
|
{"cct", TZ, 48}, /* China Coast */
|
|
|
|
{"cdt", DTZ, NEG(30)}, /* Central Daylight Time */
|
|
|
|
{"cet", TZ, 6}, /* Central European Time */
|
|
|
|
{"cetdst", DTZ, 12}, /* Central European Dayl.Time */
|
|
|
|
{"cst", TZ, NEG(36)}, /* Central Standard Time */
|
|
|
|
{DCURRENT, RESERV, DTK_CURRENT}, /* "current" is always now */
|
|
|
|
{"dec", MONTH, 12},
|
|
|
|
{"december", MONTH, 12},
|
|
|
|
{"dnt", TZ, 6}, /* Dansk Normal Tid */
|
|
|
|
{"dow", RESERV, DTK_DOW}, /* day of week */
|
|
|
|
{"dst", DTZMOD, 6},
|
|
|
|
{"east", TZ, NEG(60)}, /* East Australian Std Time */
|
|
|
|
{"edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
|
|
|
|
{"eet", TZ, 12}, /* East. Europe, USSR Zone 1 */
|
|
|
|
{"eetdst", DTZ, 18}, /* Eastern Europe */
|
|
|
|
{EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
|
1997-06-23 14:50:56 +00:00
|
|
|
#if USE_AUSTRALIAN_RULES
|
1997-09-07 05:04:48 +00:00
|
|
|
{"est", TZ, 60}, /* Australia Eastern Std Time */
|
1997-06-23 14:50:56 +00:00
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
{"est", TZ, NEG(30)}, /* Eastern Standard Time */
|
|
|
|
#endif
|
|
|
|
{"feb", MONTH, 2},
|
|
|
|
{"february", MONTH, 2},
|
|
|
|
{"fri", DOW, 5},
|
|
|
|
{"friday", DOW, 5},
|
|
|
|
{"fst", TZ, 6}, /* French Summer Time */
|
|
|
|
{"fwt", DTZ, 12}, /* French Winter Time */
|
|
|
|
{"gmt", TZ, 0}, /* Greenwish Mean Time */
|
|
|
|
{"gst", TZ, 60}, /* Guam Std Time, USSR Zone 9 */
|
|
|
|
{"hdt", DTZ, NEG(54)}, /* Hawaii/Alaska */
|
|
|
|
{"hmt", DTZ, 18}, /* Hellas ? ? */
|
|
|
|
{"hst", TZ, NEG(60)}, /* Hawaii Std Time */
|
|
|
|
{"idle", TZ, 72}, /* Intl. Date Line, East */
|
|
|
|
{"idlw", TZ, NEG(72)}, /* Intl. Date Line, West */
|
|
|
|
{LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */
|
|
|
|
{INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid
|
|
|
|
* time */
|
|
|
|
{"ist", TZ, 12}, /* Israel */
|
|
|
|
{"it", TZ, 22}, /* Iran Time */
|
|
|
|
{"jan", MONTH, 1},
|
|
|
|
{"january", MONTH, 1},
|
|
|
|
{"jst", TZ, 54}, /* Japan Std Time,USSR Zone 8 */
|
|
|
|
{"jt", TZ, 45}, /* Java Time */
|
|
|
|
{"jul", MONTH, 7},
|
|
|
|
{"july", MONTH, 7},
|
|
|
|
{"jun", MONTH, 6},
|
|
|
|
{"june", MONTH, 6},
|
|
|
|
{"kst", TZ, 54}, /* Korea Standard Time */
|
|
|
|
{"ligt", TZ, 60}, /* From Melbourne, Australia */
|
|
|
|
{"mar", MONTH, 3},
|
|
|
|
{"march", MONTH, 3},
|
|
|
|
{"may", MONTH, 5},
|
|
|
|
{"mdt", DTZ, NEG(36)}, /* Mountain Daylight Time */
|
|
|
|
{"mest", DTZ, 12}, /* Middle Europe Summer Time */
|
|
|
|
{"met", TZ, 6}, /* Middle Europe Time */
|
|
|
|
{"metdst", DTZ, 12}, /* Middle Europe Daylight Time */
|
|
|
|
{"mewt", TZ, 6}, /* Middle Europe Winter Time */
|
|
|
|
{"mez", TZ, 6}, /* Middle Europe Zone */
|
|
|
|
{"mon", DOW, 1},
|
|
|
|
{"monday", DOW, 1},
|
|
|
|
{"mst", TZ, NEG(42)}, /* Mountain Standard Time */
|
|
|
|
{"mt", TZ, 51}, /* Moluccas Time */
|
|
|
|
{"ndt", DTZ, NEG(15)}, /* Nfld. Daylight Time */
|
|
|
|
{"nft", TZ, NEG(21)}, /* Newfoundland Standard Time */
|
|
|
|
{"nor", TZ, 6}, /* Norway Standard Time */
|
|
|
|
{"nov", MONTH, 11},
|
|
|
|
{"november", MONTH, 11},
|
|
|
|
{NOW, RESERV, DTK_NOW}, /* current transaction time */
|
|
|
|
{"nst", TZ, NEG(21)}, /* Nfld. Standard Time */
|
|
|
|
{"nt", TZ, NEG(66)}, /* Nome Time */
|
|
|
|
{"nzdt", DTZ, 78}, /* New Zealand Daylight Time */
|
|
|
|
{"nzst", TZ, 72}, /* New Zealand Standard Time */
|
|
|
|
{"nzt", TZ, 72}, /* New Zealand Time */
|
|
|
|
{"oct", MONTH, 10},
|
|
|
|
{"october", MONTH, 10},
|
|
|
|
{"on", IGNORE, 0}, /* "on" (throwaway) */
|
|
|
|
{"pdt", DTZ, NEG(42)}, /* Pacific Daylight Time */
|
|
|
|
{"pm", AMPM, PM},
|
|
|
|
{"pst", TZ, NEG(48)}, /* Pacific Standard Time */
|
|
|
|
{"sadt", DTZ, 63}, /* S. Australian Dayl. Time */
|
|
|
|
{"sast", TZ, 57}, /* South Australian Std Time */
|
|
|
|
{"sat", DOW, 6},
|
|
|
|
{"saturday", DOW, 6},
|
|
|
|
{"sep", MONTH, 9},
|
|
|
|
{"sept", MONTH, 9},
|
|
|
|
{"september", MONTH, 9},
|
|
|
|
{"set", TZ, NEG(6)}, /* Seychelles Time ?? */
|
|
|
|
{"sst", DTZ, 12}, /* Swedish Summer Time */
|
|
|
|
{"sun", DOW, 0},
|
|
|
|
{"sunday", DOW, 0},
|
|
|
|
{"swt", TZ, 6}, /* Swedish Winter Time */
|
|
|
|
{"thu", DOW, 4},
|
|
|
|
{"thur", DOW, 4},
|
|
|
|
{"thurs", DOW, 4},
|
|
|
|
{"thursday", DOW, 4},
|
|
|
|
{TODAY, RESERV, DTK_TODAY}, /* midnight */
|
|
|
|
{TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */
|
|
|
|
{"tue", DOW, 2},
|
|
|
|
{"tues", DOW, 2},
|
|
|
|
{"tuesday", DOW, 2},
|
|
|
|
{"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid
|
|
|
|
* time */
|
|
|
|
{"ut", TZ, 0},
|
|
|
|
{"utc", TZ, 0},
|
|
|
|
{"wadt", DTZ, 48}, /* West Australian DST */
|
|
|
|
{"wast", TZ, 42}, /* West Australian Std Time */
|
|
|
|
{"wat", TZ, NEG(6)}, /* West Africa Time */
|
|
|
|
{"wdt", DTZ, 54}, /* West Australian DST */
|
|
|
|
{"wed", DOW, 3},
|
|
|
|
{"wednesday", DOW, 3},
|
|
|
|
{"weds", DOW, 3},
|
|
|
|
{"wet", TZ, 0}, /* Western Europe */
|
|
|
|
{"wetdst", DTZ, 6}, /* Western Europe */
|
|
|
|
{"wst", TZ, 48}, /* West Australian Std Time */
|
|
|
|
{"ydt", DTZ, NEG(48)}, /* Yukon Daylight Time */
|
|
|
|
{YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */
|
|
|
|
{"yst", TZ, NEG(54)}, /* Yukon Standard Time */
|
|
|
|
{"zp4", TZ, NEG(24)}, /* GMT +4 hours. */
|
|
|
|
{"zp5", TZ, NEG(30)}, /* GMT +5 hours. */
|
|
|
|
{"zp6", TZ, NEG(36)}, /* GMT +6 hours. */
|
|
|
|
{"z", RESERV, DTK_ZULU}, /* 00:00:00 */
|
|
|
|
{ZULU, RESERV, DTK_ZULU}, /* 00:00:00 */
|
1997-09-06 00:22:44 +00:00
|
|
|
};
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
static datetkn deltatktbl[] = {
|
1997-09-07 05:04:48 +00:00
|
|
|
/* text token lexval */
|
|
|
|
{"@", IGNORE, 0}, /* postgres relative time prefix */
|
|
|
|
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
|
|
|
|
{"c", UNITS, DTK_CENTURY}, /* "century" relative time units */
|
|
|
|
{"cent", UNITS, DTK_CENTURY}, /* "century" relative time units */
|
|
|
|
{"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative time units */
|
|
|
|
{DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative time units */
|
|
|
|
{"d", UNITS, DTK_DAY}, /* "day" relative time units */
|
|
|
|
{DDAY, UNITS, DTK_DAY}, /* "day" relative time units */
|
|
|
|
{"days", UNITS, DTK_DAY}, /* "days" relative time units */
|
|
|
|
{"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */
|
|
|
|
{"decs", UNITS, DTK_DECADE},/* "decades" relative time units */
|
|
|
|
{DDECADE, UNITS, DTK_DECADE}, /* "decade" relative time units */
|
|
|
|
{"decades", UNITS, DTK_DECADE}, /* "decades" relative time units */
|
|
|
|
{"h", UNITS, DTK_HOUR}, /* "hour" relative time units */
|
|
|
|
{DHOUR, UNITS, DTK_HOUR}, /* "hour" relative time units */
|
|
|
|
{"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */
|
|
|
|
{"hr", UNITS, DTK_HOUR}, /* "hour" relative time units */
|
|
|
|
{"hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */
|
|
|
|
{INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid
|
|
|
|
* time */
|
|
|
|
{"m", UNITS, DTK_MINUTE}, /* "minute" relative time units */
|
|
|
|
{"microsecon", UNITS, DTK_MILLISEC}, /* "microsecond" relative
|
|
|
|
* time units */
|
|
|
|
{"mil", UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */
|
|
|
|
{"mils", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */
|
|
|
|
{"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */
|
|
|
|
{DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */
|
|
|
|
{"millisecon", UNITS, DTK_MILLISEC}, /* "millisecond" relative
|
|
|
|
* time units */
|
|
|
|
{"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
|
|
|
|
{"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
|
|
|
|
{"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
|
|
|
|
{DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative time units */
|
|
|
|
{"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative time units */
|
|
|
|
{"mon", UNITS, DTK_MONTH}, /* "months" relative time units */
|
|
|
|
{"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
|
|
|
|
{DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
|
|
|
|
{"months", UNITS, DTK_MONTH}, /* "months" relative time units */
|
|
|
|
{"ms", UNITS, DTK_MILLISEC},/* "millisecond" relative time units */
|
|
|
|
{"msec", UNITS, DTK_MILLISEC}, /* "millisecond" relative time
|
|
|
|
* units */
|
|
|
|
{DMILLISEC, UNITS, DTK_MILLISEC}, /* "millisecond" relative time
|
|
|
|
* units */
|
|
|
|
{"mseconds", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time
|
|
|
|
* units */
|
|
|
|
{"msecs", UNITS, DTK_MILLISEC}, /* "milliseconds" relative time
|
|
|
|
* units */
|
|
|
|
{"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time units */
|
|
|
|
{DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time units */
|
|
|
|
{"reltime", IGNORE, 0}, /* "reltime" for pre-v6.1 "Undefined
|
|
|
|
* Reltime" */
|
|
|
|
{"s", UNITS, DTK_SECOND}, /* "second" relative time units */
|
|
|
|
{"sec", UNITS, DTK_SECOND}, /* "second" relative time units */
|
|
|
|
{DSECOND, UNITS, DTK_SECOND}, /* "second" relative time units */
|
|
|
|
{"seconds", UNITS, DTK_SECOND}, /* "seconds" relative time units */
|
|
|
|
{"secs", UNITS, DTK_SECOND},/* "seconds" relative time units */
|
|
|
|
{DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
|
|
|
|
{"tz", UNITS, DTK_TZ}, /* "timezone" time offset */
|
|
|
|
{"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid
|
|
|
|
* time */
|
|
|
|
{"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
|
|
|
|
{"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time
|
|
|
|
* units */
|
|
|
|
{DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative time
|
|
|
|
* units */
|
|
|
|
{"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
|
|
|
|
* units */
|
|
|
|
{"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
|
|
|
|
* units */
|
|
|
|
{"w", UNITS, DTK_WEEK}, /* "week" relative time units */
|
|
|
|
{DWEEK, UNITS, DTK_WEEK}, /* "week" relative time units */
|
|
|
|
{"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */
|
|
|
|
{"y", UNITS, DTK_YEAR}, /* "year" relative time units */
|
|
|
|
{DYEAR, UNITS, DTK_YEAR}, /* "year" relative time units */
|
|
|
|
{"years", UNITS, DTK_YEAR}, /* "years" relative time units */
|
|
|
|
{"yr", UNITS, DTK_YEAR}, /* "year" relative time units */
|
|
|
|
{"yrs", UNITS, DTK_YEAR}, /* "years" relative time units */
|
1997-09-06 00:22:44 +00:00
|
|
|
};
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
|
|
|
|
|
|
|
|
#if USE_DATE_CACHE
|
1997-09-08 02:41:22 +00:00
|
|
|
datetkn *datecache[MAXDATEFIELDS] = {NULL};
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
datetkn *deltacache[MAXDATEFIELDS] = {NULL};
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calendar time to Julian date conversions.
|
|
|
|
* Julian date is commonly used in astronomical applications,
|
1997-09-07 05:04:48 +00:00
|
|
|
* since it is numerically accurate and computationally simple.
|
1997-03-14 23:21:12 +00:00
|
|
|
* The algorithms here will accurately convert between Julian day
|
1997-09-07 05:04:48 +00:00
|
|
|
* and calendar date for all non-negative Julian days
|
|
|
|
* (i.e. from Nov 23, -4713 on).
|
1997-03-14 23:21:12 +00:00
|
|
|
*
|
|
|
|
* Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
|
1997-09-07 05:04:48 +00:00
|
|
|
* University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
|
1997-03-14 23:21:12 +00:00
|
|
|
*
|
1997-05-11 15:11:47 +00:00
|
|
|
* Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
|
1997-09-07 05:04:48 +00:00
|
|
|
* now at Aerospace Corp. (hi, Henry!)
|
1997-05-11 15:11:47 +00:00
|
|
|
*
|
1997-03-14 23:21:12 +00:00
|
|
|
* These routines will be used by other date/time packages - tgl 97/02/25
|
|
|
|
*/
|
|
|
|
|
1997-05-11 15:11:47 +00:00
|
|
|
/* Set the minimum year to one greater than the year of the first valid day
|
1997-09-07 05:04:48 +00:00
|
|
|
* to avoid having to check year and day both. - tgl 97/05/08
|
1997-05-11 15:11:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define JULIAN_MINYEAR (-4713)
|
|
|
|
#define JULIAN_MINMONTH (11)
|
|
|
|
#define JULIAN_MINDAY (23)
|
|
|
|
|
|
|
|
#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
|
|
|
|
|| ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
|
|
|
|
|| ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
date2j(int y, int m, int d)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int m12 = (m - 14) / 12;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12
|
|
|
|
- (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075);
|
|
|
|
} /* date2j() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-06-20 17:12:54 +00:00
|
|
|
void
|
1997-09-07 05:04:48 +00:00
|
|
|
j2date(int jd, int *year, int *month, int *day)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int j,
|
|
|
|
y,
|
|
|
|
m,
|
|
|
|
d;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
int i,
|
|
|
|
l,
|
|
|
|
n;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
l = jd + 68569;
|
|
|
|
n = (4 * l) / 146097;
|
|
|
|
l -= (146097 * n + 3) / 4;
|
|
|
|
i = (4000 * (l + 1)) / 1461001;
|
|
|
|
l += 31 - (1461 * i) / 4;
|
|
|
|
j = (80 * l) / 2447;
|
|
|
|
d = l - (2447 * j) / 80;
|
|
|
|
l = j / 11;
|
|
|
|
m = (j + 2) - (12 * l);
|
|
|
|
y = 100 * (n - 49) + i + l;
|
|
|
|
|
|
|
|
*year = y;
|
|
|
|
*month = m;
|
|
|
|
*day = d;
|
|
|
|
return;
|
|
|
|
} /* j2date() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
j2day(int date)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int day;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
day = (date + 1) % 7;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (day);
|
|
|
|
} /* j2day() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
|
|
|
|
/* datetime2tm()
|
|
|
|
* Convert datetime data type to POSIX time structure.
|
|
|
|
* Note that year is _not_ 1900-based, but is an explicit full value.
|
|
|
|
* Also, month is one-based, _not_ zero-based.
|
1997-05-11 15:11:47 +00:00
|
|
|
* Returns:
|
1997-09-07 05:04:48 +00:00
|
|
|
* 0 on success
|
|
|
|
* -1 on out of range
|
1997-05-30 15:02:51 +00:00
|
|
|
*
|
|
|
|
* For dates within the system-supported time_t range, convert to the
|
1997-09-07 05:04:48 +00:00
|
|
|
* local time zone. If out of this range, leave as GMT. - tgl 97/05/27
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
*/
|
1997-03-25 08:11:24 +00:00
|
|
|
int
|
1997-09-07 05:04:48 +00:00
|
|
|
datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double date,
|
|
|
|
date0,
|
|
|
|
time,
|
|
|
|
sec;
|
|
|
|
time_t utime;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
1997-09-08 02:41:22 +00:00
|
|
|
struct tm *tx;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-04-22 17:36:57 +00:00
|
|
|
#endif
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
date0 = date2j(2000, 1, 1);
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
time = dt;
|
|
|
|
TMODULO(time, date, 86400e0);
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (time < 0)
|
|
|
|
{
|
|
|
|
time += 86400;
|
|
|
|
date -= 1;
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* Julian day routine does not work for negative Julian days */
|
|
|
|
if (date < -date0)
|
|
|
|
return -1;
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* add offset to go from J2000 back to standard Julian date */
|
|
|
|
date += date0;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- date is %f (%f %f)\n", dt, date, time);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
|
|
|
dt2time(time, &tm->tm_hour, &tm->tm_min, &sec);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
|
|
|
printf("datetime2tm- time is %02d:%02d:%02.0f\n", tm->tm_hour, tm->tm_min, sec);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*fsec = JROUND(sec);
|
|
|
|
TMODULO(*fsec, tm->tm_sec, 1);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tzp != NULL)
|
|
|
|
{
|
|
|
|
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
{
|
|
|
|
utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
|
1997-06-23 14:50:56 +00:00
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
if (utime < -1)
|
|
|
|
utime++;
|
1997-06-23 14:50:56 +00:00
|
|
|
#endif
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
1997-09-07 05:04:48 +00:00
|
|
|
tx = localtime(&utime);
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-05-30 15:02:51 +00:00
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n",
|
|
|
|
tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec,
|
|
|
|
tzname[0], tzname[1], tx->tm_isdst);
|
1997-05-30 15:02:51 +00:00
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s dst=%d\n",
|
|
|
|
tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec,
|
|
|
|
tx->tm_zone, tx->tm_isdst);
|
1997-05-30 15:02:51 +00:00
|
|
|
#endif
|
|
|
|
#else
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_year = tx->tm_year + 1900;
|
|
|
|
tm->tm_mon = tx->tm_mon + 1;
|
|
|
|
tm->tm_mday = tx->tm_mday;
|
|
|
|
tm->tm_hour = tx->tm_hour;
|
|
|
|
tm->tm_min = tx->tm_min;
|
1997-06-23 14:50:56 +00:00
|
|
|
#if FALSE
|
|
|
|
/* XXX HACK
|
|
|
|
* Argh! My Linux box puts in a 1 second offset for dates less than 1970
|
1997-09-07 05:04:48 +00:00
|
|
|
* but only if the seconds field was non-zero. So, don't copy the seconds
|
|
|
|
* field and instead carry forward from the original - tgl 97/06/18
|
1997-06-23 14:50:56 +00:00
|
|
|
* Note that GNU/Linux uses the standard freeware zic package as do
|
1997-09-07 05:04:48 +00:00
|
|
|
* many other platforms so this may not be GNU/Linux/ix86-specific.
|
1997-06-23 14:50:56 +00:00
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_sec = tx->tm_sec;
|
1997-06-23 14:50:56 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_isdst = tx->tm_isdst;
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
*tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
|
|
|
|
if (tzn != NULL)
|
|
|
|
*tzn = tzname[(tm->tm_isdst > 0)];
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !HAVE_INT_TIMEZONE */
|
|
|
|
tm->tm_gmtoff = tx->tm_gmtoff;
|
|
|
|
tm->tm_zone = tx->tm_zone;
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
|
|
|
|
if (tzn != NULL)
|
|
|
|
*tzn = tm->tm_zone;
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-05-11 15:11:47 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !USE_POSIX_TIME */
|
|
|
|
*tzp = CTimeZone; /* V7 conventions; don't know timezone? */
|
|
|
|
if (tzn != NULL)
|
|
|
|
*tzn = CTZName;
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*tzp = 0;
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
if (tzn != NULL)
|
|
|
|
*tzn = NULL;
|
|
|
|
}
|
1997-04-25 18:40:50 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
dt = dt2local(dt, *tzp);
|
1997-04-25 18:40:50 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
if (tzn != NULL)
|
|
|
|
*tzn = NULL;
|
|
|
|
}
|
1997-04-25 18:40:50 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
|
|
|
printf("datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-05-30 15:02:51 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
|
|
|
|
tzname[tm->tm_isdst != 0], ((tzp != NULL) ? *tzp : 0), CTimeZone, CDayLight);
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-05-30 15:02:51 +00:00
|
|
|
#endif
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* datetime2tm() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
|
1997-03-25 08:11:24 +00:00
|
|
|
/* tm2datetime()
|
|
|
|
* Convert a tm structure to a datetime data type.
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
* Note that year is _not_ 1900-based, but is an explicit full value.
|
|
|
|
* Also, month is one-based, _not_ zero-based.
|
1997-03-25 08:11:24 +00:00
|
|
|
*/
|
1997-05-11 15:11:47 +00:00
|
|
|
int
|
1997-09-08 21:56:23 +00:00
|
|
|
tm2datetime(struct tm * tm, double fsec, int *tzp, DateTime *result)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
double date,
|
|
|
|
time;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* Julian day routines are not correct for negative Julian days */
|
|
|
|
if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
return (-1);
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
|
|
|
|
time = time2t(tm->tm_hour, tm->tm_min, (tm->tm_sec + fsec));
|
|
|
|
*result = (date * 86400 + time);
|
1997-03-25 08:11:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
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);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tzp != NULL)
|
|
|
|
*result = dt2local(*result, -(*tzp));
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* tm2datetime() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
|
1997-05-30 15:02:51 +00:00
|
|
|
/* timespan2tm()
|
|
|
|
* Convert a timespan data type to a tm structure.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-08 21:56:23 +00:00
|
|
|
timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec)
|
1997-03-25 08:11:24 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double time;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (span.month != 0)
|
|
|
|
{
|
|
|
|
tm->tm_year = span.month / 12;
|
|
|
|
tm->tm_mon = span.month % 12;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_year = 0;
|
|
|
|
tm->tm_mon = 0;
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-05-11 15:11:47 +00:00
|
|
|
#ifdef ROUND_ALL
|
1997-09-07 05:04:48 +00:00
|
|
|
time = JROUND(span.time);
|
1997-05-11 15:11:47 +00:00
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
time = span.time;
|
1997-05-11 15:11:47 +00:00
|
|
|
#endif
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
TMODULO(time, tm->tm_mday, 86400e0);
|
|
|
|
TMODULO(time, tm->tm_hour, 3600e0);
|
|
|
|
TMODULO(time, tm->tm_min, 60e0);
|
|
|
|
TMODULO(time, tm->tm_sec, 1);
|
|
|
|
*fsec = time;
|
1997-03-25 08:11:24 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("timespan2tm- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span.month, span.time,
|
|
|
|
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* timespan2tm() */
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-08 21:56:23 +00:00
|
|
|
tm2timespan(struct tm * tm, double fsec, TimeSpan *span)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
span->month = ((tm->tm_year * 12) + tm->tm_mon);
|
|
|
|
span->time = ((((((tm->tm_mday * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60) + tm->tm_sec);
|
|
|
|
span->time = JROUND(span->time + fsec);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-03-25 08:11:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month, span->time,
|
|
|
|
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
|
1997-03-25 08:11:24 +00:00
|
|
|
#endif
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* tm2timespan() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
static DateTime
|
1997-06-20 17:12:54 +00:00
|
|
|
dt2local(DateTime dt, int tz)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
dt -= tz;
|
|
|
|
dt = JROUND(dt);
|
|
|
|
return (dt);
|
|
|
|
} /* dt2local() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-06-20 17:12:54 +00:00
|
|
|
double
|
|
|
|
time2t(const int hour, const int min, const double sec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
return ((((hour * 60) + min) * 60) + sec);
|
|
|
|
} /* time2t() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-08-19 21:40:56 +00:00
|
|
|
static void
|
1997-06-20 17:12:54 +00:00
|
|
|
dt2time(DateTime jd, int *hour, int *min, double *sec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double time;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
time = jd;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*hour = (time / 3600);
|
|
|
|
time -= ((*hour) * 3600);
|
|
|
|
*min = (time / 60);
|
|
|
|
time -= ((*min) * 60);
|
|
|
|
*sec = JROUND(time);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return;
|
|
|
|
} /* dt2time() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* parse and convert date in timestr (the normal interface)
|
|
|
|
*
|
|
|
|
* Returns the number of seconds since epoch (J2000)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* ParseDateTime()
|
|
|
|
* Break string into tokens based on a date/time context.
|
|
|
|
*/
|
|
|
|
int
|
1997-09-07 05:04:48 +00:00
|
|
|
ParseDateTime(char *timestr, char *lowstr,
|
|
|
|
char *field[], int ftype[], int maxfields, int *numfields)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int nf = 0;
|
|
|
|
char *cp = timestr;
|
|
|
|
char *lp = lowstr;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("ParseDateTime- input string is %s\n", timestr);
|
|
|
|
#endif
|
|
|
|
/* outer loop through fields */
|
|
|
|
while (*cp != '\0')
|
|
|
|
{
|
|
|
|
field[nf] = lp;
|
|
|
|
|
|
|
|
/* leading digit? then date or time */
|
|
|
|
if (isdigit(*cp))
|
|
|
|
{
|
|
|
|
*lp++ = *cp++;
|
|
|
|
while (isdigit(*cp))
|
|
|
|
*lp++ = *cp++;
|
|
|
|
/* time field? */
|
|
|
|
if (*cp == ':')
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_TIME;
|
|
|
|
while (isdigit(*cp) || (*cp == ':') || (*cp == '.'))
|
|
|
|
*lp++ = *cp++;
|
|
|
|
|
|
|
|
/* date field? allow embedded text month */
|
|
|
|
}
|
|
|
|
else if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_DATE;
|
|
|
|
while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.'))
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* otherwise, number only and will determine year, month,
|
|
|
|
* or day later
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_NUMBER;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* text? then date string, month, day of week, special, or
|
|
|
|
* timezone
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else if (isalpha(*cp))
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_STRING;
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
while (isalpha(*cp))
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
|
|
|
|
/* full date string with leading text month? */
|
|
|
|
if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_DATE;
|
|
|
|
while (isdigit(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.'))
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip leading spaces */
|
|
|
|
}
|
|
|
|
else if (isspace(*cp))
|
|
|
|
{
|
|
|
|
cp++;
|
|
|
|
continue;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* sign? then special or numeric timezone */
|
|
|
|
}
|
|
|
|
else if ((*cp == '+') || (*cp == '-'))
|
|
|
|
{
|
|
|
|
*lp++ = *cp++;
|
|
|
|
/* soak up leading whitespace */
|
|
|
|
while (isspace(*cp))
|
|
|
|
cp++;
|
|
|
|
/* numeric timezone? */
|
|
|
|
if (isdigit(*cp))
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_TZ;
|
|
|
|
*lp++ = *cp++;
|
|
|
|
while (isdigit(*cp) || (*cp == ':'))
|
|
|
|
*lp++ = *cp++;
|
|
|
|
|
|
|
|
/* special? */
|
|
|
|
}
|
|
|
|
else if (isalpha(*cp))
|
|
|
|
{
|
|
|
|
ftype[nf] = DTK_SPECIAL;
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
while (isalpha(*cp))
|
|
|
|
*lp++ = tolower(*cp++);
|
|
|
|
|
|
|
|
/* otherwise something wrong... */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ignore punctuation but use as delimiter */
|
|
|
|
}
|
|
|
|
else if (ispunct(*cp))
|
|
|
|
{
|
|
|
|
cp++;
|
|
|
|
continue;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* force in a delimiter */
|
|
|
|
*lp++ = '\0';
|
|
|
|
nf++;
|
|
|
|
if (nf > MAXDATEFIELDS)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("ParseDateTime- set field[%d] to %s type %d\n", (nf - 1), field[nf - 1], ftype[nf - 1]);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*numfields = nf;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* ParseDateTime() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeDateTime()
|
|
|
|
* Interpret previously parsed fields for general date and time.
|
|
|
|
* Return 0 if full date, 1 if only time, and -1 if problems.
|
1997-09-07 05:04:48 +00:00
|
|
|
* External format(s):
|
|
|
|
* "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>"
|
|
|
|
* "Fri Feb-7-1997 15:23:27"
|
|
|
|
* "Feb-7-1997 15:23:27"
|
|
|
|
* "2-7-1997 15:23:27"
|
|
|
|
* "1997-2-7 15:23:27"
|
|
|
|
* "1997.038 15:23:27" (day of year 1-366)
|
|
|
|
* Also supports input in compact time:
|
|
|
|
* "970207 152327"
|
|
|
|
* "97038 152327"
|
1997-05-30 15:02:51 +00:00
|
|
|
*
|
|
|
|
* Use the system-provided functions to get the current time zone
|
1997-09-07 05:04:48 +00:00
|
|
|
* if not specified in the input string.
|
1997-05-30 15:02:51 +00:00
|
|
|
* If the date is outside the time_t system-supported time range,
|
1997-09-07 05:04:48 +00:00
|
|
|
* then assume GMT time zone. - tgl 97/05/27
|
1997-03-14 23:21:12 +00:00
|
|
|
*/
|
|
|
|
int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeDateTime(char *field[], int ftype[], int nf,
|
|
|
|
int *dtype, struct tm * tm, double *fsec, int *tzp)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int fmask = 0,
|
|
|
|
tmask,
|
|
|
|
type;
|
|
|
|
int i;
|
|
|
|
int flen,
|
|
|
|
val;
|
|
|
|
int mer = HR24;
|
|
|
|
int bc = FALSE;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
|
|
|
tm->tm_isdst = -1; /* don't know daylight savings time status
|
|
|
|
* apriori */
|
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = 0;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("DecodeDateTime- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
|
|
|
|
#endif
|
|
|
|
switch (ftype[i])
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_DATE:
|
|
|
|
if (DecodeDate(field[i], fmask, &tmask, tm) != 0)
|
1997-09-07 05:04:48 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TIME:
|
|
|
|
if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
|
1997-09-07 05:04:48 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
1997-09-08 02:41:22 +00:00
|
|
|
* check upper limit on hours; other limits checked in
|
|
|
|
* DecodeTime()
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
if (tm->tm_hour > 23)
|
1997-09-07 05:04:48 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TZ:
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tzp == NULL)
|
|
|
|
return -1;
|
1997-09-08 02:41:22 +00:00
|
|
|
if (DecodeTimezone(field[i], tzp) != 0)
|
|
|
|
return -1;
|
|
|
|
tmask = DTK_M(TZ);
|
1997-09-07 05:04:48 +00:00
|
|
|
break;
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_NUMBER:
|
|
|
|
flen = strlen(field[i]);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
if (flen > 4)
|
|
|
|
{
|
|
|
|
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DecodeNumber(flen, field[i], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
break;
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("DecodeDateTime- special field[%d] %s type=%d value=%d\n", i, field[i], type, val);
|
|
|
|
#endif
|
|
|
|
if (type == IGNORE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RESERV:
|
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("DecodeDateTime- RESERV field %s value is %d\n", field[i], val);
|
|
|
|
#endif
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case DTK_NOW:
|
|
|
|
tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
GetCurrentTime(tm);
|
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = CTimeZone;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_YESTERDAY:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
GetCurrentTime(tm);
|
|
|
|
j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1),
|
|
|
|
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TODAY:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
GetCurrentTime(tm);
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_TOMORROW:
|
|
|
|
tmask = DTK_DATE_M;
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
GetCurrentTime(tm);
|
|
|
|
j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1),
|
|
|
|
&tm->tm_year, &tm->tm_mon, &tm->tm_mday);
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_ZULU:
|
|
|
|
tmask = (DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_DATE;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
if (tzp != NULL)
|
|
|
|
*tzp = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
*dtype = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MONTH:
|
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("DecodeDateTime- month field %s value is %d\n", field[i], val);
|
|
|
|
#endif
|
|
|
|
tm->tm_mon = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* daylight savings time modifier (solves "MET
|
|
|
|
* DST" syntax)
|
|
|
|
*/
|
|
|
|
case DTZMOD:
|
|
|
|
tmask |= DTK_M(DTZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
|
|
|
return -1;
|
|
|
|
*tzp += val * 60;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTZ:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* set mask for TZ here _or_ check for DTZ later
|
|
|
|
* when getting default timezone
|
|
|
|
*/
|
|
|
|
tmask |= DTK_M(TZ);
|
|
|
|
tm->tm_isdst = 1;
|
|
|
|
if (tzp == NULL)
|
|
|
|
return -1;
|
|
|
|
*tzp = val * 60;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TZ:
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
if (tzp == NULL)
|
|
|
|
return -1;
|
|
|
|
*tzp = val * 60;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IGNORE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AMPM:
|
|
|
|
mer = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ADBC:
|
|
|
|
bc = (val == BC);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DOW:
|
|
|
|
tm->tm_wday = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateTime- field[%d] %s (%08x/%08x) value is %d\n",
|
|
|
|
i, field[i], fmask, tmask, val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tmask & fmask)
|
|
|
|
return -1;
|
|
|
|
fmask |= tmask;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
|
|
|
|
if (bc)
|
|
|
|
tm->tm_year = -(tm->tm_year - 1);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((mer != HR24) && (tm->tm_hour > 12))
|
|
|
|
return -1;
|
|
|
|
if (mer == PM)
|
|
|
|
tm->tm_hour += 12;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateTime- mask %08x (%08x)", fmask, DTK_DATE_M);
|
|
|
|
printf(" set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
|
|
|
printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M))
|
|
|
|
return (((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* timezone not specified? then find local timezone if possible */
|
|
|
|
if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
|
|
|
|
&& (tzp != NULL) && (!(fmask & DTK_M(TZ))))
|
|
|
|
{
|
1997-04-25 18:40:50 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
|
|
|
* daylight savings time modifier but no standard timezone? then
|
|
|
|
* error
|
|
|
|
*/
|
|
|
|
if (fmask & DTK_M(DTZMOD))
|
|
|
|
return -1;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
|
|
|
|
{
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_year -= 1900;
|
|
|
|
tm->tm_mon -= 1;
|
|
|
|
tm->tm_isdst = -1;
|
|
|
|
mktime(tm);
|
|
|
|
tm->tm_year += 1900;
|
|
|
|
tm->tm_mon += 1;
|
1997-04-22 17:36:57 +00:00
|
|
|
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
*tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !HAVE_INT_TIMEZONE */
|
|
|
|
*tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-05-30 15:02:51 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
#else /* !USE_POSIX_TIME */
|
|
|
|
*tzp = CTimeZone;
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
*tzp = 0;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-04-22 17:36:57 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeDateTime() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeTimeOnly()
|
|
|
|
* Interpret parsed string as time fields only.
|
|
|
|
*/
|
|
|
|
int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeTimeOnly(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int fmask,
|
|
|
|
tmask,
|
|
|
|
type;
|
|
|
|
int i;
|
|
|
|
int flen,
|
|
|
|
val;
|
|
|
|
int mer = HR24;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
*dtype = DTK_TIME;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
tm->tm_isdst = -1; /* don't know daylight savings time status
|
|
|
|
* apriori */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
fmask = DTK_DATE_M;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeTimeOnly- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
switch (ftype[i])
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TIME:
|
|
|
|
if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_NUMBER:
|
|
|
|
flen = strlen(field[i]);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeTimeOnly- special field[%d] %s type=%d value=%d\n", i, field[i], type, val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
continue;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
tmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case RESERV:
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeTimeOnly- RESERV field %s value is %d\n", field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case DTK_NOW:
|
|
|
|
tmask = DTK_TIME_M;
|
|
|
|
*dtype = DTK_TIME;
|
|
|
|
GetCurrentTime(tm);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_ZULU:
|
|
|
|
tmask = (DTK_TIME_M | DTK_M(TZ));
|
|
|
|
*dtype = DTK_TIME;
|
|
|
|
tm->tm_hour = 0;
|
|
|
|
tm->tm_min = 0;
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
tm->tm_isdst = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IGNORE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AMPM:
|
|
|
|
mer = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tmask & fmask)
|
|
|
|
return -1;
|
|
|
|
fmask |= tmask;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeTimeOnly- field[%d] %s value is %d\n", i, field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeTimeOnly- mask %08x (%08x)", fmask, DTK_TIME_M);
|
|
|
|
printf(" %02d:%02d:%02d (%f)\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((mer != HR24) && (tm->tm_hour > 12))
|
|
|
|
return -1;
|
|
|
|
if (mer == PM)
|
|
|
|
tm->tm_hour += 12;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((fmask & DTK_TIME_M) != DTK_TIME_M)
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeTimeOnly() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeDate()
|
|
|
|
* Decode date string which includes delimiters.
|
|
|
|
* Insist on a complete set of fields.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double fsec;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
int nf = 0;
|
|
|
|
int i,
|
|
|
|
len;
|
|
|
|
int type,
|
|
|
|
val,
|
|
|
|
dmask = 0;
|
|
|
|
char *field[MAXDATEFIELDS];
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/* parse this string... */
|
|
|
|
while ((*str != '\0') && (nf < MAXDATEFIELDS))
|
|
|
|
{
|
|
|
|
/* skip field separators */
|
|
|
|
while (!isalnum(*str))
|
|
|
|
str++;
|
|
|
|
|
|
|
|
field[nf] = str;
|
|
|
|
if (isdigit(*str))
|
|
|
|
{
|
|
|
|
while (isdigit(*str))
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
else if (isalpha(*str))
|
|
|
|
{
|
|
|
|
while (isalpha(*str))
|
|
|
|
str++;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (*str != '\0')
|
|
|
|
*str++ = '\0';
|
|
|
|
nf++;
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* don't allow too many fields */
|
|
|
|
if (nf > 3)
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = 0;
|
|
|
|
|
|
|
|
/* look first for text fields, since that will be unambiguous month */
|
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
if (isalpha(*field[i]))
|
|
|
|
{
|
|
|
|
type = DecodeSpecial(i, field[i], &val);
|
|
|
|
if (type == IGNORE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dmask = DTK_M(type);
|
|
|
|
switch (type)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case MONTH:
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeDate- month field %s value is %d\n", field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
tm->tm_mon = val;
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeDate- illegal field %s value is %d\n", field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
return -1;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
if (fmask & dmask)
|
|
|
|
return -1;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
fmask |= dmask;
|
|
|
|
*tmask |= dmask;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* mark this field as being completed */
|
|
|
|
field[i] = NULL;
|
|
|
|
}
|
1997-09-05 18:13:45 +00: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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* now pick up remaining numeric fields */
|
|
|
|
for (i = 0; i < nf; i++)
|
|
|
|
{
|
|
|
|
if (field[i] == NULL)
|
|
|
|
continue;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((len = strlen(field[i])) <= 0)
|
|
|
|
return -1;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec) != 0)
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (fmask & dmask)
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
fmask |= dmask;
|
|
|
|
*tmask |= dmask;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeDate() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeTime()
|
|
|
|
* Decode time string which includes delimiters.
|
1997-04-22 17:36:57 +00:00
|
|
|
* Only check the lower limit on hours, since this same code
|
1997-09-07 05:04:48 +00:00
|
|
|
* can be used to represent time spans.
|
1997-03-14 23:21:12 +00:00
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
char *cp;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_TIME_M;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_hour = strtol(str, &cp, 10);
|
|
|
|
if (*cp != ':')
|
|
|
|
return -1;
|
|
|
|
str = cp + 1;
|
|
|
|
tm->tm_min = strtol(str, &cp, 10);
|
|
|
|
if (*cp == '\0')
|
|
|
|
{
|
|
|
|
tm->tm_sec = 0;
|
|
|
|
*fsec = 0;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (*cp != ':')
|
|
|
|
{
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
str = cp + 1;
|
|
|
|
tm->tm_sec = strtol(str, &cp, 10);
|
|
|
|
if (*cp == '\0')
|
|
|
|
{
|
|
|
|
*fsec = 0;
|
|
|
|
}
|
|
|
|
else if (*cp == '.')
|
|
|
|
{
|
|
|
|
str = cp;
|
|
|
|
*fsec = strtod(str, &cp);
|
|
|
|
if (cp == str)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* do a sanity check */
|
|
|
|
if ((tm->tm_hour < 0)
|
|
|
|
|| (tm->tm_min < 0) || (tm->tm_min > 59)
|
|
|
|
|| (tm->tm_sec < 0) || (tm->tm_sec > 59))
|
|
|
|
return -1;
|
1997-04-22 17:36:57 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeTime() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeNumber()
|
|
|
|
* Interpret numeric field as a date value in context.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeNumber(int flen, char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int val;
|
|
|
|
char *cp;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = 0;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
val = strtol(str, &cp, 10);
|
|
|
|
if (cp == str)
|
|
|
|
return -1;
|
|
|
|
if (*cp == '.')
|
|
|
|
{
|
|
|
|
*fsec = strtod(cp, &cp);
|
|
|
|
if (*cp != '\0')
|
|
|
|
return -1;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- %s is %d fmask=%08x tmask=%08x\n", str, val, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* enough digits to be unequivocal year? */
|
|
|
|
if (flen == 4)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- match %d (%s) as year\n", val, str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*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)))
|
|
|
|
{
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- misidentified year previously; swap with day %d\n", tm->tm_mday);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_mday = tm->tm_year;
|
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
}
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_year = val;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* special case day of year? */
|
|
|
|
}
|
|
|
|
else if ((flen == 3) && (fmask & DTK_M(YEAR))
|
|
|
|
&& ((val >= 1) && (val <= 366)))
|
|
|
|
{
|
|
|
|
*tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
|
|
|
|
tm->tm_yday = val;
|
|
|
|
j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1),
|
|
|
|
&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)))
|
|
|
|
&& ((val >= 1) && (val <= 12)))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- match %d (%s) as month\n", val, str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_M(MONTH);
|
|
|
|
tm->tm_mon = val;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* no year and EuroDates enabled? then could be day */
|
|
|
|
}
|
|
|
|
else if ((EuroDates || (fmask & DTK_M(MONTH)))
|
|
|
|
&& (!(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)))
|
|
|
|
&& ((val >= 1) && (val <= 31)))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- match %d (%s) as day\n", val, str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if ((!(fmask & DTK_M(MONTH)))
|
|
|
|
&& ((val >= 1) && (val <= 12)))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- (2) match %d (%s) as month\n", val, str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_M(MONTH);
|
|
|
|
tm->tm_mon = val;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if ((!(fmask & DTK_M(DAY)))
|
|
|
|
&& ((val >= 1) && (val <= 31)))
|
|
|
|
{
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- (2) match %d (%s) as day\n", val, str);
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_M(DAY);
|
|
|
|
tm->tm_mday = val;
|
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!
1997-04-02 18:36:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (!(fmask & DTK_M(YEAR)))
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumber- (2) match %d (%s) as year\n", val, str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_M(YEAR);
|
|
|
|
tm->tm_year = val;
|
|
|
|
if (tm->tm_year < 70)
|
|
|
|
{
|
|
|
|
tm->tm_year += 2000;
|
|
|
|
}
|
|
|
|
else if (tm->tm_year < 100)
|
|
|
|
{
|
|
|
|
tm->tm_year += 1900;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeNumber() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeNumberField()
|
|
|
|
* Interpret numeric string as a concatenated date field.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
char *cp;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* yyyymmdd? */
|
|
|
|
if (len == 8)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumberField- %s is 8 character date fmask=%08x tmask=%08x\n", str, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_DATE_M;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_mday = atoi(str + 6);
|
|
|
|
*(str + 6) = '\0';
|
|
|
|
tm->tm_mon = atoi(str + 4);
|
|
|
|
*(str + 4) = '\0';
|
|
|
|
tm->tm_year = atoi(str + 0);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* yymmdd or hhmmss? */
|
|
|
|
}
|
|
|
|
else if (len == 6)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumberField- %s is 6 characters fmask=%08x tmask=%08x\n", str, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
if (fmask & DTK_DATE_M)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_TIME_M;
|
|
|
|
tm->tm_sec = atoi(str + 4);
|
|
|
|
*(str + 4) = '\0';
|
|
|
|
tm->tm_min = atoi(str + 2);
|
|
|
|
*(str + 2) = '\0';
|
|
|
|
tm->tm_hour = atoi(str + 0);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumberField- %s is date field fmask=%08x tmask=%08x\n", str, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_DATE_M;
|
|
|
|
tm->tm_mday = atoi(str + 4);
|
|
|
|
*(str + 4) = '\0';
|
|
|
|
tm->tm_mon = atoi(str + 2);
|
|
|
|
*(str + 2) = '\0';
|
|
|
|
tm->tm_year = atoi(str + 0);
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (strchr(str, '.') != NULL)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeNumberField- %s is time field fmask=%08x tmask=%08x\n", str, fmask, *tmask);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
*tmask = DTK_TIME_M;
|
|
|
|
tm->tm_sec = strtod((str + 4), &cp);
|
|
|
|
if (cp == (str + 4))
|
|
|
|
return -1;
|
|
|
|
if (*cp == '.')
|
|
|
|
{
|
|
|
|
*fsec = strtod(cp, NULL);
|
|
|
|
}
|
|
|
|
*(str + 4) = '\0';
|
|
|
|
tm->tm_min = strtod((str + 2), &cp);
|
|
|
|
*(str + 2) = '\0';
|
|
|
|
tm->tm_hour = strtod((str + 0), &cp);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return 0;
|
|
|
|
} /* DecodeNumberField() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeTimezone()
|
|
|
|
* Interpret string as a numeric timezone.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeTimezone(char *str, int *tzp)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int tz;
|
|
|
|
int hr,
|
|
|
|
min;
|
|
|
|
char *cp;
|
|
|
|
int len;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* assume leading character is "+" or "-" */
|
|
|
|
hr = strtol((str + 1), &cp, 10);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* explicit delimiter? */
|
|
|
|
if (*cp == ':')
|
|
|
|
{
|
|
|
|
min = strtol((cp + 1), &cp, 10);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* otherwise, might have run things together... */
|
|
|
|
}
|
|
|
|
else if ((*cp == '\0') && ((len = strlen(str)) > 3))
|
|
|
|
{
|
|
|
|
min = strtol((str + len - 2), &cp, 10);
|
|
|
|
*(str + len - 2) = '\0';
|
|
|
|
hr = strtol((str + 1), &cp, 10);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
min = 0;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
tz = (hr * 60 + min) * 60;
|
|
|
|
if (*str == '-')
|
|
|
|
tz = -tz;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*tzp = -tz;
|
|
|
|
return (*cp != '\0');
|
|
|
|
} /* DecodeTimezone() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeSpecial()
|
|
|
|
* Decode text string using lookup table.
|
|
|
|
* Implement a cache lookup since it is likely that dates
|
1997-09-07 05:04:48 +00:00
|
|
|
* will be related in format.
|
1997-03-14 23:21:12 +00:00
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-03-14 23:21:12 +00:00
|
|
|
DecodeSpecial(int field, char *lowtoken, int *val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int type;
|
|
|
|
datetkn *tp;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#if USE_DATE_CACHE
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((datecache[field] != NULL)
|
|
|
|
&& (strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0))
|
|
|
|
{
|
|
|
|
tp = datecache[field];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
|
1997-03-14 23:21:12 +00:00
|
|
|
#if USE_DATE_CACHE
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
datecache[field] = tp;
|
|
|
|
#endif
|
|
|
|
if (tp == NULL)
|
|
|
|
{
|
|
|
|
type = IGNORE;
|
|
|
|
*val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
type = tp->type;
|
|
|
|
switch (type)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case TZ:
|
|
|
|
case DTZ:
|
|
|
|
case DTZMOD:
|
|
|
|
*val = FROMVAL(tp);
|
|
|
|
break;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
*val = tp->value;
|
|
|
|
break;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (type);
|
|
|
|
} /* DecodeSpecial() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeDateDelta()
|
|
|
|
* Interpret previously parsed fields for general time interval.
|
|
|
|
* Return 0 if decoded and -1 if problems.
|
|
|
|
*
|
|
|
|
* If code is changed to read fields from first to last,
|
1997-09-07 05:04:48 +00:00
|
|
|
* then use READ_FORWARD-bracketed code to allow sign
|
|
|
|
* to persist to subsequent unsigned fields.
|
1997-03-14 23:21:12 +00:00
|
|
|
*/
|
|
|
|
int
|
1997-09-07 05:04:48 +00:00
|
|
|
DecodeDateDelta(char *field[], int ftype[], int nf, int *dtype, struct tm * tm, double *fsec)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int is_before = FALSE;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
#if READ_FORWARD
|
1997-09-08 02:41:22 +00:00
|
|
|
int is_neg = FALSE;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
int fmask = 0,
|
|
|
|
tmask,
|
|
|
|
type;
|
|
|
|
int i,
|
|
|
|
ii;
|
|
|
|
int flen,
|
|
|
|
val;
|
|
|
|
char *cp;
|
|
|
|
double sec;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
*dtype = DTK_DELTA;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
type = SECOND;
|
|
|
|
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;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* read through list forwards to pick up initial time fields, if any */
|
|
|
|
for (ii = 0; ii < nf; ii++)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateDelta- field[%d] is %s (type %d)\n", ii, field[ii], ftype[ii]);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
if (ftype[ii] == DTK_TIME)
|
|
|
|
{
|
|
|
|
if (DecodeTime(field[ii], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
|
|
|
fmask |= tmask;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
|
|
|
* read through remaining list backwards to pick up units before
|
|
|
|
* values
|
|
|
|
*/
|
|
|
|
for (i = nf - 1; i >= ii; i--)
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
switch (ftype[i])
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TIME:
|
|
|
|
/* already read in forward-scan above so return error */
|
1997-03-14 23:21:12 +00:00
|
|
|
#if FALSE
|
1997-09-08 02:41:22 +00:00
|
|
|
if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
|
|
|
|
return -1;
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_TZ: /* timezone is a token with a leading sign
|
1997-09-07 05:04:48 +00:00
|
|
|
* character */
|
1997-03-14 23:21:12 +00:00
|
|
|
#if READ_FORWARD
|
1997-09-08 02:41:22 +00:00
|
|
|
is_neg = (*field[i] == '-');
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_NUMBER:
|
|
|
|
val = strtol(field[i], &cp, 10);
|
1997-03-14 23:21:12 +00:00
|
|
|
#if READ_FORWARD
|
1997-09-08 02:41:22 +00:00
|
|
|
if (is_neg && (val > 0))
|
|
|
|
val = -val;
|
1997-09-07 05:04:48 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
if (*cp == '.')
|
|
|
|
{
|
|
|
|
*fsec = strtod(cp, NULL);
|
|
|
|
if (val < 0)
|
|
|
|
*fsec = -(*fsec);
|
|
|
|
}
|
|
|
|
flen = strlen(field[i]);
|
|
|
|
tmask = 0; /* DTK_M(type); */
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case DTK_MICROSEC:
|
|
|
|
*fsec += (val * 1e-6);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MILLISEC:
|
|
|
|
*fsec += (val * 1e-3);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_SECOND:
|
|
|
|
tm->tm_sec += val;
|
|
|
|
tmask = DTK_M(SECOND);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MINUTE:
|
|
|
|
tm->tm_min += val;
|
|
|
|
tmask = DTK_M(MINUTE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_HOUR:
|
|
|
|
tm->tm_hour += val;
|
|
|
|
tmask = DTK_M(HOUR);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DAY:
|
|
|
|
tm->tm_mday += val;
|
|
|
|
tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_WEEK:
|
|
|
|
tm->tm_mday += val * 7;
|
|
|
|
tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MONTH:
|
|
|
|
tm->tm_mon += val;
|
|
|
|
tmask = DTK_M(MONTH);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_YEAR:
|
|
|
|
tm->tm_year += val;
|
|
|
|
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_DECADE:
|
|
|
|
tm->tm_year += val * 10;
|
|
|
|
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_CENTURY:
|
|
|
|
tm->tm_year += val * 100;
|
|
|
|
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DTK_MILLENIUM:
|
|
|
|
tm->tm_year += val * 1000;
|
|
|
|
tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
break;
|
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case DTK_STRING:
|
|
|
|
case DTK_SPECIAL:
|
|
|
|
type = DecodeUnits(i, field[i], &val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeDateDelta- special field[%d] %s type=%d value=%d\n", i, field[i], type, val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
if (type == IGNORE)
|
|
|
|
continue;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
tmask = 0; /* DTK_M(type); */
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case UNITS:
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-08 02:41:22 +00:00
|
|
|
printf("DecodeDateDelta- UNITS field %s value is %d\n", field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-08 02:41:22 +00:00
|
|
|
type = val;
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
case AGO:
|
|
|
|
is_before = TRUE;
|
|
|
|
type = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESERV:
|
|
|
|
tmask = (DTK_DATE_M || DTK_TIME_M);
|
|
|
|
*dtype = val;
|
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-08 02:41:22 +00:00
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
break;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateDelta- (%08x/%08x) field[%d] %s value is %d\n",
|
|
|
|
fmask, tmask, i, field[i], val);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tmask & fmask)
|
|
|
|
return -1;
|
|
|
|
fmask |= tmask;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (*fsec != 0)
|
|
|
|
{
|
|
|
|
TMODULO(*fsec, sec, 1);
|
|
|
|
tm->tm_sec += sec;
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (is_before)
|
|
|
|
{
|
|
|
|
*fsec = -(*fsec);
|
|
|
|
tm->tm_sec = -(tm->tm_sec);
|
|
|
|
tm->tm_min = -(tm->tm_min);
|
|
|
|
tm->tm_hour = -(tm->tm_hour);
|
|
|
|
tm->tm_mday = -(tm->tm_mday);
|
|
|
|
tm->tm_mon = -(tm->tm_mon);
|
|
|
|
tm->tm_year = -(tm->tm_year);
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("DecodeDateDelta- mask %08x (%08x)", fmask, DTK_DATE_M);
|
|
|
|
printf(" set y%04d m%02d d%02d", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
|
|
|
printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* ensure that at least one time field has been found */
|
|
|
|
return ((fmask != 0) ? 0 : -1);
|
|
|
|
} /* DecodeDateDelta() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* DecodeUnits()
|
|
|
|
* Decode text string using lookup table.
|
|
|
|
* This routine supports time interval decoding.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
1997-03-14 23:21:12 +00:00
|
|
|
DecodeUnits(int field, char *lowtoken, int *val)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int type;
|
|
|
|
datetkn *tp;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#if USE_DATE_CACHE
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((deltacache[field] != NULL)
|
|
|
|
&& (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0))
|
|
|
|
{
|
|
|
|
tp = deltacache[field];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
|
1997-03-14 23:21:12 +00:00
|
|
|
#if USE_DATE_CACHE
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
deltacache[field] = tp;
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tp == NULL)
|
|
|
|
{
|
|
|
|
type = IGNORE;
|
|
|
|
*val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
type = tp->type;
|
|
|
|
if ((type == TZ) || (type == DTZ))
|
|
|
|
{
|
|
|
|
*val = FROMVAL(tp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*val = tp->value;
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (type);
|
|
|
|
} /* DecodeUnits() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
/* datebsearch()
|
1997-03-14 23:21:12 +00:00
|
|
|
* Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
|
|
|
|
* is WAY faster than the generic bsearch().
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static datetkn *
|
1997-09-08 21:56:23 +00:00
|
|
|
datebsearch(char *key, datetkn *base, unsigned int nel)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
register datetkn *last = base + nel - 1,
|
1997-09-08 02:41:22 +00:00
|
|
|
*position;
|
|
|
|
register int result;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
while (last >= base)
|
|
|
|
{
|
|
|
|
position = base + ((last - base) >> 1);
|
|
|
|
result = key[0] - position->token[0];
|
|
|
|
if (result == 0)
|
|
|
|
{
|
|
|
|
result = strncmp(key, position->token, TOKMAXLEN);
|
|
|
|
if (result == 0)
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
if (result < 0)
|
|
|
|
last = position - 1;
|
|
|
|
else
|
|
|
|
base = position + 1;
|
1997-03-14 23:21:12 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
return NULL;
|
1997-03-14 23:21:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
/* EncodeSpecialDateTime()
|
|
|
|
* Convert reserved datetime data type to string.
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static int
|
|
|
|
EncodeSpecialDateTime(DateTime dt, char *str)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
if (DATETIME_IS_RESERVED(dt))
|
|
|
|
{
|
|
|
|
if (DATETIME_IS_INVALID(dt))
|
|
|
|
{
|
|
|
|
strcpy(str, INVALID);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (DATETIME_IS_NOBEGIN(dt))
|
|
|
|
{
|
|
|
|
strcpy(str, EARLY);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (DATETIME_IS_NOEND(dt))
|
|
|
|
{
|
|
|
|
strcpy(str, LATE);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (DATETIME_IS_CURRENT(dt))
|
|
|
|
{
|
|
|
|
strcpy(str, DCURRENT);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else if (DATETIME_IS_EPOCH(dt))
|
|
|
|
{
|
|
|
|
strcpy(str, EPOCH);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeSpecialDateTime- unrecognized date\n");
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
strcpy(str, INVALID);
|
|
|
|
}
|
|
|
|
return (TRUE);
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (FALSE);
|
|
|
|
} /* EncodeSpecialDateTime() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
1997-07-01 00:22:46 +00:00
|
|
|
/* EncodeDateOnly()
|
|
|
|
* Encode date as local time.
|
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
EncodeDateOnly(struct tm * tm, int style, char *str)
|
1997-07-01 00:22:46 +00:00
|
|
|
{
|
|
|
|
#if FALSE
|
1997-09-08 02:41:22 +00:00
|
|
|
int day;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
|
|
|
|
return -1;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* compatible with ISO date formats */
|
|
|
|
if (style == USE_ISO_DATES)
|
|
|
|
{
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf(str, "%04d-%02d-%02d",
|
|
|
|
tm->tm_year, tm->tm_mon, tm->tm_mday);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(str, "%04d-%02d-%02d %s",
|
|
|
|
-(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* compatible with Oracle/Ingres date formats */
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else if (style == USE_SQL_DATES)
|
|
|
|
{
|
|
|
|
if (EuroDates)
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
|
|
|
|
}
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "/%04d", tm->tm_year);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "/%04d %s", -(tm->tm_year - 1), "BC");
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* backward-compatible with traditional Postgres abstime dates */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* if (style == USE_POSTGRES_DATES) */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#if FALSE
|
1997-09-07 05:04:48 +00:00
|
|
|
day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
1997-07-01 00:22:46 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateOnly- day is %d\n", day);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_wday = j2day(day);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
strncpy(str, days[tm->tm_wday], 3);
|
|
|
|
strcpy((str + 3), " ");
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (EuroDates)
|
|
|
|
{
|
|
|
|
sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);
|
|
|
|
}
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 10), " %04d", tm->tm_year);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 10), " %04d %s", -(tm->tm_year - 1), "BC");
|
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* traditional date-only style for Postgres */
|
|
|
|
if (EuroDates)
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday);
|
|
|
|
}
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "-%04d", tm->tm_year);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "-%04d %s", -(tm->tm_year - 1), "BC");
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateOnly- date result is %s\n", str);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (TRUE);
|
|
|
|
} /* EncodeDateOnly() */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* EncodeTimeOnly()
|
|
|
|
* Encode time fields only.
|
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str)
|
1997-07-01 00:22:46 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double sec;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
|
|
|
|
return -1;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
sec = (tm->tm_sec + fsec);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min);
|
|
|
|
sprintf((str + 6), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeTimeOnly- time result is %s\n", str);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (TRUE);
|
|
|
|
} /* EncodeTimeOnly() */
|
1997-07-01 00:22:46 +00:00
|
|
|
|
|
|
|
|
1997-04-22 17:36:57 +00:00
|
|
|
/* EncodeDateTime()
|
|
|
|
* Encode date and time interpreted as local time.
|
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str)
|
1997-03-14 23:21:12 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int day,
|
|
|
|
hour,
|
|
|
|
min;
|
|
|
|
double sec;
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
|
|
|
|
return -1;
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
sec = (tm->tm_sec + fsec);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
1997-04-25 18:40:50 +00:00
|
|
|
#ifdef USE_POSIX_TIME
|
|
|
|
#ifdef HAVE_INT_TIMEZONE
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n",
|
|
|
|
*tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight);
|
1997-04-25 18:40:50 +00:00
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n",
|
|
|
|
*tzn, tm->tm_zone, (-tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
|
|
|
#else
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n",
|
|
|
|
*tzn, CTZName, CTimeZone, CDayLight);
|
1997-04-25 18:40:50 +00:00
|
|
|
#endif
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* compatible with ISO date formats */
|
|
|
|
if (style == USE_ISO_DATES)
|
|
|
|
{
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf(str, "%04d-%02d-%02d %02d:%02d:",
|
|
|
|
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
|
|
|
|
sprintf((str + 17), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);
|
|
|
|
|
|
|
|
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
|
|
|
|
{
|
|
|
|
if (tzp != NULL)
|
|
|
|
{
|
|
|
|
hour = -(*tzp / 3600);
|
|
|
|
min = ((abs(*tzp) / 60) % 60);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hour = 0;
|
|
|
|
min = 0;
|
|
|
|
}
|
|
|
|
sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
|
|
|
|
}
|
1997-04-25 18:40:50 +00:00
|
|
|
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (tm->tm_hour || tm->tm_min)
|
|
|
|
{
|
|
|
|
sprintf(str, "%04d-%02d-%02d %02d:%02d %s",
|
|
|
|
-(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, "BC");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(str, "%04d-%02d-%02d %s",
|
|
|
|
-(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
|
|
|
|
}
|
|
|
|
}
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* compatible with Oracle/Ingres date formats */
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else if (style == USE_SQL_DATES)
|
|
|
|
{
|
|
|
|
if (EuroDates)
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
|
|
|
|
}
|
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "/%04d %02d:%02d:%05.2f",
|
|
|
|
tm->tm_year, tm->tm_hour, tm->tm_min, sec);
|
1997-03-14 23:21:12 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
|
|
|
|
{
|
|
|
|
strcpy((str + 22), " ");
|
|
|
|
strcpy((str + 23), *tzn);
|
|
|
|
}
|
1997-04-25 18:40:50 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 5), "/%04d %02d:%02d %s",
|
|
|
|
-(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC");
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/* backward-compatible with traditional Postgres abstime dates */
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else
|
|
|
|
{ /* if (style == USE_POSTGRES_DATES) */
|
|
|
|
day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
1997-07-01 00:22:46 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateTime- day is %d\n", day);
|
1997-07-01 00:22:46 +00:00
|
|
|
#endif
|
1997-09-07 05:04:48 +00:00
|
|
|
tm->tm_wday = j2day(day);
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
strncpy(str, days[tm->tm_wday], 3);
|
|
|
|
strcpy((str + 3), " ");
|
1997-07-01 00:22:46 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
if (EuroDates)
|
|
|
|
{
|
|
|
|
sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
if (tm->tm_year > 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
|
|
|
|
if (fsec != 0)
|
|
|
|
{
|
|
|
|
sprintf((str + 16), ":%05.2f %04d", sec, tm->tm_year);
|
|
|
|
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
|
|
|
|
{
|
|
|
|
strcpy((str + 27), " ");
|
|
|
|
strcpy((str + 28), *tzn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 16), ":%02.0f %04d", sec, tm->tm_year);
|
|
|
|
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
|
|
|
|
{
|
|
|
|
strcpy((str + 24), " ");
|
|
|
|
strcpy((str + 25), *tzn);
|
|
|
|
}
|
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf((str + 10), " %02d:%02d %04d %s",
|
|
|
|
tm->tm_hour, tm->tm_min, -(tm->tm_year - 1), "BC");
|
|
|
|
}
|
1997-09-05 18:13:45 +00:00
|
|
|
}
|
1997-03-25 08:11:24 +00:00
|
|
|
|
1997-03-14 23:21:12 +00:00
|
|
|
#ifdef DATEDEBUG
|
1997-09-07 05:04:48 +00:00
|
|
|
printf("EncodeDateTime- date result is %s\n", str);
|
1997-03-14 23:21:12 +00:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (TRUE);
|
|
|
|
} /* EncodeDateTime() */
|
1997-03-14 23:21:12 +00:00
|
|
|
|
|
|
|
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
/* EncodeTimeSpan()
|
|
|
|
* Interpret time structure as a delta time and convert to string.
|
|
|
|
*
|
|
|
|
* Pass a flag to specify the style of string, but only implement
|
1997-09-07 05:04:48 +00:00
|
|
|
* the traditional Postgres style for now. - tgl 97/03/27
|
From: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [HACKERS] abstime "now" broken
Yes, I broke 'now' :( with an attempt at a bug fix involving
servers running in the UTC/GMT timezone. These patches fix
the problem, and have been tested in GMT (+00 hours),
PST (-08), and NZT (+12) timezones which exercized the code for
various cases including across day boundaries. btw, this code
fixes the same type of problem for 'today', 'yesterday', 'tomorrow',
for DATETIME, ABSTIME, DATE and TIME types.
The bugfix itself is quite small, but I have accumulated other
changes in the datetime data type and include them here also.
One set of changes involves printing ISO-formatted dates and
is in response to the helpful information from Kurt Lidl regarding
ANSI SQL dates. I'll send another e-mail sometime soon discussing
more issues he has raised...
1997-03-28 07:13:21 +00:00
|
|
|
*/
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
int is_before = FALSE;
|
|
|
|
int is_nonzero = FALSE;
|
|
|
|
char *cp;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
strcpy(str, "@");
|
|
|
|
cp = str + strlen(str);
|
|
|
|
|
|
|
|
if (tm->tm_year != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_year < 0);
|
|
|
|
sprintf(cp, " %d year%s", abs(tm->tm_year), ((abs(tm->tm_year) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tm->tm_mon != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_mon < 0);
|
|
|
|
sprintf(cp, " %d mon%s", abs(tm->tm_mon), ((abs(tm->tm_mon) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tm->tm_mday != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_mday < 0);
|
|
|
|
sprintf(cp, " %d day%s", abs(tm->tm_mday), ((abs(tm->tm_mday) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tm->tm_hour != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_hour < 0);
|
|
|
|
sprintf(cp, " %d hour%s", abs(tm->tm_hour), ((abs(tm->tm_hour) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tm->tm_min != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_min < 0);
|
|
|
|
sprintf(cp, " %d min%s", abs(tm->tm_min), ((abs(tm->tm_min) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fractional seconds? */
|
|
|
|
if (fsec != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
fsec += tm->tm_sec;
|
|
|
|
is_before |= (fsec < 0);
|
|
|
|
sprintf(cp, " %.2f secs", fabs(fsec));
|
|
|
|
cp += strlen(cp);
|
|
|
|
|
|
|
|
/* otherwise, integer seconds only? */
|
|
|
|
}
|
|
|
|
else if (tm->tm_sec != 0)
|
|
|
|
{
|
|
|
|
is_nonzero = TRUE;
|
|
|
|
is_before |= (tm->tm_sec < 0);
|
|
|
|
sprintf(cp, " %d sec%s", abs(tm->tm_sec), ((abs(tm->tm_sec) != 1) ? "s" : ""));
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* identically zero? then put in a unitless zero... */
|
|
|
|
if (!is_nonzero)
|
|
|
|
{
|
|
|
|
strcat(cp, " 0");
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_before)
|
|
|
|
{
|
|
|
|
strcat(cp, " ago");
|
|
|
|
cp += strlen(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DATEDEBUG
|
|
|
|
printf("EncodeTimeSpan- result is %s\n", str);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} /* EncodeTimeSpan() */
|
1997-07-29 14:09:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
#if defined(linux) && defined(PPC)
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
datetime_is_epoch(double j)
|
1997-07-29 14:09:11 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
static union
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double epoch;
|
|
|
|
unsigned char c[8];
|
|
|
|
} u;
|
1997-07-29 14:09:11 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
u.c[0] = 0x80; /* sign bit */
|
|
|
|
u.c[1] = 0x10; /* DBL_MIN */
|
1997-07-29 14:09:11 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (j == u.epoch);
|
1997-07-29 14:09:11 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
int
|
|
|
|
datetime_is_current(double j)
|
1997-07-29 14:09:11 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
static union
|
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
double current;
|
|
|
|
unsigned char c[8];
|
|
|
|
} u;
|
1997-07-29 14:09:11 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
u.c[1] = 0x10; /* DBL_MIN */
|
1997-07-29 14:09:11 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return (j == u.current);
|
1997-07-29 14:09:11 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1997-07-29 14:09:11 +00:00
|
|
|
#endif
|