mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Attached is the new patch. To summarize:
- new function justify_interval(interval) - modified function justify_hours(interval) - modified function justify_days(interval) These functions are defined to meet the requirements as discussed in this thread. Specifically: - justify_hours makes certain the sign bit on the hours matches the sign bit on the days. It only checks the sign bit on the days, and not the months, when determining if the hours should be positive or negative. After the call, -24 < hours < 24. - justify_days makes certain the sign bit on the days matches the sign bit on the months. It's behavior does not depend on the hours, nor does it modify the hours. After the call, -30 < days < 30. - justify_interval makes sure the sign bits on all three fields months, days, and hours are all the same. After the call, -24 < hours < 24 AND -30 < days < 30. Mark Dilger
This commit is contained in:
parent
19c21d115d
commit
d69b163247
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.309 2006/03/06 04:53:50 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.310 2006/03/06 22:49:15 momjian Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -5287,11 +5287,14 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
||||
<indexterm>
|
||||
<primary>isfinite</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>justify_days</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>justify_hours</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>justify_days</primary>
|
||||
<primary>justify_interval</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>localtime</primary>
|
||||
@ -5429,6 +5432,14 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
||||
<entry><literal>true</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal><function>justify_days</function>(<type>interval</type>)</literal></entry>
|
||||
<entry><type>interval</type></entry>
|
||||
<entry>Adjust interval so 30-day time periods are represented as months</entry>
|
||||
<entry><literal>justify_days(interval '30 days')</literal></entry>
|
||||
<entry><literal>1 month</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal><function>justify_hours</function>(<type>interval</type>)</literal></entry>
|
||||
<entry><type>interval</type></entry>
|
||||
@ -5438,11 +5449,11 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><literal><function>justify_days</function>(<type>interval</type>)</literal></entry>
|
||||
<entry><literal><function>justify_interval</function>(<type>interval</type>)</literal></entry>
|
||||
<entry><type>interval</type></entry>
|
||||
<entry>Adjust interval so 30-day time periods are represented as months</entry>
|
||||
<entry><literal>justify_days(interval '30 days')</literal></entry>
|
||||
<entry><literal>1 month</literal></entry>
|
||||
<entry>Adjust interval using <function>justify_days</> and <function>justify_hours</>, with additional sign adjustments</></entry>
|
||||
<entry><literal>justify_interval(interval '1 mon -1 hour')</literal></entry>
|
||||
<entry><literal>29 days 23:00:00</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -5486,13 +5497,6 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
If you are using both <function>justify_hours</> and
|
||||
<function>justify_days</>, it is best to use <function>justify_hours</>
|
||||
first so any additional days will be included in the
|
||||
<function>justify_days</> calculation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In addition to these functions, the SQL <literal>OVERLAPS</> operator is
|
||||
supported:
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.161 2006/03/05 15:58:44 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.162 2006/03/06 22:49:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1974,6 +1974,82 @@ timestamp_mi(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* interval_justify_interval()
|
||||
*
|
||||
* Adjust interval so 'month', 'day', and 'time' portions are within
|
||||
* customary bounds. Specifically:
|
||||
*
|
||||
* 0 <= abs(time) < 24 hours
|
||||
* 0 <= abs(day) < 30 days
|
||||
*
|
||||
* Also, the sign bit on all three fields is made equal, so either
|
||||
* all three fields are negative or all are positive.
|
||||
*/
|
||||
Datum
|
||||
interval_justify_interval(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Interval *span = PG_GETARG_INTERVAL_P(0);
|
||||
Interval *result;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 wholeday;
|
||||
#else
|
||||
double wholeday;
|
||||
#endif
|
||||
int32 wholemonth;
|
||||
|
||||
result = (Interval *) palloc(sizeof(Interval));
|
||||
result->month = span->month;
|
||||
result->day = span->day;
|
||||
result->time = span->time;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
TMODULO(result->time, wholeday, USECS_PER_DAY);
|
||||
#else
|
||||
TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
|
||||
#endif
|
||||
result->day += wholeday; /* could overflow... */
|
||||
|
||||
wholemonth = result->day / DAYS_PER_MONTH;
|
||||
result->day -= wholemonth * DAYS_PER_MONTH;
|
||||
result->month += wholemonth;
|
||||
|
||||
if (result->month > 0 &&
|
||||
(result->day < 0 || (result->day == 0 && result->time < 0)))
|
||||
{
|
||||
result->day += DAYS_PER_MONTH;
|
||||
result->month--;
|
||||
}
|
||||
else if (result->month < 0 &&
|
||||
(result->day > 0 || (result->day == 0 && result->time > 0)))
|
||||
{
|
||||
result->day -= DAYS_PER_MONTH;
|
||||
result->month++;
|
||||
}
|
||||
|
||||
if (result->day > 0 && result->time < 0)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time += USECS_PER_DAY;
|
||||
#else
|
||||
result->time += (double) SECS_PER_DAY;
|
||||
#endif
|
||||
result->day--;
|
||||
}
|
||||
else if (result->day < 0 && result->time > 0)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time -= USECS_PER_DAY;
|
||||
#else
|
||||
result->time -= (double) SECS_PER_DAY;
|
||||
#endif
|
||||
result->day++;
|
||||
}
|
||||
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* interval_justify_hours()
|
||||
*
|
||||
@ -2006,6 +2082,25 @@ interval_justify_hours(PG_FUNCTION_ARGS)
|
||||
#endif
|
||||
result->day += wholeday; /* could overflow... */
|
||||
|
||||
if (result->day > 0 && result->time < 0)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time += USECS_PER_DAY;
|
||||
#else
|
||||
result->time += (double) SECS_PER_DAY;
|
||||
#endif
|
||||
result->day--;
|
||||
}
|
||||
else if (result->day < 0 && result->time > 0)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
result->time -= USECS_PER_DAY;
|
||||
#else
|
||||
result->time -= (double) SECS_PER_DAY;
|
||||
#endif
|
||||
result->day++;
|
||||
}
|
||||
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
@ -2031,6 +2126,17 @@ interval_justify_days(PG_FUNCTION_ARGS)
|
||||
result->day -= wholemonth * DAYS_PER_MONTH;
|
||||
result->month += wholemonth;
|
||||
|
||||
if (result->month > 0 && result->day < 0)
|
||||
{
|
||||
result->day += DAYS_PER_MONTH;
|
||||
result->month--;
|
||||
}
|
||||
else if (result->month < 0 && result->day > 0)
|
||||
{
|
||||
result->day -= DAYS_PER_MONTH;
|
||||
result->month++;
|
||||
}
|
||||
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.318 2006/03/05 15:58:54 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.319 2006/03/06 22:49:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200602281
|
||||
#define CATALOG_VERSION_NO 200603061
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.400 2006/03/05 15:58:54 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.401 2006/03/06 22:49:16 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -1462,6 +1462,8 @@ DATA(insert OID = 1173 ( timestamptz PGNSP PGUID 12 f f t f i 1 1184 "702" _
|
||||
DESCR("convert abstime to timestamp with time zone");
|
||||
DATA(insert OID = 1174 ( timestamptz PGNSP PGUID 12 f f t f s 1 1184 "1082" _null_ _null_ _null_ date_timestamptz - _null_ ));
|
||||
DESCR("convert date to timestamp with time zone");
|
||||
DATA(insert OID = 2711 ( justify_interval PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_interval - _null_ ));
|
||||
DESCR("promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months");
|
||||
DATA(insert OID = 1175 ( justify_hours PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_hours - _null_ ));
|
||||
DESCR("promote groups of 24 hours to numbers of days");
|
||||
DATA(insert OID = 1295 ( justify_days PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_days - _null_ ));
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.58 2006/03/05 15:59:08 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.59 2006/03/06 22:49:17 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -234,6 +234,7 @@ extern Datum interval_cmp(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_hash(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_smaller(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_larger(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_justify_interval(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_justify_hours(PG_FUNCTION_ARGS);
|
||||
extern Datum interval_justify_days(PG_FUNCTION_ARGS);
|
||||
|
||||
|
@ -241,3 +241,10 @@ SELECT justify_days(interval '6 months 36 days 5 hours 4 minutes 3 seconds') as
|
||||
@ 7 mons 6 days 5 hours 4 mins 3 secs
|
||||
(1 row)
|
||||
|
||||
-- test justify_interval()
|
||||
SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour";
|
||||
1 month -1 hour
|
||||
--------------------
|
||||
@ 29 days 23 hours
|
||||
(1 row)
|
||||
|
||||
|
@ -76,3 +76,6 @@ select '4 millenniums 5 centuries 4 decades 1 year 4 months 4 days 17 minutes 31
|
||||
SELECT justify_hours(interval '6 months 3 days 52 hours 3 minutes 2 seconds') as "6 mons 5 days 4 hours 3 mins 2 seconds";
|
||||
SELECT justify_days(interval '6 months 36 days 5 hours 4 minutes 3 seconds') as "7 mons 6 days 5 hours 4 mins 3 seconds";
|
||||
|
||||
-- test justify_interval()
|
||||
|
||||
SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour";
|
||||
|
Loading…
x
Reference in New Issue
Block a user