diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 19d357651786157e5b26e1f2f4c057704df0a7ba..139c81effc3727ab630bef56727ee9f6547601b2 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.196 2004/03/30 15:53:18 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.197 2004/04/10 18:02:59 momjian Exp $ PostgreSQL documentation --> @@ -4948,18 +4948,31 @@ EXTRACT (<replaceable>field</replaceable> FROM <replaceable>source</replaceable> <term><literal>century</literal></term> <listitem> <para> - The year field divided by 100 + The historical definition of a century. </para> <screen> -SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); +SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); <lineannotation>Result: </lineannotation><computeroutput>20</computeroutput> +SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); +<lineannotation>Result: </lineannotation><computeroutput>21</computeroutput> </screen> <para> - Note that the result for the century field is simply the year field - divided by 100, and not the conventional definition which puts most - years in the 1900's in the twentieth century. + An historical century is a period of 100 years. + The first century starts at 0001-01-01 00:00:00 AD, although + they did not know at the time. This definition applies to all + Gregorian calendar countries. There is no number 0 century, + you go from -1 to 1. + + If you disagree with this, please write your complaint to: + Pope, Cathedral Saint-Peter of Roma, Vatican. + </para> + + <para> + Compatibility: if you want the previous postgres version of century, + just divide the year by 100. Note that with this definition, + century number 0 lasts 200 years. </para> </listitem> </varlistentry> @@ -5083,18 +5096,17 @@ SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5'); <term><literal>millennium</literal></term> <listitem> <para> - The year field divided by 1000 + The conventional historical millennium. </para> <screen> SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); -<lineannotation>Result: </lineannotation><computeroutput>2</computeroutput> +<lineannotation>Result: </lineannotation><computeroutput>3</computeroutput> </screen> <para> - Note that the result for the millennium field is simply the year field - divided by 1000, and not the conventional definition which puts - years in the 1900's in the second millennium. + Years in the 1900's are in the second millennium. + The third millennium starts January 1, 2001. </para> </listitem> </varlistentry> diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index dafc8ae5bedace622f141063ac7d7a4b17b28f8f..b2628a3a6f6aa4ea8fea63951607cf6175c5191a 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.103 2004/03/30 15:53:18 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.104 2004/04/10 18:02:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -3273,11 +3273,23 @@ timestamp_part(PG_FUNCTION_ARGS) break; case DTK_CENTURY: - result = (tm->tm_year / 100); + /* centuries AD, c>0: year in [ (c-1)*100+1 : c*100 ] + * centuries BC, c<0: year in [ c*100 : (c+1)*100-1 ] + * there is no number 0 century. + */ + if (tm->tm_year > 0) + result = ((tm->tm_year+99) / 100); + else + /* caution: C division may yave negative remainder */ + result = - ((99 - (tm->tm_year-1))/100); break; case DTK_MILLENNIUM: - result = (tm->tm_year / 1000); + /* see comments above. */ + if (tm->tm_year > 0) + result = ((tm->tm_year+999) / 1000); + else + result = - ((999 - (tm->tm_year-1))/1000); break; case DTK_JULIAN: diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out index 20ffaf188defcab7fabf24b1aca855a38b59ab8e..77bbdb967624ef745babdb83f95250fed8822dd2 100644 --- a/src/test/regress/expected/date.out +++ b/src/test/regress/expected/date.out @@ -819,3 +819,114 @@ SELECT date 'tomorrow' - date 'yesterday' AS "Two days"; 2 (1 row) +-- +-- test extract! +-- +-- century +-- +SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2 + date_part +----------- + -2 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '0100-12-31 BC'); -- -1 + date_part +----------- + -1 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); -- -1 + date_part +----------- + -1 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '0001-01-01'); -- 1 + date_part +----------- + 1 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); -- 1 + date_part +----------- + 1 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '1900-12-31'); -- 19 + date_part +----------- + 19 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '1901-01-01'); -- 20 + date_part +----------- + 20 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '2000-12-31'); -- 20 + date_part +----------- + 20 +(1 row) + +SELECT EXTRACT(CENTURY FROM DATE '2001-01-01'); -- 21 + date_part +----------- + 21 +(1 row) + +SELECT EXTRACT(CENTURY FROM CURRENT_DATE)>=21 AS True; -- true + true +------ + t +(1 row) + +-- +-- millennium +-- +SELECT EXTRACT(MILLENNIUM FROM DATE '0001-12-31 BC'); -- -1 + date_part +----------- + -1 +(1 row) + +SELECT EXTRACT(MILLENNIUM FROM DATE '0001-01-01 AD'); -- 1 + date_part +----------- + 1 +(1 row) + +SELECT EXTRACT(MILLENNIUM FROM DATE '1000-12-31'); -- 1 + date_part +----------- + 1 +(1 row) + +SELECT EXTRACT(MILLENNIUM FROM DATE '1001-01-01'); -- 2 + date_part +----------- + 2 +(1 row) + +SELECT EXTRACT(MILLENNIUM FROM DATE '2000-12-31'); -- 2 + date_part +----------- + 2 +(1 row) + +SELECT EXTRACT(MILLENNIUM FROM DATE '2001-01-01'); -- 3 + date_part +----------- + 3 +(1 row) + +-- next test to be fixed on the turn of the next millennium;-) +SELECT EXTRACT(MILLENNIUM FROM CURRENT_DATE); -- 3 + date_part +----------- + 3 +(1 row) + diff --git a/src/test/regress/sql/date.sql b/src/test/regress/sql/date.sql index 10bd87cadcf39a11f28d6503217112bdfbc0618b..a3cad66ed2e16d95f8ee41be25ff8fa383d8e8e6 100644 --- a/src/test/regress/sql/date.sql +++ b/src/test/regress/sql/date.sql @@ -208,3 +208,30 @@ SELECT date 'tomorrow' - date 'today' AS "One day"; SELECT date 'today' - date 'yesterday' AS "One day"; SELECT date 'tomorrow' - date 'yesterday' AS "Two days"; + +-- +-- test extract! +-- +-- century +-- +SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2 +SELECT EXTRACT(CENTURY FROM DATE '0100-12-31 BC'); -- -1 +SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); -- -1 +SELECT EXTRACT(CENTURY FROM DATE '0001-01-01'); -- 1 +SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); -- 1 +SELECT EXTRACT(CENTURY FROM DATE '1900-12-31'); -- 19 +SELECT EXTRACT(CENTURY FROM DATE '1901-01-01'); -- 20 +SELECT EXTRACT(CENTURY FROM DATE '2000-12-31'); -- 20 +SELECT EXTRACT(CENTURY FROM DATE '2001-01-01'); -- 21 +SELECT EXTRACT(CENTURY FROM CURRENT_DATE)>=21 AS True; -- true +-- +-- millennium +-- +SELECT EXTRACT(MILLENNIUM FROM DATE '0001-12-31 BC'); -- -1 +SELECT EXTRACT(MILLENNIUM FROM DATE '0001-01-01 AD'); -- 1 +SELECT EXTRACT(MILLENNIUM FROM DATE '1000-12-31'); -- 1 +SELECT EXTRACT(MILLENNIUM FROM DATE '1001-01-01'); -- 2 +SELECT EXTRACT(MILLENNIUM FROM DATE '2000-12-31'); -- 2 +SELECT EXTRACT(MILLENNIUM FROM DATE '2001-01-01'); -- 3 +-- next test to be fixed on the turn of the next millennium;-) +SELECT EXTRACT(MILLENNIUM FROM CURRENT_DATE); -- 3