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

Commit 1ace93c

Browse files
author
Thomas G. Lockhart
committed
Fix "Y-2K" problem with two-digit BC dates being corrected by two millenia.
They are not corrected now. Allow the date type to accept BC dates. Share more date/time validation declarations through dt.h.
1 parent 791822e commit 1ace93c

File tree

2 files changed

+88
-16
lines changed

2 files changed

+88
-16
lines changed

src/backend/utils/adt/datetime.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.26 1998/12/31 16:30:56 thomas Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.27 1999/01/20 16:29:39 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -27,12 +27,13 @@
2727

2828
static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn);
2929

30-
30+
#if 0
3131
static int day_tab[2][12] = {
3232
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
3333
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
3434

3535
#define isleap(y) (((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0)
36+
#endif
3637

3738
#define UTIME_MINYEAR (1901)
3839
#define UTIME_MINMONTH (12)
@@ -99,10 +100,12 @@ date_in(char *str)
99100
elog(ERROR, "Unrecognized date external representation %s", str);
100101
}
101102

103+
#if 0
102104
if (tm->tm_year < 0 || tm->tm_year > 32767)
103105
elog(ERROR, "date_in: year must be limited to values 0 through 32767 in '%s'", str);
104106
if (tm->tm_mon < 1 || tm->tm_mon > 12)
105107
elog(ERROR, "date_in: month must be limited to values 1 through 12 in '%s'", str);
108+
#endif
106109
if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
107110
elog(ERROR, "date_in: day must be limited to values 1 through %d in '%s'",
108111
day_tab[isleap(tm->tm_year)][tm->tm_mon - 1], str);

src/backend/utils/adt/dt.c

+83-14
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.61 1999/01/10 17:20:54 thomas Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.62 1999/01/20 16:29:39 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -31,11 +31,12 @@
3131
#endif
3232
#include "utils/builtins.h"
3333

34+
3435
static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
3536
static int DecodeNumber(int flen, char *field,
36-
int fmask, int *tmask, struct tm * tm, double *fsec);
37+
int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
3738
static int DecodeNumberField(int len, char *str,
38-
int fmask, int *tmask, struct tm * tm, double *fsec);
39+
int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
3940
static int DecodeSpecial(int field, char *lowtoken, int *val);
4041
static int DecodeTime(char *str, int fmask, int *tmask,
4142
struct tm * tm, double *fsec);
@@ -50,12 +51,20 @@ static double time2t(const int hour, const int min, const double sec);
5051
static int timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec);
5152
static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span);
5253

54+
5355
#define USE_DATE_CACHE 1
5456
#define ROUND_ALL 0
5557

58+
#if 0
5659
#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
5760

5861
int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
62+
#endif
63+
64+
int day_tab[2][13] = {
65+
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
66+
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
67+
5968

6069
char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
6170
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
@@ -873,13 +882,17 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
873882
}
874883

875884
/* adjust for end of month boundary problems... */
885+
#if 0
876886
if (tm->tm_mday > mdays[tm->tm_mon - 1])
877887
{
878888
if ((tm->tm_mon == 2) && isleap(tm->tm_year))
879889
tm->tm_mday = (mdays[tm->tm_mon - 1] + 1);
880890
else
881891
tm->tm_mday = mdays[tm->tm_mon - 1];
882892
}
893+
#endif
894+
if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
895+
tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
883896

