]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
* to_char:
authorBruce Momjian <bruce@momjian.us>
Tue, 29 Aug 2000 04:41:48 +0000 (04:41 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 29 Aug 2000 04:41:48 +0000 (04:41 +0000)
  - full support for IW (ISO week) and vice versa conversion for IW too
    (the to_char 'week' support is now complete and I hope correct).

  Thomas, I use for IW code from timestamp.c, for this I create separate
  function date2isoweek() from original 'case DTK_WEEK:' code in the
  timestamp_part(). I mean will better use one code for same feature in
  date_part() and in to_char(). The isoweek2date() is added to timestamp.c
  too. Right?

  IMHO in 7.1 will all to_char's features complete. It is cca 41 templates
  for date/time and cca 21 for numbers.

 * to_ascii:

   - gcc, is it correct now? :-)

  In the patch is documentation for to_char's IW and for to_ascii().

                                                        Karel

doc/src/sgml/func.sgml
src/backend/utils/adt/formatting.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/adt/timestamp.c
src/include/utils/timestamp.h

index aa7e2b098989bd46bd4e99a9bf4149c6b321afea..9f8fdd89324cc64b69ff0438012468b31baa823e 100644 (file)
        </row>
       </thead>
       <tbody>
+       <row>
+       <entry>to_ascii(text [,name|int])</entry>
+       <entry>text</entry>
+       <entry>convert text from multibyte encoding to ASCII</entry>
+       <entry>to_ascii('Karel')</entry>
+       </row>
        <row>
        <entry>char(text)</entry>
        <entry>char</entry>
    <para>
     Most functions explicitly defined for text will work for char() and varchar() arguments.
    </para>
+   <para>
+    The to_ascii() support conversion from LATIN1, LATIN2, WIN1250 (CP1250) only.
+   </para>
   </sect1>
 
   <sect1>
        <entry>WW</entry>
        <entry>week number of year (1-53) where first week start on the first day of the year</entry>
        </row>
+       <row>
+       <entry>IW</entry>
+       <entry>ISO week number of year</entry>
+       </row>
        <row>
        <entry>CC</entry>
        <entry>century (2 digits)</entry>
index 864c3867ba5329bfabcc6febb292d01f80c77a94..8dcce7f1d90e34497ab14f52dcdf7d74c01fe49a 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.20 2000/07/29 03:26:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.21 2000/08/29 04:41:47 momjian Exp $
  *
  *
  *      Portions Copyright (c) 1999-2000, PostgreSQL, Inc
