Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1934055

Browse files
committed
Please find a small patch to fix the brain damage "century" and
"millennium" date part implementation in postgresql, both in the code and the documentation, so that it conforms to the official definition. If you do not agree with the official definition, please send your complaint to "pope@vatican.org". I'm not responsible for them;-) With the previous version, the centuries and millenniums had a wrong number and started the wrong year. Moreover century number 0, which does not exist in reality, lasted 200 years. Also, millennium number 0 lasted 2000 years. If you want postgresql to have it's own definition of "century" and "millennium" that does not conform to the one of the society, just give them another name. I would suggest "pgCENTURY" and "pgMILLENNIUM";-) IMO, if someone may use the options, it means that postgresql is used for historical data, so it make sense to have an historical definition. Also, I just want to divide the year by 100 or 1000, I can do that quite easily. BACKWARD INCOMPATIBLE CHANGE Fabien Coelho - coelho@cri.ensmp.fr
1 parent 296f485 commit 1934055

File tree

4 files changed

+176
-14
lines changed

4 files changed

+176
-14
lines changed

doc/src/sgml/func.sgml

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.196 2004/03/30 15:53:18 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.197 2004/04/10 18:02:59 momjian Exp $
33
PostgreSQL documentation
44
-->
55

@@ -4948,18 +4948,31 @@ EXTRACT (<replaceable>field</replaceable> FROM <replaceable>source</replaceable>
49484948
<term><literal>century</literal></term>
49494949
<listitem>
49504950
<para>
4951-
The year field divided by 100
4951+
The historical definition of a century.
49524952
</para>
49534953

49544954
<screen>
4955-
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
4955+
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');
49564956
<lineannotation>Result: </lineannotation><computeroutput>20</computeroutput>
4957+
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
4958+
<lineannotation>Result: </lineannotation><computeroutput>21</computeroutput>
49574959
</screen>
49584960

49594961
<para>
4960-
Note that the result for the century field is simply the year field
4961-
divided by 100, and not the conventional definition which puts most
4962-
years in the 1900's in the twentieth century.
4962+
An historical century is a period of 100 years.
4963+
The first century starts at 0001-01-01 00:00:00 AD, although
4964+
they did not know at the time. This definition applies to all
4965+
Gregorian calendar countries. There is no number 0 century,
4966+
you go from -1 to 1.
4967+
4968+
If you disagree with this, please write your complaint to:
4969+
Pope, Cathedral Saint-Peter of Roma, Vatican.
4970+
</para>
4971+
4972+
<para>
4973+
Compatibility: if you want the previous postgres version of century,
4974+
just divide the year by 100. Note that with this definition,
4975+
century number 0 lasts 200 years.
49634976
</para>
49644977
</listitem>
49654978
</varlistentry>
@@ -5083,18 +5096,17 @@ SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
50835096
<term><literal>millennium</literal></term>
50845097
<listitem>
50855098
<para>
5086-
The year field divided by 1000
5099+
The conventional historical millennium.
50875100
</para>
50885101

50895102
<screen>
50905103
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
5091-
<lineannotation>Result: </lineannotation><computeroutput>2</computeroutput>
5104+
<lineannotation>Result: </lineannotation><computeroutput>3</computeroutput>
50925105
</screen>
50935106

50945107
<para>
5095-
Note that the result for the millennium field is simply the year field
5096-
divided by 1000, and not the conventional definition which puts
5097-
years in the 1900's in the second millennium.
5108+
Years in the 1900's are in the second millennium.
5109+
The third millennium starts January 1, 2001.
50985110
</para>
50995111
</listitem>
51005112
</varlistentry>

src/backend/utils/adt/timestamp.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.103 2004/03/30 15:53:18 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.104 2004/04/10 18:02:59 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3273,11 +3273,23 @@ timestamp_part(PG_FUNCTION_ARGS)
32733273
break;
32743274

32753275
case DTK_CENTURY:
3276-
result = (tm->tm_year / 100);
3276+
/* centuries AD, c>0: year in [ (c-1)*100+1 : c*100 ]
3277+
* centuries BC, c<0: year in [ c*100 : (c+1)*100-1 ]
3278+
* there is no number 0 century.
3279+
*/
3280+
if (tm->tm_year > 0)
3281+
result = ((tm->tm_year+99) / 100);
3282+
else
3283+
/* caution: C division may yave negative remainder */
3284+
result = - ((99 - (tm->tm_year-1))/100);
32773285
break;
32783286

32793287
case DTK_MILLENNIUM:
3280-
result = (tm->tm_year / 1000);
3288+
/* see comments above. */
3289+
if (tm->tm_year > 0)
3290+
result = ((tm->tm_year+999) / 1000);
3291+
else
3292+
result = - ((999 - (tm->tm_year-1))/1000);
32813293
break;
32823294

32833295
case DTK_JULIAN:

src/test/regress/expected/date.out

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,3 +819,114 @@ SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
819819
2
820820
(1 row)
821821

822+
--
823+
-- test extract!
824+
--
825+
-- century
826+
--
827+
SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2
828+
date_part
829+
-----------
830+
-2
831+
(1 row)
832+
833+
SELECT EXTRACT(CENTURY FROM DATE '0100-12-31 BC'); -- -1
834+
date_part
835+
-----------
836+
-1
837+
(1 row)
838+
839+
SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); -- -1
840+
date_part
841+
-----------
842+
-1
843+
(1 row)
844+
845+
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01'); -- 1
846+
date_part
847+
-----------
848+
1
849+
(1 row)
850+
851+
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); -- 1
852+
date_part
853+
-----------
854+
1
855+
(1 row)
856+
857+
SELECT EXTRACT(CENTURY FROM DATE '1900-12-31'); -- 19
858+
date_part
859+
-----------
860+
19
861+
(1 row)
862+
863+
SELECT EXTRACT(CENTURY FROM DATE '1901-01-01'); -- 20
864+
date_part
865+
-----------
866+
20
867+
(1 row)
868+
869+
SELECT EXTRACT(CENTURY FROM DATE '2000-12-31'); -- 20
870+
date_part
871+
-----------
872+
20
873+
(1 row)
874+
875+
SELECT EXTRACT(CENTURY FROM DATE '2001-01-01'); -- 21
876+
date_part
877+
-----------
878+
21
879+
(1 row)
880+
881+
SELECT EXTRACT(CENTURY FROM CURRENT_DATE)>=21 AS True; -- true
882+
true
883+
------
884+
t
885+
(1 row)
886+
887+
--
888+
-- millennium
889+
--
890+
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-12-31 BC'); -- -1
891+
date_part
892+
-----------
893+
-1
894+
(1 row)
895+
896+
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-01-01 AD'); -- 1
897+
date_part
898+
-----------
899+
1
900+
(1 row)
901+
902+
SELECT EXTRACT(MILLENNIUM FROM DATE '1000-12-31'); -- 1
903+
date_part
904+
-----------
905+
1
906+
(1 row)
907+
908+
SELECT EXTRACT(MILLENNIUM FROM DATE '1001-01-01'); -- 2
909+
date_part
910+
-----------
911+
2
912+
(1 row)
913+
914+
SELECT EXTRACT(MILLENNIUM FROM DATE '2000-12-31'); -- 2
915+
date_part
916+
-----------
917+
2
918+
(1 row)
919+
920+
SELECT EXTRACT(MILLENNIUM FROM DATE '2001-01-01'); -- 3
921+
date_part
922+
-----------
923+
3
924+
(1 row)
925+
926+
-- next test to be fixed on the turn of the next millennium;-)
927+
SELECT EXTRACT(MILLENNIUM FROM CURRENT_DATE); -- 3
928+
date_part
929+
-----------
930+
3
931+
(1 row)
932+