884897
#ifdef DATEDEBUG
885898
printf("datetime_pl_span- date becomes %04d-%02d-%02d %02d:%02d:%02d\n",
@@ -1184,16 +1197,22 @@ datetime_age(DateTime *datetime1, DateTime *datetime2)
11841197
{
11851198
if (dt1 < dt2)
11861199
{
1200+
#if 0
11871201
tm->tm_mday += mdays[tm1->tm_mon - 1];
11881202
if (isleap(tm1->tm_year) && (tm1->tm_mon == 2))
11891203
tm->tm_mday++;
1204+
#endif
1205+
tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
11901206
tm->tm_mon--;
11911207
}
11921208
else
11931209
{
1210+
#if 0
11941211
tm->tm_mday += mdays[tm2->tm_mon - 1];
11951212
if (isleap(tm2->tm_year) && (tm2->tm_mon == 2))
11961213
tm->tm_mday++;
1214+
#endif
1215+
tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
11971216
tm->tm_mon--;
11981217
}
11991218
}
@@ -2036,7 +2055,7 @@ static datetkn datetktbl[] = {
20362055
{"adt", DTZ, NEG(18)}, /* Atlantic Daylight Time */
20372056
{"aesst", DTZ, 66}, /* E. Australia */
20382057
{"aest", TZ, 60}, /* Australia Eastern Std Time */
2039-
{"ahst", TZ, 60}, /* Alaska-Hawaii Std Time */
2058+
{"ahst", TZ, NEG(60)}, /* Alaska-Hawaii Std Time */
20402059
{"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
20412060
{"am", AMPM, AM},
20422061
{"apr", MONTH, 4},
@@ -2087,12 +2106,12 @@ static datetkn datetktbl[] = {
20872106
{"hmt", DTZ, 18}, /* Hellas ? ? */
20882107
{"hst", TZ, NEG(60)}, /* Hawaii Std Time */
20892108
{"idle", TZ, 72}, /* Intl. Date Line, East */
2090-
{"idlw", TZ, NEG(72)}, /* Intl. Date Line,, est */
2109+
{"idlw", TZ, NEG(72)}, /* Intl. Date Line, West */
20912110
{LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */
2092-
{INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for invalid
2093-
* time */
2111+
{INVALID, RESERV, DTK_INVALID},
2112+
/* "invalid" reserved for invalid time */
20942113
{"ist", TZ, 12}, /* Israel */
2095-
{"it", TZ, 22}, /* Iran Time */
2114+
{"it", TZ, 21}, /* Iran Time */
20962115
{"jan", MONTH, 1},
20972116
{"january", MONTH, 1},
20982117
{"jst", TZ, 54}, /* Japan Std Time,USSR Zone 8 */
@@ -2283,6 +2302,8 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
22832302
* These routines will be used by other date/time packages - tgl 97/02/25
22842303
*/
22852304

2305+
#if 0
2306+
XXX moved to dt.h - thomas 1999-01-15
22862307
/* Set the minimum year to one greater than the year of the first valid day
22872308
* to avoid having to check year and day both. - tgl 97/05/08
22882309
*/
@@ -2294,6 +2315,7 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
22942315
#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
22952316
|| ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
22962317
|| ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
2318+
#endif
22972319

22982320
int
22992321
date2j(int y, int m, int d)
@@ -2792,6 +2814,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
27922814
int flen,
27932815
val;
27942816
int mer = HR24;
2817+
int is2digits = FALSE;
27952818
int bc = FALSE;
27962819

27972820
*dtype = DTK_DATE;
@@ -2843,14 +2866,14 @@ DecodeDateTime(char **field, int *ftype, int nf,
28432866
* then interpret as a concatenated date or time... */
28442867
if ((flen > 4) && !((fmask & DTK_DATE_M) && (fmask & DTK_TIME_M)))
28452868
{
2846-
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0)
2869+
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
28472870
return -1;
28482871

28492872
}
28502873
/* otherwise it is a single date/time field... */
28512874
else
28522875
{
2853-
if (DecodeNumber(flen, field[i], fmask, &tmask, tm, fsec) != 0)
2876+
if (DecodeNumber(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
28542877
return -1;
28552878
}
28562879
break;
@@ -3009,6 +3032,13 @@ DecodeDateTime(char **field, int *ftype, int nf,
30093032
else
30103033
elog(ERROR,"Inconsistant use of year %04d and 'BC'", tm->tm_year);
30113034
}
3035+
else if (is2digits)
3036+
{
3037+
if (tm->tm_year < 70)
3038+
tm->tm_year += 2000;
3039+
else if (tm->tm_year < 100)
3040+
tm->tm_year += 1900;
3041+
}
30123042

30133043
if ((mer != HR24) && (tm->tm_hour > 12))
30143044
return -1;
@@ -3083,6 +3113,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou
30833113
int i;
30843114
int flen,
30853115
val;
3116+
int is2digits = FALSE;
30863117
int mer = HR24;
30873118

30883119
*dtype = DTK_TIME;
@@ -3110,7 +3141,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou
31103141
case DTK_NUMBER:
31113142
flen = strlen(field[i]);
31123143

3113-
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec) != 0)
3144+
if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
31143145
return -1;
31153146
break;
31163147

@@ -3209,6 +3240,8 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
32093240
int nf = 0;
32103241
int i,
32113242
len;
3243+
int bc = FALSE;
3244+
int is2digits = FALSE;
32123245
int type,
32133246
val,
32143247
dmask = 0;
@@ -3238,9 +3271,11 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
32383271
nf++;
32393272
}
32403273

3274+
#if 0
32413275
/* don't allow too many fields */
32423276
if (nf > 3)
32433277
return -1;
3278+
#endif
32443279

32453280
*tmask = 0;
32463281

@@ -3263,6 +3298,10 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
32633298
tm->tm_mon = val;
32643299
break;
32653300

3301+
case ADBC:
3302+
bc = (val == BC);
3303+
break;
3304+
32663305
default:
32673306
#ifdef DATEDEBUG
32683307
printf("DecodeDate- illegal field %s value is %d\n", field[i], val);
@@ -3289,7 +3328,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
32893328
if ((len = strlen(field[i])) <= 0)
32903329
return -1;
32913330

3292-
if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec) != 0)
3331+
if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec, &is2digits) != 0)
32933332
return -1;
32943333

32953334
if (fmask & dmask)
@@ -3299,6 +3338,25 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
32993338
*tmask |= dmask;
33003339
}
33013340

