diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 25af8a212b..2aa6df1756 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 2adc178de4..50ef8976be 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 665e969498..e7cdb417e5 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);