Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 015722f

Browse files
committed
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
1 parent e442b0f commit 015722f

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ typedef struct
412412
mi,
413413
ss,
414414
ssss,
415-
d,
415+
d, /* stored as 1-7, Sunday = 1, 0 means missing */
416416
dd,
417417
ddd,
418418
mm,
@@ -2897,13 +2897,15 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
28972897
from_char_seq_search(&value, &s, days, ONE_UPPER,
28982898
MAX_DAY_LEN, n);
28992899
from_char_set_int(&out->d, value, n);
2900+
out->d++;
29002901
break;
29012902
case DCH_DY:
29022903
case DCH_Dy:
29032904
case DCH_dy:
29042905
from_char_seq_search(&value, &s, days, ONE_UPPER,
29052906
MAX_DY_LEN, n);
29062907
from_char_set_int(&out->d, value, n);
2908+
out->d++;
29072909
break;
29082910
case DCH_DDD:
29092911
from_char_parse_int(&out->ddd, &s, n);
@@ -2919,11 +2921,13 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
29192921
break;
29202922
case DCH_D:
29212923
from_char_parse_int(&out->d, &s, n);
2922-
out->d--;
29232924
s += SKIP_THth(n->suffix);
29242925
break;
29252926
case DCH_ID:
29262927
from_char_parse_int_len(&out->d, &s, 1, n);
2928+
/* Shift numbering to match Gregorian where Sunday = 1 */
2929+
if (++out->d > 7)
2930+
out->d = 1;
29272931
s += SKIP_THth(n->suffix);
29282932
break;
29292933
case DCH_WW:
@@ -3534,7 +3538,7 @@ do_to_timestamp(text *date_txt, text *fmt,
35343538
if (tmfc.w)
35353539
tmfc.dd = (tmfc.w - 1) * 7 + 1;
35363540
if (tmfc.d)
3537-
tm->tm_wday = tmfc.d;
3541+
tm->tm_wday = tmfc.d - 1; /* convert to native numbering */
35383542
if (tmfc.dd)
35393543
tm->tm_mday = tmfc.dd;
35403544
if (tmfc.ddd)

src/backend/utils/adt/timestamp.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3775,18 +3775,22 @@ isoweek2date(int woy, int *year, int *mon, int *mday)
37753775

37763776
/* isoweekdate2date()
37773777
*
3778-
* Convert an ISO 8601 week date (ISO year, ISO week and day of week) into a Gregorian date.
3778+
* Convert an ISO 8601 week date (ISO year, ISO week) into a Gregorian date.
3779+
* Gregorian day of week sent so weekday strings can be supplied.
37793780
* Populates year, mon, and mday with the correct Gregorian values.
37803781
* year must be passed in as the ISO year.
37813782
*/
37823783
void
3783-
isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday)
3784+
isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday)
37843785
{
37853786
int jday;
37863787

37873788
jday = isoweek2j(*year, isoweek);
3788-
jday += isowday - 1;
3789-
3789+
/* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
3790+
if (wday > 1)
3791+
jday += wday - 2;
3792+
else
3793+
jday += 6;
37903794
j2date(jday, year, mon, mday);
37913795
}
37923796

src/include/utils/timestamp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
236236

237237
extern int isoweek2j(int year, int week);
238238
extern void isoweek2date(int woy, int *year, int *mon, int *mday);
239-
extern void isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday);
239+
extern void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday);
240240
extern int date2isoweek(int year, int mon, int mday);
241241
extern int date2isoyear(int year, int mon, int mday);
242242
extern int date2isoyearday(int year, int mon, int mday);

0 commit comments

Comments
 (0)