Thread: Strange results from to_timestamp

Strange results from to_timestamp

From
Mario Weilguni
Date:
mydb=# select to_timestamp('00000000 0300','yyyymmdd hh24mi');      to_timestamp
---------------------------0001-01-01 03:00:00+01 BC
(1 row)

Questionable, but probably valid.



mydb=# select to_timestamp('         0300','yyyymmdd hh24mi');     to_timestamp
------------------------0300-12-25 03:00:00+01
(1 row)

This puzzles me. Where is the 25th of december coming from?



mydb=# select to_timestamp('         030004','yyyymmdd hh24mi');     to_timestamp
------------------------0382-04-23 03:00:00+01
(1 row)

Same as above.


mydb=# select to_timestamp('         040004','yyyymmdd hh24mi');     to_timestamp
------------------------0509-10-10 04:00:00+01


I think all except the first one should raise a warning, isn't it? Where can I 
find the source code of this function?

Best regards,Mario Weilguni



Re: Strange results from to_timestamp

From
Mario Weilguni
Date:
Am Donnerstag, 6. April 2006 14:57 schrieb Mario Weilguni:
> mydb=# select to_timestamp('00000000 0300','yyyymmdd hh24mi');
>        to_timestamp
> ---------------------------
>  0001-01-01 03:00:00+01 BC
> (1 row)
>
> Questionable, but probably valid.
>
>
>
> mydb=# select to_timestamp('         0300','yyyymmdd hh24mi');
>       to_timestamp
> ------------------------
>  0300-12-25 03:00:00+01
> (1 row)
>
> This puzzles me. Where is the 25th of december coming from?

Sorry, forgot to mention, this is from PostgreSQL 8.1.3


Re: Strange results from to_timestamp

From
"William ZHANG"
Date:
ISTM, and mismatch between the date/time string and the format string will
lead to
strange results.
The source code of to_timestamp() is in src/backend/utils/adt/formatting.c:

Datum
to_timestamp(PG_FUNCTION_ARGS)

Regards,
William ZHANG


"Mario Weilguni" <mweilguni@sime.com>
> Am Donnerstag, 6. April 2006 14:57 schrieb Mario Weilguni:
> > mydb=# select to_timestamp('00000000 0300','yyyymmdd hh24mi');
> >        to_timestamp
> > ---------------------------
> >  0001-01-01 03:00:00+01 BC
> > (1 row)
> >
> > Questionable, but probably valid.
> >
> >
> >
> > mydb=# select to_timestamp('         0300','yyyymmdd hh24mi');
> >       to_timestamp
> > ------------------------
> >  0300-12-25 03:00:00+01
> > (1 row)
> >
> > This puzzles me. Where is the 25th of december coming from?
>
> Sorry, forgot to mention, this is from PostgreSQL 8.1.3
>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: explain analyze is your friend
>




Re: Strange results from to_timestamp

From
Tom Lane
Date:
Mario Weilguni <mweilguni@sime.com> writes:
> I think all except the first one should raise a warning, isn't it?

to_timestamp (and friends) all seem to me to act pretty bizarre when
faced with input that doesn't match the given format string.  However,
in the end that is an Oracle-compatibility function, and there is only
one measure of what it should do: what does Oracle do in the same case.
Can anyone try these examples on a recent Oracle version?
        regards, tom lane


Re: Strange results from to_timestamp

From
"Adrian Maier"
Date:
On 4/7/06, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Mario Weilguni <mweilguni@sime.com> writes:
> > I think all except the first one should raise a warning, isn't it?
>
> to_timestamp (and friends) all seem to me to act pretty bizarre when
> faced with input that doesn't match the given format string.  However,
> in the end that is an Oracle-compatibility function, and there is only
> one measure of what it should do: what does Oracle do in the same case.
> Can anyone try these examples on a recent Oracle version?


In Oracle10g Express those dates are rejected as invalid :

SQL> select to_timestamp('00000000 0300','yyyymmdd hh24mi') from dual;
select to_timestamp('00000000 0300','yyyymmdd hh24mi') from dual                   *
ERROR at line 1:
ORA-01843: not a valid month


SQL> select to_timestamp('         0300','yyyymmdd hh24mi') from dual;
select to_timestamp('         0300','yyyymmdd hh24mi') from dual                   *
ERROR at line 1:
ORA-01843: not a valid month



Cheers,
Adrian Maier


Re: Strange results from to_timestamp

