]> granicus.if.org Git - postgresql/commitdiff
Fix to_date() and to_timestamp() to allow specification of the day of
authorBruce Momjian <bruce@momjian.us>
Tue, 4 Sep 2012 02:52:34 +0000 (22:52 -0400)
committerBruce Momjian <bruce@momjian.us>
Tue, 4 Sep 2012 02:52:44 +0000 (22:52 -0400)
the week via ISO or Gregorian designations.  The fix is to store the
day-of-week consistently as 1-7, Sunday = 1.

Fixes bug reported by Marc Munro

src/backend/utils/adt/formatting.c
src/backend/utils/adt/timestamp.c
src/include/utils/timestamp.h

index 25af8a212b825b9446bfbf16093ac6b6d8c281bf..2aa6df1756b13f370078aea461caab3ad34eef78 100644 (file)
@@ -412,7 +412,7 @@ typedef struct
                                mi,
                                ss,
                                ssss,
-                               d,
+                               d,                              /* stored as 1-7, Sunday = 1, 0 means missing */
                                dd,
                                ddd,
                                mm,
@@ -2897,6 +2897,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
                                from_char_seq_search(&value, &s, days, ONE_UPPER,
                                                                         MAX_DAY_LEN, n);
                                from_char_set_int(&out->d, value, n);
+                               out->d++;
                                break;
                        case DCH_DY:
                        case DCH_Dy:
@@ -2904,6 +2905,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
                                from_char_seq_search(&value, &s, days, ONE_UPPER,
                                                                         MAX_DY_LEN, n);
                                from_char_set_int(&out->d, value, n);
+                               out->d++;
                                break;
                        case DCH_DDD:
                                from_char_parse_int(&out->ddd, &s, n);
@@ -2919,11 +2921,13 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
                                break;
                        case DCH_D:
                                from_char_parse_int(&out->d, &s, n);
-                               out->d--;
                                s += SKIP_THth(n->suffix);
                                break;
                        case DCH_ID:
                                from_char_parse_int_len(&out->d, &s, 1, n);
+                               /* Shift numbering to match Gregorian where Sunday = 1 */
+                               if (++out->d > 7)
+                                       out->d = 1;
                                s += SKIP_THth(n->suffix);
                                break;
                        case DCH_WW:
@@ -3534,7 +3538,7 @@ do_to_timestamp(text *date_txt, text *fmt,
        if (tmfc.w)
                tmfc.dd = (tmfc.w - 1) * 7 + 1;
        if (tmfc.d)
-               tm->tm_wday = tmfc.d;
+               tm->tm_wday = tmfc.d - 1;       /* convert to native numbering */
        if (tmfc.dd)
                tm->tm_mday = tmfc.dd;
        if (tmfc.ddd)
index 2adc178de4fbe1e14d010dc6f00fb07f9a6780b4..50ef8976bed9099efb9cd296ee570ffbadd00c83 100644 (file)
@@ -3775,18 +3775,22 @@ isoweek2date(int woy, int *year, int *mon, int *mday)
 
 /* isoweekdate2date()
  *
- *     Convert an ISO 8601 week date (ISO year, ISO week and day of week) into a Gregorian date.
+ *     Convert an ISO 8601 week date (ISO year, ISO week) into a Gregorian date.
+ *     Gregorian day of week sent so weekday strings can be supplied.
  *     Populates year, mon, and mday with the correct Gregorian values.
  *     year must be passed in as the ISO year.
  */
 void
-isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday)
+isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
 {
        int                     jday;
 
        jday = isoweek2j(*year, isoweek);
-       jday += isowday - 1;
-
+       /* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
+       if (wday > 1)
+               jday += wday - 2;
+       else
+               jday += 6;
        j2date(jday, year, mon, mday);
 }
 
index 665e969498cffe3df94e17985987311049a6fbbe..e7cdb417e59e6534d6b75c48a6efd226d6bbe349 100644 (file)
@@ -236,7 +236,7 @@ extern int  timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
 
 extern int     isoweek2j(int year, int week);
 extern void isoweek2date(int woy, int *year, int *mon, int *mday);
-extern void isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday);
+extern void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday);
 extern int     date2isoweek(int year, int mon, int mday);
 extern int     date2isoyear(int year, int mon, int mday);
 extern int     date2isoyearday(int year, int mon, int mday);