aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2012-09-03 22:52:34 -0400
committerBruce Momjian <bruce@momjian.us>2012-09-03 22:52:44 -0400
commit015722fb364416b29fb1bb2c10631feb67ad61cd (patch)
treedfeaba3901788d298d2b122f3d2aa6eb18fa8071
parente442b0f0c6fd26738bafdeb5222511b586dfe4b9 (diff)
downloadpostgresql-015722fb364416b29fb1bb2c10631feb67ad61cd.tar.gz
postgresql-015722fb364416b29fb1bb2c10631feb67ad61cd.zip
Fix to_date() and to_timestamp() to allow specification of the day of
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
-rw-r--r--src/backend/utils/adt/formatting.c10
-rw-r--r--src/backend/utils/adt/timestamp.c12
-rw-r--r--src/include/utils/timestamp.h2
3 files changed, 16 insertions, 8 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 25af8a212b8..2aa6df1756b 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -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)
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 2adc178de4f..50ef8976bed 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -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);
}
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index 665e969498c..e7cdb417e59 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -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);