From
"Mario Weilguni"
Date:
to_timestamp is only for Oracle compatibility? I always thought it's some sort of sql standard. What's the sql
compliantway to do this? 

Regards,    mario weilguni


-----Ursprüngliche Nachricht-----
Von: pgsql-hackers-owner@postgresql.org [mailto:pgsql-hackers-owner@postgresql.org] Im Auftrag von Tom Lane
Gesendet: Freitag, 07. April 2006 06:09
An: Mario Weilguni
Cc: PostgreSQL-development
Betreff: Re: [HACKERS] Strange results from to_timestamp

Mario Weilguni <mweilguni@sime.com> writes:
> I think all except the first one should raise a warning, isn't it?

to_timestamp (and friends) all seem to me to act pretty bizarre when faced with input that doesn't match the given
formatstring.  However, in the end that is an Oracle-compatibility function, and there is only one measure of what it
shoulddo: what does Oracle do in the same case. 
Can anyone try these examples on a recent Oracle version?
        regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?
              http://www.postgresql.org/docs/faq


Re: Strange results from to_timestamp

From
Bruce Momjian
Date:
Mario Weilguni wrote:
> to_timestamp is only for Oracle compatibility? I always thought it's
> some sort of sql standard. What's the sql compliant way to do this?

There isn't a standard method, which is why we added Oracle functions.

---------------------------------------------------------------------------


> 
> Regards,
> mario weilguni
> 
> 
> -----Urspr?ngliche Nachricht----- Von:
> pgsql-hackers-owner@postgresql.org
> [mailto:pgsql-hackers-owner@postgresql.org] Im Auftrag von Tom Lane
> Gesendet: Freitag, 07. April 2006 06:09 An: Mario Weilguni Cc:
> PostgreSQL-development Betreff: Re: [HACKERS] Strange results from
> to_timestamp
> 
> Mario Weilguni <mweilguni@sime.com> writes:
> > I think all except the first one should raise a warning, isn't it?
> 
> to_timestamp (and friends) all seem to me to act pretty bizarre when
> faced with input that doesn't match the given format string.  However,
> in the end that is an Oracle-compatibility function, and there is only
> one measure of what it should do: what does Oracle do in the same case.
> Can anyone try these examples on a recent Oracle version?
> 
>         regards, tom lane
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: Have you checked our extensive FAQ?
> 
>       http://www.postgresql.org/docs/faq
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>   choose an index scan if your joining column's datatypes do not
>   match
> 

-- Bruce Momjian   http://candle.pha.pa.us EnterpriseDB    http://www.enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: Strange results from to_timestamp

From
Bruce Momjian
Date:
Interesting bug report.  The problem is that sscanf(buf, "%d", &val)
eats leading white space, but our functions were not handling that.

I have applied the attached patch that fixes this:test=> select to_timestamp('         0300','yyyymmdd hh24mi');
to_timestamp------------------------0300-01-01 00:00:00-05(1 row)test=> select to_timestamp('         030004','yyyymmdd
hh24mi');     to_timestamp------------------------ 0300-04-01 00:00:00-05(1 row)test=>  select to_timestamp('
040004','yyyymmddhh24mi');      to_timestamp------------------------ 0400-04-01 00:00:00-05(1 row)
 

It doesn't throw an error for too mamy format strings, but it does avoid
the incorrect values.  The fix will appear in 8.2.

---------------------------------------------------------------------------

Mario Weilguni wrote:
> mydb=# select to_timestamp('00000000 0300','yyyymmdd hh24mi');
>        to_timestamp
> ---------------------------
>  0001-01-01 03:00:00+01 BC
> (1 row)
> 
> Questionable, but probably valid.
> 
> 
> 
> mydb=# select to_timestamp('         0300','yyyymmdd hh24mi');
>       to_timestamp
> ------------------------
>  0300-12-25 03:00:00+01
> (1 row)
> 
> This puzzles me. Where is the 25th of december coming from?
> 
> 
> 
> mydb=# select to_timestamp('         030004','yyyymmdd hh24mi');
>       to_timestamp
> ------------------------
>  0382-04-23 03:00:00+01
> (1 row)
> 
> Same as above.
> 
> 
> mydb=# select to_timestamp('         040004','yyyymmdd hh24mi');
>       to_timestamp
> ------------------------
>  0509-10-10 04:00:00+01
> 
> 
> I think all except the first one should raise a warning, isn't it? Where can I 
> find the source code of this function?
> 
> Best regards,
>     Mario Weilguni
> 
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match
> 

--  Bruce Momjian   http://candle.pha.pa.us EnterpriseDB    http://www.enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: Strange results from to_timestamp

From
Bruce Momjian
Date:
Attachment now attached.  :-)

---------------------------------------------------------------------------

Bruce Momjian wrote:
>
> Interesting bug report.  The problem is that sscanf(buf, "%d", &val)
> eats leading white space, but our functions were not handling that.
>
> I have applied the attached patch that fixes this:
>
>     test=> select to_timestamp('         0300','yyyymmdd hh24mi');
>           to_timestamp
>     ------------------------
>      0300-01-01 00:00:00-05
>     (1 row)
>
>     test=> select to_timestamp('         030004','yyyymmdd hh24mi');
>           to_timestamp
>     ------------------------
>      0300-04-01 00:00:00-05
>     (1 row)
>
>     test=>  select to_timestamp('         040004','yyyymmdd hh24mi');
>           to_timestamp
>     ------------------------
>      0400-04-01 00:00:00-05
>     (1 row)
>
> It doesn't throw an error for too mamy format strings, but it does avoid
> the incorrect values.  The fix will appear in 8.2.
>
> ---------------------------------------------------------------------------
>
> Mario Weilguni wrote:
> > mydb=# select to_timestamp('00000000 0300','yyyymmdd hh24mi');
> >        to_timestamp
> > ---------------------------
> >  0001-01-01 03:00:00+01 BC
> > (1 row)
> >
> > Questionable, but probably valid.
> >
> >
> >
> > mydb=# select to_timestamp('         0300','yyyymmdd hh24mi');
> >       to_timestamp
> > ------------------------
> >  0300-12-25 03:00:00+01
> > (1 row)
> >
> > This puzzles me. Where is the 25th of december coming from?
> >
> >
> >
> > mydb=# select to_timestamp('         030004','yyyymmdd hh24mi');
> >       to_timestamp
> > ------------------------
> >  0382-04-23 03:00:00+01
> > (1 row)
> >
> > Same as above.
> >
> >
> > mydb=# select to_timestamp('         040004','yyyymmdd hh24mi');
> >       to_timestamp
> > ------------------------
> >  0509-10-10 04:00:00+01
> >
> >
> > I think all except the first one should raise a warning, isn't it? Where can I
> > find the source code of this function?
> >
> > Best regards,
> >     Mario Weilguni
> >
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 9: In versions below 8.0, the planner will ignore your desire to
> >        choose an index scan if your joining column's datatypes do not
> >        match
> >
>
> --
>   Bruce Momjian   http://candle.pha.pa.us
>   EnterpriseDB    http://www.enterprisedb.com
>
>   + If your life is a hard drive, Christ can be your backup. +
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match
>

--
  Bruce Momjian   http://candle.pha.pa.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.109
diff -c -c -r1.109 formatting.c
*** src/backend/utils/adt/formatting.c    19 Apr 2006 14:48:06 -0000    1.109
--- src/backend/utils/adt/formatting.c    19 Apr 2006 16:07:35 -0000
***************
*** 917,922 ****
--- 917,923 ----

  static char *get_th(char *num, int type);
  static char *str_numth(char *dest, char *num, int type);
+ static int    strspace_len(char *str);
  static int    strdigits_len(char *str);
  static char *str_toupper(char *buff);
  static char *str_tolower(char *buff);
***************
*** 1687,1697 ****
  }

  static int
  strdigits_len(char *str)
  {
      char       *p = str;
!     int            len = 0;

      while (*p && isdigit((unsigned char) *p) && len <= DCH_MAX_ITEM_SIZ)
      {
          len++;
--- 1688,1714 ----
  }

  static int
+ strspace_len(char *str)
+ {
+     int            len = 0;
+
+     while (*str && isspace((unsigned char) *str))
+     {
+         str++;
+         len++;
+     }
+     return len;
+ }
+
+ static int
  strdigits_len(char *str)
  {
      char       *p = str;
!     int            len;

+     len = strspace_len(str);
+     p += len;
+
      while (*p && isdigit((unsigned char) *p) && len <= DCH_MAX_ITEM_SIZ)
      {
          len++;
***************
*** 1826,1832 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->hh);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 1843,1849 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->hh);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 1848,1854 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->hh);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 1865,1871 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->hh);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 1870,1876 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->mi);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 1887,1893 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->mi);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 1892,1898 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->ss);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 1909,1915 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->ss);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 1998,2004 ****
                  else
                  {
                      sscanf(inout, "%05d", &tmfc->ssss);
!                     return 5 + SKIP_THth(suf);
                  }
              }
              break;