src/test/regress/sql/date.sql

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,30 @@ SELECT date 'tomorrow' - date 'today' AS "One day";
208208
SELECT date 'today' - date 'yesterday' AS "One day";
209209

210210
SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
211+
212+
--
213+
-- test extract!
214+
--
215+
-- century
216+
--
217+
SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2
218+
SELECT EXTRACT(CENTURY FROM DATE '0100-12-31 BC'); -- -1
219+
SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); -- -1
220+
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01'); -- 1
221+
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); -- 1
222+
SELECT EXTRACT(CENTURY FROM DATE '1900-12-31'); -- 19
223+
SELECT EXTRACT(CENTURY FROM DATE '1901-01-01'); -- 20
224+
SELECT EXTRACT(CENTURY FROM DATE '2000-12-31'); -- 20
225+
SELECT EXTRACT(CENTURY FROM DATE '2001-01-01'); -- 21
226+
SELECT EXTRACT(CENTURY FROM CURRENT_DATE)>=21 AS True; -- true
227+
--
228+
-- millennium
229+
--
230+
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-12-31 BC'); -- -1
231+
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-01-01 AD'); -- 1
232+
SELECT EXTRACT(MILLENNIUM FROM DATE '1000-12-31'); -- 1
233+
SELECT EXTRACT(MILLENNIUM FROM DATE '1001-01-01'); -- 2
234+
SELECT EXTRACT(MILLENNIUM FROM DATE '2000-12-31'); -- 2
235+
SELECT EXTRACT(MILLENNIUM FROM DATE '2001-01-01'); -- 3
236+
-- next test to be fixed on the turn of the next millennium;-)
237+
SELECT EXTRACT(MILLENNIUM FROM CURRENT_DATE); -- 3

0 commit comments

Comments
 (0)