* to_char:
authorBruce Momjian
Tue, 29 Aug 2000 04:41:48 +0000 (04:41 +0000)
committerBruce Momjian
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)
        
       
       
+       
+   to_ascii(text [,name|int])
+   text
+   convert text from multibyte encoding to ASCII
+   to_ascii('Karel')
+       
        
    char(text)
    char
    
     Most functions explicitly defined for text will work for char() and varchar() arguments.
    
+   
+    The to_ascii() support conversion from LATIN1, LATIN2, WIN1250 (CP1250) only.
+   
   
 
   
    WW
    week number of year (1-53) where first week start on the first day of the year
        
+       
+   IW
+   ISO week number of year
+       
        
    CC
    century (2 digits)
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 */