patch for 60 seconds bug

Поиск
Список
Период
Сортировка
От Joseph Shraibman
Тема patch for 60 seconds bug
Дата
Msg-id 3B7B2DEC.4070700@selectacast.net
обсуждение исходный текст
Ответы Re: patch for 60 seconds bug
Список 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@selectacast.net
Increase signal to noise ratio.  http://www.targabot.com


В списке pgsql-patches по дате отправления:

Предыдущее
От: Vince Vielhaber
Дата:
Сообщение: Re: Re: Proposal for encrypting pg_shadow passwords
Следующее
От: Tom Lane
Дата:
Сообщение: Re: Re: Proposal for encrypting pg_shadow passwords