@@ -344,24 +344,24 @@ static int        NUMCounter = 0;
  * ----------
  */
 typedef struct {
-       int     hh, am, pm, mi, ss, ssss, d, dd, ddd, mm, yyyy, bc, ww, w, cc, q, j;
+       int     hh, am, pm, mi, ss, ssss, d, dd, ddd, mm, yyyy, bc, iw, ww, w, cc, q, j;
 } TmFromChar;
 
 #define ZERO_tmfc( _X )        \
        do { \
                (_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \
                (_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->bc= \
-               (_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \
+               (_X)->iw= (_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \
        } while(0) 
 
 #ifdef DEBUG_TO_FROM_CHAR
 
 #define NOTICE_TMFC \
-               elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nyyyy %d\nbc %d\nww %d\nw %d\ncc %d\nq %d\nj %d", \
+               elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nyyyy %d\nbc %d\niw %d\nww %d\nw %d\ncc %d\nq %d\nj %d", \
                        tmfc->hh, tmfc->am, tmfc->pm, tmfc->mi, tmfc->ss, \
                        tmfc->ssss, tmfc->d, tmfc->dd, tmfc->ddd, tmfc->mm, \
-                       tmfc->yyyy, tmfc->bc, tmfc->ww, tmfc->w, tmfc->cc, \
-                       tmfc->q, tmfc->j);
+                       tmfc->yyyy, tmfc->bc, tmfc->iw, tmfc->ww, tmfc->w, \
+                       tmfc->cc, tmfc->q, tmfc->j);
 
 #define NOTICE_TM \
                elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
@@ -487,6 +487,7 @@ typedef enum
        DCH_HH24,
        DCH_HH12,
        DCH_HH,
+       DCH_IW,
        DCH_J,
        DCH_MI,
        DCH_MM,
@@ -524,6 +525,7 @@ typedef enum
        DCH_hh24,
        DCH_hh12,
        DCH_hh,
+       DCH_iw,
        DCH_j,
        DCH_mi,
        DCH_mm,
@@ -596,14 +598,14 @@ typedef enum
  * ----------
  */
 static KeyWord DCH_keywords[] = {
-/*     keyword,        len, func.      type                             is in Index */
+/*     keyword,len,func.type                    is in Index */
        {"A.D.", 4, dch_date, DCH_A_D},         /* A */
        {"A.M.", 4, dch_time, DCH_A_M},
        {"AD", 2, dch_date, DCH_AD},
        {"AM", 2, dch_time, DCH_AM},
        {"B.C.", 4, dch_date, DCH_B_C},         /* B */
        {"BC", 2, dch_date, DCH_BC},
-       {"CC", 2, dch_date, DCH_CC},/* C */
+       {"CC", 2, dch_date, DCH_CC},            /* C */
        {"DAY", 3, dch_date, DCH_DAY},          /* D */
        {"DDD", 3, dch_date, DCH_DDD},
        {"DD", 2, dch_date, DCH_DD},
@@ -615,7 +617,8 @@ static KeyWord DCH_keywords[] = {
        {"HH24", 4, dch_time, DCH_HH24},        /* H */
        {"HH12", 4, dch_time, DCH_HH12},
        {"HH", 2, dch_time, DCH_HH},
-       {"J", 1, dch_date, DCH_J},      /* J */
+       {"IW", 2, dch_date, DCH_IW},            /* I */ 
+       {"J", 1, dch_date, DCH_J},              /* J */
        {"MI", 2, dch_time, DCH_MI},
        {"MM", 2, dch_date, DCH_MM},
        {"MONTH", 5, dch_date, DCH_MONTH},
@@ -624,12 +627,12 @@ static KeyWord DCH_keywords[] = {
        {"Mon", 3, dch_date, DCH_Mon},
        {"P.M.", 4, dch_time, DCH_P_M},         /* P */
        {"PM", 2, dch_time, DCH_PM},
-       {"Q", 1, dch_date, DCH_Q},      /* Q */
-       {"RM", 2, dch_date, DCH_RM},/* R */
+       {"Q", 1, dch_date, DCH_Q},              /* Q */
+       {"RM", 2, dch_date, DCH_RM},            /* R */
        {"SSSS", 4, dch_time, DCH_SSSS},        /* S */
        {"SS", 2, dch_time, DCH_SS},
        {"TZ", 2, dch_time, DCH_TZ},            /* T */
-       {"WW", 2, dch_date, DCH_WW},/* W */
+       {"WW", 2, dch_date, DCH_WW},            /* W */
        {"W", 1, dch_date, DCH_W},
        {"Y,YYY", 5, dch_date, DCH_Y_YYY},      /* Y */
        {"YYYY", 4, dch_date, DCH_YYYY},
@@ -642,7 +645,7 @@ static KeyWord DCH_keywords[] = {
        {"am", 2, dch_time, DCH_am},
        {"b.c.", 4, dch_date, DCH_b_c},         /* b */
        {"bc", 2, dch_date, DCH_bc},
-       {"cc", 2, dch_date, DCH_CC},/* c */
+       {"cc", 2, dch_date, DCH_CC},            /* c */
        {"day", 3, dch_date, DCH_day},          /* d */
        {"ddd", 3, dch_date, DCH_DDD},
        {"dd", 2, dch_date, DCH_DD},
@@ -652,19 +655,20 @@ static KeyWord DCH_keywords[] = {
        {"hh24", 4, dch_time, DCH_HH24},        /* h */
        {"hh12", 4, dch_time, DCH_HH12},
        {"hh", 2, dch_time, DCH_HH},
-       {"j", 1, dch_time, DCH_J},      /* j */
-       {"mi", 2, dch_time, DCH_MI},/* m */
+       {"iw", 2, dch_date, DCH_IW},            /* i */
+       {"j", 1, dch_time, DCH_J},              /* j */
+       {"mi", 2, dch_time, DCH_MI},            /* m */
        {"mm", 2, dch_date, DCH_MM},
        {"month", 5, dch_date, DCH_month},
        {"mon", 3, dch_date, DCH_mon},
        {"p.m.", 4, dch_time, DCH_p_m},         /* p */
        {"pm", 2, dch_time, DCH_pm},
-       {"q", 1, dch_date, DCH_Q},      /* q */
-       {"rm", 2, dch_date, DCH_rm},/* r */
+       {"q", 1, dch_date, DCH_Q},              /* q */
+       {"rm", 2, dch_date, DCH_rm},            /* r */
        {"ssss", 4, dch_time, DCH_SSSS},        /* s */
        {"ss", 2, dch_time, DCH_SS},
        {"tz", 2, dch_time, DCH_tz},            /* t */
-       {"ww", 2, dch_date, DCH_WW},/* w */
+       {"ww", 2, dch_date, DCH_WW},            /* w */
        {"w", 1, dch_date, DCH_W},
        {"y,yyy", 5, dch_date, DCH_Y_YYY},      /* y */
        {"yyyy", 4, dch_date, DCH_YYYY},
@@ -735,10 +739,10 @@ static int        DCH_index[KeyWord_INDEX_SIZE] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
-       DCH_FX, -1, DCH_HH24, -1, DCH_J, -1, -1, DCH_MI, -1, -1,
+       DCH_FX, -1, DCH_HH24, DCH_IW, DCH_J, -1, -1, DCH_MI, -1, -1,
        DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, -1, -1, DCH_WW, -1, DCH_Y_YYY,
        -1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
-       DCH_day, -1, DCH_fx, -1, DCH_hh24, -1, DCH_j, -1, -1, DCH_mi,
+       DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iw, DCH_j, -1, -1, DCH_mi,
        -1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, -1, -1, DCH_ww,
        -1, DCH_y_yyy, -1, -1, -1, -1
 
@@ -1526,8 +1530,8 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
 
 /* ----------
  * Master function of TIME for:
- *                                       TO_CHAR       - write (inout) formated string
- *                                       FROM_CHAR - scan (inout) string by course of FormatNode
+ *                       TO_CHAR       - write (inout) formated string
+ *                       FROM_CHAR - scan (inout) string by course of FormatNode
  * ----------
  */
 static int
@@ -1772,7 +1776,7 @@ do { \
 
 /* ----------
  * Master of DATE for:
- *               TO_CHAR       - write (inout) formated string
+ *               TO_CHAR - write (inout) formated string
  *               FROM_CHAR - scan (inout) string by course of FormatNode
  * ----------
  */
@@ -2086,6 +2090,33 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                                        return 1 + SKIP_THth(suf);
                                }
                        }
+                       break;
+               case DCH_IW:
+                       if (flag == TO_CHAR)
+                       {
+                               sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
+                                       date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
+                               if (S_THth(suf))
+                                       str_numth(p_inout, inout, S_TH_TYPE(suf));
+                               if (S_FM(suf) || S_THth(suf))
+                                       return strlen(p_inout) - 1;
+                               else
+                                       return 1;
+
+                       }
+                       else if (flag == FROM_CHAR) 
+                       {
+                               if (S_FM(suf))
+                               {
+                                       sscanf(inout, "%d", &tmfc->iw);
+                                       return int4len((int4) tmfc->iw) - 1 + SKIP_THth(suf);
+                               }
+                               else
+                               {
+                                       sscanf(inout, "%02d", &tmfc->iw);
+                                       return 1 + SKIP_THth(suf);
+                               }
+                       }
                        break;  
                case DCH_Q:
                        if (flag == TO_CHAR)
@@ -2687,19 +2718,29 @@ to_timestamp(PG_FUNCTION_ARGS)
                case 4: tm->tm_mday = 1; tm->tm_mon = 10; break;
        }
        
-       if (tmfc->j)
-               j2date(tmfc->j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
        if (tmfc->yyyy) 
                tm->tm_year = tmfc->yyyy;
+       
+       if (tmfc->j)
+               j2date(tmfc->j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+       
        if (tmfc->bc && tm->tm_year > 0)
                tm->tm_year = -(tm->tm_year);
+       
        if (tm->tm_year < 0)
                tm->tm_year = tm->tm_year + 1;
+       
+       if (tmfc->iw)
+               isoweek2date(tmfc->iw, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+               
        if (tmfc->d)    tm->tm_wday = tmfc->d;
        if (tmfc->dd)   tm->tm_mday = tmfc->dd; 
        if (tmfc->ddd)  tm->tm_yday = tmfc->ddd;
        if (tmfc->mm)   tm->tm_mon  = tmfc->mm; 
 
+       /*
+        * we not ignore DDD
+        */
        if (tmfc->ddd && (tm->tm_mon <=1 || tm->tm_mday <=1))
        {
                /* count mday and mon from yday */
@@ -2726,6 +2767,7 @@ to_timestamp(PG_FUNCTION_ARGS)
                        tm->tm_mday = i == 0 ?  tm->tm_yday :
                                                tm->tm_yday - y[i-1];
        }
+       
        /* -------------------------------------------------------------- */
 
 #ifdef DEBUG_TO_FROM_CHAR
index d176a8fd230de60b9820d85928b395db78f27794..31e791170fe586d9fe0f9c48f0eafe09bf67ff7e 100644 (file)
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------
  * pg_locale.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.5 2000/06/29 01:19:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.6 2000/08/29 04:41:47 momjian Exp $
  *
  *
  *      Portions Copyright (c) 1999-2000, PostgreSQL, Inc
@@ -26,6 +26,8 @@
 /* #define DEBUG_LOCALE_UTILS  */
 
 
+static struct lconv *CurrentLocaleConv = NULL;
+
 /*------
  * Return in PG_LocaleCategories current locale setting
  *------
@@ -119,7 +121,9 @@ struct lconv *
 PGLC_localeconv(void)
 {
        PG_LocaleCategories lc;
-       struct lconv *lconv;
+       
+       if (CurrentLocaleConv)
+               return CurrentLocaleConv;
 
        /* Save current locale setting to lc */
        PGLC_current(&lc);
@@ -128,12 +132,12 @@ PGLC_localeconv(void)
        setlocale(LC_ALL, "");
 
        /* Get numeric formatting information */
-       lconv = localeconv();
+       CurrentLocaleConv = localeconv();
 
        /* Set previous original locale */
        PGLC_setlocale(&lc);
 
-       return lconv;
+       return CurrentLocaleConv;
 }
 
 
index 0730d56147350f5f482e60636ec4bffabcd257bb..8894f60d54a5c7467ac22ab6df24bc89d4ced156 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.34 2000/07/17 03:05:18 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.35 2000/08/29 04:41:47 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1796,7 +1796,81 @@ interval_trunc(PG_FUNCTION_ARGS)
        PG_RETURN_INTERVAL_P(result);
 }
 
+/* isoweek2date()
+ *
+ *     Convert ISO week of year number to date. An year must be already set.  
+ *     karel 2000/08/07
+ */
+void
+isoweek2date( int woy, int *year, int *mon, int *mday)
+{
+       int     day0, day4, dayn;
+       
+       if (!*year)
+               elog(ERROR, "isoweek2date(): can't convert without year information");
+
+       /* fourth day of current year */
+       day4 = date2j(*year, 1, 4);
+       
+       /* day0 == offset to first day of week (Monday) */
+       day0 = (j2day(day4 - 1) % 7);
+
+       dayn = ((woy - 1) * 7) + (day4 - day0);
+       
+       j2date(dayn, year, mon, mday);
+}
+
+/* date2isoweek()
+ * 
+ *     Returns ISO week number of year.
+ */
+int
+date2isoweek(int year, int mon, int mday) 
+{
+       float8  result;
+       int     day0, day4, dayn;
+       
+       /* current day */       
+       dayn = date2j(year, mon, mday);
+       
+       /* fourth day of current year */
+       day4 = date2j(year, 1, 4);
+       
+       /* day0 == offset to first day of week (Monday) */
+       day0 = (j2day(day4 - 1) % 7);
+       
+       /* We need the first week containing a Thursday,
+        * otherwise this day falls into the previous year
+        * for purposes of counting weeks
+        */
+       if (dayn < (day4 - day0))
+       {
+               day4 = date2j((year - 1), 1, 4);
+       
+               /* day0 == offset to first day of week (Monday) */
+               day0 = (j2day(day4 - 1) % 7);
+       }
+       
+       result = (((dayn - (day4 - day0)) / 7) + 1);
+       
+       /* Sometimes the last few days in a year will fall into
+        * the first week of the next year, so check for this.
+        */
+       if (result >= 53)
+       {
+               day4 = date2j((year + 1), 1, 4);
+       
+               /* day0 == offset to first day of week (Monday) */
+               day0 = (j2day(day4 - 1) % 7);
+               
+               if (dayn >= (day4 - day0))
+                       result = (((dayn - (day4 - day0)) / 7) + 1);
+       }
 
+       return (int) result;
+} 
 /* timestamp_part()
  * Extract specified field from timestamp.
  */
@@ -1897,35 +1971,7 @@ timestamp_part(PG_FUNCTION_ARGS)
                                        break;
 
                                case DTK_WEEK:
-                                       {
-                                               int day0, day4, dayn;
-                                               dayn = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-                                               day4 = date2j(tm->tm_year, 1, 4);
-                                               /* day0 == offset to first day of week (Monday) */
-                                               day0 = (j2day(day4 - 1) % 7);
-                                               /* We need the first week containing a Thursday,
-                                                * otherwise this day falls into the previous year
-                                                * for purposes of counting weeks
-                                                */
-                                               if (dayn < (day4 - day0))
-                                               {
-                                                       day4 = date2j((tm->tm_year - 1), 1, 4);
-                                                       /* day0 == offset to first day of week (Monday) */
-                                                       day0 = (j2day(day4 - 1) % 7);
-                                               }
-                                               result = (((dayn - (day4 - day0)) / 7) + 1);
-                                               /* Sometimes the last few days in a year will fall into
-                                                * the first week of the next year, so check for this.
-                                                */
-                                               if (result >= 53)
-                                               {
-                                                       day4 = date2j((tm->tm_year + 1), 1, 4);
-                                                       /* day0 == offset to first day of week (Monday) */
-                                                       day0 = (j2day(day4 - 1) % 7);
-                                                       if (dayn >= (day4 - day0))
-                                                               result = (((dayn - (day4 - day0)) / 7) + 1);
-                                               }
-                                       }
+                                       result = (float8) date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
                                        break;
 
                                case DTK_YEAR:
index b848c894a0414b86bb26119fc835bc79f4f6136a..5ee3575d1fa3cb062c8d396e47433dd5c380b4cb 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: timestamp.h,v 1.9 2000/07/17 03:05:32 tgl Exp $
+ * $Id: timestamp.h,v 1.10 2000/08/29 04:41:48 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -190,4 +190,7 @@ extern int  timestamp2tm(Timestamp dt, int *tzp, struct tm * tm,
 
 extern Timestamp SetTimestamp(Timestamp timestamp);
 
+extern void    isoweek2date( int woy, int *year, int *mon, int *mday);
+extern int     date2isoweek(int year, int mon, int mday);
+
 #endif  /* TIMESTAMP_H */