--- 2015,2021 ----
                  else
                  {
                      sscanf(inout, "%05d", &tmfc->ssss);
!                     return strspace_len(inout) + 5 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2249,2255 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->mm);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 2266,2272 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->mm);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2323,2329 ****
                  else
                  {
                      sscanf(inout, "%03d", &tmfc->ddd);
!                     return 3 + SKIP_THth(suf);
                  }
              }
              break;
--- 2340,2346 ----
                  else
                  {
                      sscanf(inout, "%03d", &tmfc->ddd);
!                     return strspace_len(inout) + 3 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2345,2351 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->dd);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 2362,2368 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->dd);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2360,2366 ****
              else
              {
                  sscanf(inout, "%1d", &tmfc->d);
!                 return 1 + SKIP_THth(suf);
              }
              break;
          case DCH_WW:
--- 2377,2383 ----
              else
              {
                  sscanf(inout, "%1d", &tmfc->d);
!                 return strspace_len(inout) + 1 + SKIP_THth(suf);
              }
              break;
          case DCH_WW:
***************
*** 2382,2388 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->ww);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 2399,2405 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->ww);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2405,2411 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->iw);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 2422,2428 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->iw);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2422,2428 ****
              else
              {
                  sscanf(inout, "%1d", &tmfc->q);
!                 return 1 + SKIP_THth(suf);
              }
              break;
          case DCH_CC:
--- 2439,2445 ----
              else
              {
                  sscanf(inout, "%1d", &tmfc->q);
!                 return strspace_len(inout) + 1 + SKIP_THth(suf);
              }
              break;
          case DCH_CC:
***************
*** 2447,2453 ****
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->cc);
!                     return 2 + SKIP_THth(suf);
                  }
              }
              break;
--- 2464,2470 ----
                  else
                  {
                      sscanf(inout, "%02d", &tmfc->cc);
!                     return strspace_len(inout) + 2 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2507,2513 ****
                  {
                      sscanf(inout, "%04d", &tmfc->year);
                      tmfc->yysz = 4;
!                     return 4 + SKIP_THth(suf);
                  }
              }
              break;
--- 2524,2530 ----
                  {
                      sscanf(inout, "%04d", &tmfc->year);
                      tmfc->yysz = 4;
!                     return strspace_len(inout) + 4 + SKIP_THth(suf);
                  }
              }
              break;
***************
*** 2540,2546 ****
                  else
                      tmfc->year += 2000;
                  tmfc->yysz = 3;
!                 return 3 + SKIP_THth(suf);
              }
              break;
          case DCH_YY:
--- 2557,2563 ----
                  else
                      tmfc->year += 2000;
                  tmfc->yysz = 3;
!                 return strspace_len(inout) + 3 + SKIP_THth(suf);
              }
              break;
          case DCH_YY:
***************
*** 2572,2578 ****
                  else
                      tmfc->year += 1900;
                  tmfc->yysz = 2;
!                 return 2 + SKIP_THth(suf);
              }
              break;
          case DCH_Y:
--- 2589,2595 ----
                  else
                      tmfc->year += 1900;
                  tmfc->yysz = 2;
!                 return strspace_len(inout) + 2 + SKIP_THth(suf);
              }
              break;
          case DCH_Y:
***************
*** 2600,2606 ****
                   */
                  tmfc->year += 2000;
                  tmfc->yysz = 1;
!                 return 1 + SKIP_THth(suf);
              }
              break;
          case DCH_RM:
--- 2617,2623 ----
                   */
                  tmfc->year += 2000;
                  tmfc->yysz = 1;
!                 return strspace_len(inout) + 1 + SKIP_THth(suf);
              }
              break;
          case DCH_RM:
***************
*** 2652,2658 ****
              else
              {
                  sscanf(inout, "%1d", &tmfc->w);
!                 return 1 + SKIP_THth(suf);
              }
              break;
          case DCH_J:
--- 2669,2675 ----
              else
              {
                  sscanf(inout, "%1d", &tmfc->w);
!                 return strspace_len(inout) + 1 + SKIP_THth(suf);
              }
              break;
          case DCH_J: