mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Fix leap year and month boundary arithmetic for datetime +/- timespan;
the problem only manifests itself when adding years/months and hours when the hours:minutes:seconds pushes over midnight. Fix interpretation of times with explicit timezone when the timezone is in daylight savings time and is not the default timezone. Allow interpretation of explicit timezone when it is specified as two words: <standard time> DST". For example, "MET DST" (Middle European Time Daylight Savings Time). This syntax is found in the zic package on Linux boxes at least.
This commit is contained in:
parent
a75d6aaa41
commit
3cef45d330
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.24 1997/06/03 06:32:56 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.25 1997/06/20 17:12:54 thomas Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,7 +48,23 @@ char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
|
|||||||
* Macro to replace modf(), which is broken on some platforms.
|
* Macro to replace modf(), which is broken on some platforms.
|
||||||
*/
|
*/
|
||||||
#define TMODULO(t,q,u) {q = ((t < 0)? ceil(t / u): floor(t / u)); \
|
#define TMODULO(t,q,u) {q = ((t < 0)? ceil(t / u): floor(t / u)); \
|
||||||
if (q != 0) t -= rint(q * u);}
|
if (q != 0) t -= rint(q * u);}
|
||||||
|
|
||||||
|
void GetEpochTime( struct tm *tm);
|
||||||
|
|
||||||
|
#define UTIME_MINYEAR (1901)
|
||||||
|
#define UTIME_MINMONTH (12)
|
||||||
|
#define UTIME_MINDAY (14)
|
||||||
|
#define UTIME_MAXYEAR (2038)
|
||||||
|
#define UTIME_MAXMONTH (01)
|
||||||
|
#define UTIME_MAXDAY (18)
|
||||||
|
|
||||||
|
#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
|
||||||
|
|| ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
|
||||||
|
|| ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
|
||||||
|
&& ((y < UTIME_MAXYEAR) \
|
||||||
|
|| ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
|
||||||
|
|| ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -79,8 +95,7 @@ datetime_in(char *str)
|
|||||||
|| (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
|| (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
|
||||||
elog(WARN,"Bad datetime external representation %s",str);
|
elog(WARN,"Bad datetime external representation %s",str);
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
result = PALLOCTYPE(DateTime);
|
||||||
elog(WARN,"Memory allocation failed, can't input datetime '%s'",str);
|
|
||||||
|
|
||||||
switch (dtype) {
|
switch (dtype) {
|
||||||
case DTK_DATE:
|
case DTK_DATE:
|
||||||
@ -146,8 +161,7 @@ datetime_out(DateTime *dt)
|
|||||||
EncodeSpecialDateTime(DT_INVALID, buf);
|
EncodeSpecialDateTime(DT_INVALID, buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOC(strlen(buf)+1)))
|
result = PALLOC(strlen(buf)+1);
|
||||||
elog(WARN,"Memory allocation failed, can't output datetime",NULL);
|
|
||||||
|
|
||||||
strcpy( result, buf);
|
strcpy( result, buf);
|
||||||
|
|
||||||
@ -189,8 +203,7 @@ timespan_in(char *str)
|
|||||||
|| (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
|
|| (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
|
||||||
elog(WARN,"Bad timespan external representation '%s'",str);
|
elog(WARN,"Bad timespan external representation '%s'",str);
|
||||||
|
|
||||||
if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
|
span = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
|
|
||||||
|
|
||||||
switch (dtype) {
|
switch (dtype) {
|
||||||
case DTK_DELTA:
|
case DTK_DELTA:
|
||||||
@ -230,8 +243,7 @@ timespan_out(TimeSpan *span)
|
|||||||
if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
|
if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
|
||||||
elog(WARN,"Unable to format timespan",NULL);
|
elog(WARN,"Unable to format timespan",NULL);
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOC(strlen(buf)+1)))
|
result = PALLOC(strlen(buf)+1);
|
||||||
elog(WARN,"Memory allocation failed, can't output timespan",NULL);
|
|
||||||
|
|
||||||
strcpy( result, buf);
|
strcpy( result, buf);
|
||||||
return( result);
|
return( result);
|
||||||
@ -267,8 +279,6 @@ timespan_finite(TimeSpan *timespan)
|
|||||||
* Relational operators for datetime.
|
* Relational operators for datetime.
|
||||||
*---------------------------------------------------------*/
|
*---------------------------------------------------------*/
|
||||||
|
|
||||||
void GetEpochTime( struct tm *tm);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GetEpochTime( struct tm *tm)
|
GetEpochTime( struct tm *tm)
|
||||||
{
|
{
|
||||||
@ -556,7 +566,8 @@ timespan_ge(TimeSpan *timespan1, TimeSpan *timespan2)
|
|||||||
* actual value.
|
* actual value.
|
||||||
*---------------------------------------------------------*/
|
*---------------------------------------------------------*/
|
||||||
|
|
||||||
DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
|
DateTime *
|
||||||
|
datetime_smaller(DateTime *datetime1, DateTime *datetime2)
|
||||||
{
|
{
|
||||||
DateTime *result;
|
DateTime *result;
|
||||||
|
|
||||||
@ -568,8 +579,7 @@ DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
|
|||||||
dt1 = *datetime1;
|
dt1 = *datetime1;
|
||||||
dt2 = *datetime2;
|
dt2 = *datetime2;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
result = PALLOCTYPE(DateTime);
|
||||||
elog(WARN,"Memory allocation failed, can't find smaller date",NULL);
|
|
||||||
|
|
||||||
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
||||||
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
||||||
@ -585,7 +595,8 @@ DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
|
|||||||
return(result);
|
return(result);
|
||||||
} /* datetime_smaller() */
|
} /* datetime_smaller() */
|
||||||
|
|
||||||
DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
|
DateTime *
|
||||||
|
datetime_larger(DateTime *datetime1, DateTime *datetime2)
|
||||||
{
|
{
|
||||||
DateTime *result;
|
DateTime *result;
|
||||||
|
|
||||||
@ -597,8 +608,7 @@ DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
|
|||||||
dt1 = *datetime1;
|
dt1 = *datetime1;
|
||||||
dt2 = *datetime2;
|
dt2 = *datetime2;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
result = PALLOCTYPE(DateTime);
|
||||||
elog(WARN,"Memory allocation failed, can't find larger date",NULL);
|
|
||||||
|
|
||||||
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
||||||
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
||||||
@ -615,7 +625,8 @@ DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
|
|||||||
} /* datetime_larger() */
|
} /* datetime_larger() */
|
||||||
|
|
||||||
|
|
||||||
TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
TimeSpan *
|
||||||
|
datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
@ -627,8 +638,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
|||||||
dt1 = *datetime1;
|
dt1 = *datetime1;
|
||||||
dt2 = *datetime2;
|
dt2 = *datetime2;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
|
|
||||||
|
|
||||||
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
|
||||||
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
|
||||||
@ -654,15 +664,18 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
|
|||||||
* Then, if the next month has fewer days, set the day of month
|
* Then, if the next month has fewer days, set the day of month
|
||||||
* to the last day of month.
|
* to the last day of month.
|
||||||
*/
|
*/
|
||||||
DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
|
DateTime *
|
||||||
|
datetime_add_span(DateTime *datetime, TimeSpan *span)
|
||||||
{
|
{
|
||||||
DateTime *result;
|
DateTime *result;
|
||||||
|
DateTime dt;
|
||||||
|
int tz;
|
||||||
|
char *tzn;
|
||||||
|
|
||||||
if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
|
if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
|
result = PALLOCTYPE(DateTime);
|
||||||
elog(WARN,"Memory allocation failed, can't add dates",NULL);
|
|
||||||
|
|
||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->time);
|
printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->time);
|
||||||
@ -675,13 +688,19 @@ printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->ti
|
|||||||
DATETIME_INVALID(*result);
|
DATETIME_INVALID(*result);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
*result = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
||||||
|
|
||||||
|
#ifdef ROUND_ALL
|
||||||
|
dt = JROUND(dt + span->time);
|
||||||
|
#else
|
||||||
|
dt = span->time;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (span->month != 0) {
|
if (span->month != 0) {
|
||||||
struct tm tt, *tm = &tt;
|
struct tm tt, *tm = &tt;
|
||||||
double fsec;
|
double fsec;
|
||||||
|
|
||||||
if (datetime2tm( *result, NULL, tm, &fsec, NULL) == 0) {
|
if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
|
||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||||
#endif
|
#endif
|
||||||
@ -706,26 +725,22 @@ printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, t
|
|||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||||
#endif
|
#endif
|
||||||
if (tm2datetime( tm, fsec, NULL, result) != 0)
|
if (tm2datetime( tm, fsec, &tz, &dt) != 0)
|
||||||
elog(WARN,"Unable to add datetime and timespan",NULL);
|
elog(WARN,"Unable to add datetime and timespan",NULL);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DATETIME_INVALID(*result);
|
DATETIME_INVALID(*result);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ROUND_ALL
|
*result = dt;
|
||||||
*result = JROUND(*result + span->time);
|
|
||||||
#else
|
|
||||||
*result += span->time;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
} /* datetime_add_span() */
|
} /* datetime_add_span() */
|
||||||
|
|
||||||
DateTime *datetime_sub_span(DateTime *datetime, TimeSpan *span)
|
DateTime *
|
||||||
|
datetime_sub_span(DateTime *datetime, TimeSpan *span)
|
||||||
{
|
{
|
||||||
DateTime *result;
|
DateTime *result;
|
||||||
TimeSpan tspan;
|
TimeSpan tspan;
|
||||||
@ -742,15 +757,15 @@ DateTime *datetime_sub_span(DateTime *datetime, TimeSpan *span)
|
|||||||
} /* datetime_sub_span() */
|
} /* datetime_sub_span() */
|
||||||
|
|
||||||
|
|
||||||
TimeSpan *timespan_um(TimeSpan *timespan)
|
TimeSpan *
|
||||||
|
timespan_um(TimeSpan *timespan)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
if (!PointerIsValid(timespan))
|
if (!PointerIsValid(timespan))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
|
|
||||||
|
|
||||||
result->time = -(timespan->time);
|
result->time = -(timespan->time);
|
||||||
result->month = -(timespan->month);
|
result->month = -(timespan->month);
|
||||||
@ -759,7 +774,8 @@ TimeSpan *timespan_um(TimeSpan *timespan)
|
|||||||
} /* timespan_um() */
|
} /* timespan_um() */
|
||||||
|
|
||||||
|
|
||||||
TimeSpan *timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
|
TimeSpan *
|
||||||
|
timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
@ -768,8 +784,7 @@ TimeSpan *timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
|
|||||||
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't find smaller timespan",NULL);
|
|
||||||
|
|
||||||
if (TIMESPAN_IS_INVALID(*timespan1)) {
|
if (TIMESPAN_IS_INVALID(*timespan1)) {
|
||||||
result->time = timespan2->time;
|
result->time = timespan2->time;
|
||||||
@ -803,7 +818,8 @@ printf( "timespan_smaller- months %d %d times %f %f spans %f %f\n",
|
|||||||
return(result);
|
return(result);
|
||||||
} /* timespan_smaller() */
|
} /* timespan_smaller() */
|
||||||
|
|
||||||
TimeSpan *timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
|
TimeSpan *
|
||||||
|
timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
@ -812,8 +828,7 @@ TimeSpan *timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
|
|||||||
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't find larger timespan",NULL);
|
|
||||||
|
|
||||||
if (TIMESPAN_IS_INVALID(*timespan1)) {
|
if (TIMESPAN_IS_INVALID(*timespan1)) {
|
||||||
result->time = timespan2->time;
|
result->time = timespan2->time;
|
||||||
@ -848,15 +863,15 @@ printf( "timespan_larger- months %d %d times %f %f spans %f %f\n",
|
|||||||
} /* timespan_larger() */
|
} /* timespan_larger() */
|
||||||
|
|
||||||
|
|
||||||
TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
|
TimeSpan *
|
||||||
|
timespan_add(TimeSpan *span1, TimeSpan *span2)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't add timespans",NULL);
|
|
||||||
|
|
||||||
result->month = (span1->month + span2->month);
|
result->month = (span1->month + span2->month);
|
||||||
result->time = JROUND(span1->time + span2->time);
|
result->time = JROUND(span1->time + span2->time);
|
||||||
@ -864,15 +879,15 @@ TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
|
|||||||
return(result);
|
return(result);
|
||||||
} /* timespan_add() */
|
} /* timespan_add() */
|
||||||
|
|
||||||
TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2)
|
TimeSpan *
|
||||||
|
timespan_sub(TimeSpan *span1, TimeSpan *span2)
|
||||||
{
|
{
|
||||||
TimeSpan *result;
|
TimeSpan *result;
|
||||||
|
|
||||||
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
|
result = PALLOCTYPE(TimeSpan);
|
||||||
elog(WARN,"Memory allocation failed, can't subtract timespans",NULL);
|
|
||||||
|
|
||||||
result->month = (span1->month - span2->month);
|
result->month = (span1->month - span2->month);
|
||||||
result->time = JROUND(span1->time - span2->time);
|
result->time = JROUND(span1->time - span2->time);
|
||||||
@ -906,8 +921,7 @@ datetime_text(DateTime *datetime)
|
|||||||
|
|
||||||
len = (strlen(str)+VARHDRSZ);
|
len = (strlen(str)+VARHDRSZ);
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOC(len)))
|
result = PALLOC(len);
|
||||||
elog(WARN,"Memory allocation failed, can't convert datetime to text",NULL);
|
|
||||||
|
|
||||||
VARSIZE(result) = len;
|
VARSIZE(result) = len;
|
||||||
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
||||||
@ -964,8 +978,7 @@ timespan_text(TimeSpan *timespan)
|
|||||||
|
|
||||||
len = (strlen(str)+VARHDRSZ);
|
len = (strlen(str)+VARHDRSZ);
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOC(len)))
|
result = PALLOC(len);
|
||||||
elog(WARN,"Memory allocation failed, can't convert timespan to text",NULL);
|
|
||||||
|
|
||||||
VARSIZE(result) = len;
|
VARSIZE(result) = len;
|
||||||
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
memmove(VARDATA(result), str, (len-VARHDRSZ));
|
||||||
@ -1022,8 +1035,7 @@ datetime_part(text *units, DateTime *datetime)
|
|||||||
if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
|
if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(float64data)))
|
result = PALLOCTYPE(float64data);
|
||||||
elog(WARN,"Memory allocation failed, can't get date part",NULL);
|
|
||||||
|
|
||||||
up = VARDATA(units);
|
up = VARDATA(units);
|
||||||
lp = lowunits;
|
lp = lowunits;
|
||||||
@ -1031,6 +1043,9 @@ datetime_part(text *units, DateTime *datetime)
|
|||||||
*lp = '\0';
|
*lp = '\0';
|
||||||
|
|
||||||
type = DecodeUnits( 0, lowunits, &val);
|
type = DecodeUnits( 0, lowunits, &val);
|
||||||
|
if (type == IGNORE) {
|
||||||
|
type = DecodeSpecial( 0, lowunits, &val);
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
if (type == IGNORE) strcpy(lowunits, "(unknown)");
|
if (type == IGNORE) strcpy(lowunits, "(unknown)");
|
||||||
@ -1039,15 +1054,15 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
|
|||||||
|
|
||||||
if (DATETIME_NOT_FINITE(*datetime)) {
|
if (DATETIME_NOT_FINITE(*datetime)) {
|
||||||
#if FALSE
|
#if FALSE
|
||||||
|
/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
|
||||||
elog(WARN,"Datetime is not finite",NULL);
|
elog(WARN,"Datetime is not finite",NULL);
|
||||||
#endif
|
#endif
|
||||||
*result = 0;
|
*result = 0;
|
||||||
|
|
||||||
} else if (type == UNITS) {
|
} else {
|
||||||
|
|
||||||
dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
|
||||||
|
|
||||||
if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
|
if ((type == UNITS) && (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0)) {
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case DTK_TZ:
|
case DTK_TZ:
|
||||||
*result = tz;
|
*result = tz;
|
||||||
@ -1102,19 +1117,18 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
elog(WARN,"Datetime units %s not supported",units);
|
elog(WARN,"Datetime units %s not supported",lowunits);
|
||||||
*result = 0;
|
*result = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} else if ((type == RESERV) && (val == DTK_EPOCH)) {
|
||||||
|
DATETIME_EPOCH(*result);
|
||||||
|
*result = dt - SetDateTime(*result);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
elog(NOTICE,"Datetime out of range",NULL);
|
elog(WARN,"Datetime units %s not recognized",lowunits);
|
||||||
*result = 0;
|
*result = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
elog(WARN,"Datetime units %s not recognized",units);
|
|
||||||
*result = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
@ -1138,8 +1152,7 @@ timespan_part(text *units, TimeSpan *timespan)
|
|||||||
if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
|
if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PointerIsValid(result = PALLOCTYPE(float64data)))
|
result = PALLOCTYPE(float64data);
|
||||||
elog(WARN,"Memory allocation failed, can't get date part",NULL);
|
|
||||||
|
|
||||||
up = VARDATA(units);
|
up = VARDATA(units);
|
||||||
lp = lowunits;
|
lp = lowunits;
|
||||||
@ -1147,6 +1160,9 @@ timespan_part(text *units, TimeSpan *timespan)
|
|||||||
*lp = '\0';
|
*lp = '\0';
|
||||||
|
|
||||||
type = DecodeUnits( 0, lowunits, &val);
|
type = DecodeUnits( 0, lowunits, &val);
|
||||||
|
if (type == IGNORE) {
|
||||||
|
type = DecodeSpecial( 0, lowunits, &val);
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
if (type == IGNORE) strcpy(lowunits, "(unknown)");
|
if (type == IGNORE) strcpy(lowunits, "(unknown)");
|
||||||
@ -1221,6 +1237,12 @@ printf( "timespan_part- units %s type=%d value=%d\n", lowunits, type, val);
|
|||||||
*result = 0;
|
*result = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} 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));
|
||||||
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
elog(WARN,"Timespan units %s not recognized",units);
|
elog(WARN,"Timespan units %s not recognized",units);
|
||||||
@ -1284,7 +1306,7 @@ static datetkn datetktbl[] = {
|
|||||||
{ "dec", MONTH, 12},
|
{ "dec", MONTH, 12},
|
||||||
{ "december", MONTH, 12},
|
{ "december", MONTH, 12},
|
||||||
{ "dnt", TZ, 6}, /* Dansk Normal Tid */
|
{ "dnt", TZ, 6}, /* Dansk Normal Tid */
|
||||||
{ "dst", IGNORE, 0},
|
{ "dst", DTZMOD, 6},
|
||||||
{ "east", TZ, NEG(60)}, /* East Australian Std Time */
|
{ "east", TZ, NEG(60)}, /* East Australian Std Time */
|
||||||
{ "edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
|
{ "edt", DTZ, NEG(24)}, /* Eastern Daylight Time */
|
||||||
{ "eet", TZ, 12}, /* East. Europe, USSR Zone 1 */
|
{ "eet", TZ, 12}, /* East. Europe, USSR Zone 1 */
|
||||||
@ -1491,20 +1513,6 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
|
|||||||
* to avoid having to check year and day both. - tgl 97/05/08
|
* to avoid having to check year and day both. - tgl 97/05/08
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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))))))
|
|
||||||
|
|
||||||
#define JULIAN_MINYEAR (-4713)
|
#define JULIAN_MINYEAR (-4713)
|
||||||
#define JULIAN_MINMONTH (11)
|
#define JULIAN_MINMONTH (11)
|
||||||
#define JULIAN_MINDAY (23)
|
#define JULIAN_MINDAY (23)
|
||||||
@ -1522,7 +1530,8 @@ date2j(int y, int m, int d)
|
|||||||
- (3*((y+4900+m12)/100))/4 + d - 32075);
|
- (3*((y+4900+m12)/100))/4 + d - 32075);
|
||||||
} /* date2j() */
|
} /* date2j() */
|
||||||
|
|
||||||
void j2date( int jd, int *year, int *month, int *day)
|
void
|
||||||
|
j2date( int jd, int *year, int *month, int *day)
|
||||||
{
|
{
|
||||||
int j, y, m, d;
|
int j, y, m, d;
|
||||||
|
|
||||||
@ -1545,7 +1554,8 @@ void j2date( int jd, int *year, int *month, int *day)
|
|||||||
return;
|
return;
|
||||||
} /* j2date() */
|
} /* j2date() */
|
||||||
|
|
||||||
int j2day( int date)
|
int
|
||||||
|
j2day( int date)
|
||||||
{
|
{
|
||||||
int day;
|
int day;
|
||||||
|
|
||||||
@ -1766,19 +1776,22 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month
|
|||||||
} /* tm2timespan() */
|
} /* tm2timespan() */
|
||||||
|
|
||||||
|
|
||||||
DateTime dt2local(DateTime dt, int tz)
|
DateTime
|
||||||
|
dt2local(DateTime dt, int tz)
|
||||||
{
|
{
|
||||||
dt -= tz;
|
dt -= tz;
|
||||||
dt = JROUND(dt);
|
dt = JROUND(dt);
|
||||||
return(dt);
|
return(dt);
|
||||||
} /* dt2local() */
|
} /* dt2local() */
|
||||||
|
|
||||||
double time2t(const int hour, const int min, const double sec)
|
double
|
||||||
|
time2t(const int hour, const int min, const double sec)
|
||||||
{
|
{
|
||||||
return((((hour*60)+min)*60)+sec);
|
return((((hour*60)+min)*60)+sec);
|
||||||
} /* time2t() */
|
} /* time2t() */
|
||||||
|
|
||||||
void dt2time(DateTime jd, int *hour, int *min, double *sec)
|
void
|
||||||
|
dt2time(DateTime jd, int *hour, int *min, double *sec)
|
||||||
{
|
{
|
||||||
double time;
|
double time;
|
||||||
|
|
||||||
@ -1940,7 +1953,7 @@ DecodeDateTime( char *field[], int ftype[], int nf,
|
|||||||
tm->tm_sec = 0;
|
tm->tm_sec = 0;
|
||||||
*fsec = 0;
|
*fsec = 0;
|
||||||
tm->tm_isdst = -1; /* don't know daylight savings time status apriori */
|
tm->tm_isdst = -1; /* don't know daylight savings time status apriori */
|
||||||
if (tzp != NULL) *tzp = CTimeZone;
|
if (tzp != NULL) *tzp = 0;
|
||||||
|
|
||||||
for (i = 0; i < nf; i++) {
|
for (i = 0; i < nf; i++) {
|
||||||
#ifdef DATEDEBUG
|
#ifdef DATEDEBUG
|
||||||
@ -1995,6 +2008,7 @@ printf( "DecodeDateTime- RESERV field %s value is %d\n", field[i], val);
|
|||||||
tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
|
tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
|
||||||
*dtype = DTK_DATE;
|
*dtype = DTK_DATE;
|
||||||
GetCurrentTime(tm);
|
GetCurrentTime(tm);
|
||||||
|
if (tzp != NULL) *tzp = CTimeZone;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_YESTERDAY:
|
case DTK_YESTERDAY:
|
||||||
@ -2050,7 +2064,17 @@ printf( "DecodeDateTime- month field %s value is %d\n", field[i], val);
|
|||||||
tm->tm_mon = val;
|
tm->tm_mon = val;
|
||||||
break;
|
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:
|
case DTZ:
|
||||||
|
/* set mask for TZ here _or_ check for DTZ later when getting default timezone */
|
||||||
|
tmask |= DTK_M(TZ);
|
||||||
tm->tm_isdst = 1;
|
tm->tm_isdst = 1;
|
||||||
if (tzp == NULL) return -1;
|
if (tzp == NULL) return -1;
|
||||||
*tzp = val * 60;
|
*tzp = val * 60;
|
||||||
@ -2628,7 +2652,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
|
|||||||
*val = 0;
|
*val = 0;
|
||||||
} else {
|
} else {
|
||||||
type = tp->type;
|
type = tp->type;
|
||||||
if ((type == TZ) || (type == DTZ)) {
|
if ((type == TZ) || (type == DTZ) || (type == DTZMOD)) {
|
||||||
*val = FROMVAL(tp);
|
*val = FROMVAL(tp);
|
||||||
} else {
|
} else {
|
||||||
*val = tp->value;
|
*val = tp->value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user