3341+
if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
3342+
return -1;
3343+
3344+
/* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
3345+
if (bc)
3346+
{
3347+
if (tm->tm_year > 0)
3348+
tm->tm_year = -(tm->tm_year - 1);
3349+
else
3350+
elog(ERROR,"Inconsistant use of year %04d and 'BC'", tm->tm_year);
3351+
}
3352+
else if (is2digits)
3353+
{
3354+
if (tm->tm_year < 70)
3355+
tm->tm_year += 2000;
3356+
else if (tm->tm_year < 100)
3357+
tm->tm_year += 1900;
3358+
}
3359+
33023360
return 0;
33033361
} /* DecodeDate() */
33043362

@@ -3362,7 +3420,8 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
33623420
* Interpret numeric field as a date value in context.
33633421
*/
33643422
static int
3365-
DecodeNumber(int flen, char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
3423+
DecodeNumber(int flen, char *str, int fmask,
3424+
int *tmask, struct tm * tm, double *fsec, int *is2digits)
33663425
{
33673426
int val;
33683427
char *cp;
@@ -3475,13 +3534,16 @@ DecodeNumber(int flen, char *str, int fmask, int *tmask, struct tm * tm, double
34753534
tm->tm_year = val;
34763535

34773536
/* adjust ONLY if exactly two digits... */
3537+
#if 0
34783538
if (flen == 2)
34793539
{
34803540
if (tm->tm_year < 70)
34813541
tm->tm_year += 2000;
34823542
else if (tm->tm_year < 100)
34833543
tm->tm_year += 1900;
34843544
}
3545+
#endif
3546+
*is2digits = (flen == 2);
34853547

34863548
}
34873549
else
@@ -3495,7 +3557,8 @@ DecodeNumber(int flen, char *str, int fmask, int *tmask, struct tm * tm, double
34953557
* Interpret numeric string as a concatenated date field.
34963558
*/
34973559
static int
3498-
DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
3560+
DecodeNumberField(int len, char *str, int fmask,
3561+
int *tmask, struct tm * tm, double *fsec, int *is2digits)
34993562
{
35003563
char *cp;
35013564

@@ -3546,10 +3609,13 @@ DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, dou
35463609
*(str + 2) = '\0';
35473610
tm->tm_year = atoi(str + 0);
35483611

3612+
#if 0
35493613
if (tm->tm_year < 70)
35503614
tm->tm_year += 2000;
35513615
else if (tm->tm_year < 100)
35523616
tm->tm_year += 1900;
3617+
#endif
3618+
*is2digits = TRUE;
35533619
}
35543620

35553621
}
@@ -3564,10 +3630,13 @@ DecodeNumberField(int len, char *str, int fmask, int *tmask, struct tm * tm, dou
35643630
tm->tm_mon = 1;
35653631
tm->tm_year = atoi(str + 0);
35663632

3633+
#if 0
35673634
if (tm->tm_year < 70)
35683635
tm->tm_year += 2000;
35693636
else if (tm->tm_year < 100)
35703637
tm->tm_year += 1900;
3638+
#endif
3639+
*is2digits = TRUE;
35713640
}
35723641
else if (strchr(str, '.') != NULL)
35733642
{

0 commit comments

Comments
 (0)