patch for 60 seconds bug

From: Joseph Shraibman <jks(at)selectacast(dot)net>
To: pgsql-patches(at)postgresql(dot)org
Subject: patch for 60 seconds bug
Date: 2001-08-16 02:20:28
Message-ID: 3B7B2DEC.4070700@selectacast.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-patches

This patch fixes the problem of doing:
select '2001-08-15 23:59:59.996'::timestamp;

... and getting a string with 60 in the seconds field. This only fixes the method
EncodeDateTime(), the fix should be applied to EncodeTimeOnly() as well. (I didn't do it
because I thought that you might want to make this prettier before applying).

I was afraid to modify the fields in the passed in tm object. Logically since it is only
output by this method even if internally it was changed it would have to go through this
method again to be output anyway, but I didn't want to mess with it.

This should be in the next 7.1.x release so when people dump from 7.1 to upgrade to 7.2
they won't have invalid data.

Interestingly:
select '2001-08-15 23:59:59.995'::timestamp;
use to output:
2001-08-15 23:59:59.99-04
on my system before I made this change. Is this the result of some funkiness in my libc?
I'm using a redhat 6.2ish system with glibc 2.1.3

*** datetime.c.orig Wed Aug 15 21:00:05 2001
--- datetime.c Wed Aug 15 22:05:56 2001
***************
*** 2080,2086 ****
{
int
day,

hour,
!
min;
double sec;

if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
--- 2080,2091 ----
{
int
day,

hour,
!
min,
! tmyear,
! tmmon,
! tmmday,
! tmhour,
! tmmin;
double sec;

if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
***************
*** 2088,2093 ****
--- 2093,2126 ----

sec = (tm->tm_sec + fsec);

+ /* code to round the datetime so outputs with 60 seconds dont happen
+ I don't want to modify the tm values bec. I don't know if there would be side affects
+ so I created seperate variables.
+ I left BC dates alone.
+ */
+ tmyear = tm->tm_year;
+ tmmon = tm->tm_mon;
+ tmmday = tm->tm_mday;
+ tmhour = tm->tm_hour;
+ tmmin = tm->tm_min;
+ if (sec >= 59.995){
+ sec = 0;
+ if (++tmmin > 59){
+
tmmin = 0;
+
if (++tmhour > 23){
+
tmhour = 0;
+
if (++tmmday > day_tab[isleap(tmyear)][tmmon - 1]){
+
tmmday = 1;
+
if (++tmmon > 12){
+
tmmon = 1;
+
tmyear++;/* what about BC? */
+
}
+
}
+
}
+ }
+ };
+
+
switch (style)
{
/* compatible with ISO date formats */
***************
*** 2096,2102 ****
if (tm->tm_year > 0)
{

sprintf(str, "%04d-%02d-%02d %02d:%02d:",
!
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);

sprintf((str + strlen(str)), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))
--- 2129,2135 ----
if (tm->tm_year > 0)
{

sprintf(str, "%04d-%02d-%02d %02d:%02d:",
!
tmyear, tmmon, tmmday, tmhour, tmmin);

sprintf((str + strlen(str)), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))
***************
*** 2129,2158 ****
/* compatible with Oracle/Ingres date formats */
case USE_SQL_DATES:
if (EuroDates)
!
sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
else
!
sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);

if (tm->tm_year > 0)
{

sprintf((str + 5), "/%04d %02d:%02d:%05.2f",
!
tm->tm_year, tm->tm_hour, tm->tm_min, sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
}
else

sprintf((str + 5), "/%04d %02d:%02d %s",
!
-(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC");
break;

/* German variant on European style */
case USE_GERMAN_DATES:
!
sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
if (tm->tm_year > 0)
{

sprintf((str + 5), ".%04d %02d:%02d:%05.2f",
!
tm->tm_year, tm->tm_hour, tm->tm_min, sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
--- 2162,2191 ----
/* compatible with Oracle/Ingres date formats */
case USE_SQL_DATES:
if (EuroDates)
!
sprintf(str, "%02d/%02d", tmmday, tmmon);
else
!
sprintf(str, "%02d/%02d", tmmon, tmmday);

if (tm->tm_year > 0)
{

sprintf((str + 5), "/%04d %02d:%02d:%05.2f",
!
tmyear, tmhour, tmmin, sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
}
else

sprintf((str + 5), "/%04d %02d:%02d %s",
!
-(tm->tm_year - 1), tmhour, tmmin, "BC");
break;

/* German variant on European style */
case USE_GERMAN_DATES:
!
sprintf(str, "%02d.%02d", tmmday, tmmon);
if (tm->tm_year > 0)
{

sprintf((str + 5), ".%04d %02d:%02d:%05.2f",
!
tmyear, tmhour, tmmin, sec);


if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
***************
*** 2165,2193 ****
/* backward-compatible with traditional Postgres abstime dates */
case USE_POSTGRES_DATES:
default:
!
day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
tm->tm_wday = j2day(day);

strncpy(str, days[tm->tm_wday], 3);
strcpy((str + 3), " ");

if (EuroDates)
!
sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
else
!
sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);

if (tm->tm_year > 0)
{
!
sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);

if (fsec != 0)

{
!
sprintf((str + 16), ":%05.2f %04d", sec, tm->tm_year);

if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);

}

else

{
!
sprintf((str + 16), ":%02.0f %04d", sec, tm->tm_year);

if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);

}
--- 2198,2226 ----
/* backward-compatible with traditional Postgres abstime dates */
case USE_POSTGRES_DATES:
default:
!
day = date2j(tmyear, tmmon, tmmday);
tm->tm_wday = j2day(day);

strncpy(str, days[tm->tm_wday], 3);
strcpy((str + 3), " ");

if (EuroDates)
!
sprintf((str + 4), "%02d %3s", tmmday, months[tmmon - 1]);
else
!
sprintf((str + 4), "%3s %02d", months[tmmon - 1], tmmday);

if (tm->tm_year > 0)
{
!
sprintf((str + 10), " %02d:%02d", tmhour, tmmin);

if (fsec != 0)

{
!
sprintf((str + 16), ":%05.2f %04d", sec, tmyear);

if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);

}

else

{
!
sprintf((str + 16), ":%02.0f %04d", sec, tmyear);

if ((*tzn != NULL) && (tm->tm_isdst >= 0))

sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);

}
--
Joseph Shraibman
jks(at)selectacast(dot)net
Increase signal to noise ratio. http://www.targabot.com

Responses

Browse pgsql-patches by date

  From Date Subject
Next Message Tom Lane 2001-08-16 03:32:42 Re: Re: Proposal for encrypting pg_shadow passwords
Previous Message Vince Vielhaber 2001-08-16 00:12:57 Re: Re: Proposal for encrypting pg_shadow passwords