Commit 015722fb authored by Bruce Momjian's avatar Bruce Momjian

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
parent e442b0f0
...@@ -412,7 +412,7 @@ typedef struct ...@@ -412,7 +412,7 @@ typedef struct
mi, mi,
ss, ss,
ssss, ssss,
d, d, /* stored as 1-7, Sunday = 1, 0 means missing */
dd, dd,
ddd, ddd,
mm, mm,
...@@ -2897,6 +2897,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out) ...@@ -2897,6 +2897,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
from_char_seq_search(&value, &s, days, ONE_UPPER, from_char_seq_search(&value, &s, days, ONE_UPPER,
MAX_DAY_LEN, n); MAX_DAY_LEN, n);
from_char_set_int(&out->d, value, n); from_char_set_int(&out->d, value, n);
out->d++;
break; break;
case DCH_DY: case DCH_DY:
case DCH_Dy: case DCH_Dy:
...@@ -2904,6 +2905,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out) ...@@ -2904,6 +2905,7 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
from_char_seq_search(&value, &s, days, ONE_UPPER, from_char_seq_search(&value, &s, days, ONE_UPPER,
MAX_DY_LEN, n); MAX_DY_LEN, n);
from_char_set_int(&out->d, value, n); from_char_set_int(&out->d, value, n);
out->d++;
break; break;
case DCH_DDD: case DCH_DDD:
from_char_parse_int(&out->ddd, &s, n); from_char_parse_int(&out->ddd, &s, n);
...@@ -2919,11 +2921,13 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out) ...@@ -2919,11 +2921,13 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
break; break;
case DCH_D: case DCH_D:
from_char_parse_int(&out->d, &s, n); from_char_parse_int(&out->d, &s, n);
out->d--;
s += SKIP_THth(n->suffix); s += SKIP_THth(n->suffix);
break; break;
case DCH_ID: case DCH_ID:
from_char_parse_int_len(&out->d, &s, 1, n); 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); s += SKIP_THth(n->suffix);
break; break;
case DCH_WW: case DCH_WW:
...@@ -3534,7 +3538,7 @@ do_to_timestamp(text *date_txt, text *fmt, ...@@ -3534,7 +3538,7 @@ do_to_timestamp(text *date_txt, text *fmt,
if (tmfc.w) if (tmfc.w)
tmfc.dd = (tmfc.w - 1) * 7 + 1; tmfc.dd = (tmfc.w - 1) * 7 + 1;
if (tmfc.d) if (tmfc.d)
tm->tm_wday = tmfc.d; tm->tm_wday = tmfc.d - 1; /* convert to native numbering */
if (tmfc.dd) if (tmfc.dd)
tm->tm_mday = tmfc.dd; tm->tm_mday = tmfc.dd;
if (tmfc.ddd) if (tmfc.ddd)
......
...@@ -3775,18 +3775,22 @@ isoweek2date(int woy, int *year, int *mon, int *mday) ...@@ -3775,18 +3775,22 @@ isoweek2date(int woy, int *year, int *mon, int *mday)
/* isoweekdate2date() /* 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. * Populates year, mon, and mday with the correct Gregorian values.
* year must be passed in as the ISO year. * year must be passed in as the ISO year.
*/ */
void 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; int jday;
jday = isoweek2j(*year, isoweek); 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); j2date(jday, year, mon, mday);
} }
......
...@@ -236,7 +236,7 @@ extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2); ...@@ -236,7 +236,7 @@ extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
extern int isoweek2j(int year, int week); extern int isoweek2j(int year, int week);
extern void isoweek2date(int woy, int *year, int *mon, int *mday); 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 date2isoweek(int year, int mon, int mday);
extern int date2isoyear(int year, int mon, int mday); extern int date2isoyear(int year, int mon, int mday);
extern int date2isoyearday(int year, int mon, int mday); extern int date2isoyearday(int year, int mon, int mday);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment