Skip to content

Commit 63355f3

Browse files
committed
accomodated breaking change
1 parent 59f966c commit 63355f3

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@
333333
334334
19. Ellipsis elements like `..1` are correctly excluded when searching for variables in "up-a-level" syntax inside `[`, [#5460](https://github.com/Rdatatable/data.table/issues/5460). Thanks @ggrothendieck for the report and @MichaelChirico for the fix.
335335
336+
20. BREAKING CHANGE: `week()` now calculates the week of the year sequentially (days 1-7 are week 1), fixing a bug where the first week could have 6 days. A one-time warning is now issued if this change affects the output for a given input, which can be disabled via `options(datatable.warn.week.change = FALSE)`. [#2611](https://github.com/Rdatatable/data.table/issues/2611). Thanks to @MichaelChirico for the report and @venom1204 for the fix.
337+
336338
### NOTES
337339
338340
1. The following in-progress deprecations have proceeded:

inst/tests/tests.Rraw

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202
1838418384
test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA))
1838518385
test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA))
1838618386
test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA))
18387-
test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA))
18387+
test(2236.4, suppressWarnings(week(x)), c(45L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA))
1838818388
test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA))
1838918389
test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA))
1839018390
test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA))
@@ -21815,3 +21815,11 @@ test(2341.24, fread('a
2181521815
# leading cmnt
2181621816
b
2181721817
', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b")))
21818+
21819+
# week() sequential numbering fix tests #2611
21820+
test(2342.1, week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L)) # Jan 1–7 all week 1, Jan 8 week 2
21821+
test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L)) # leap day stays in same week
21822+
test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L)) # year boundary non-leap → reset to 1
21823+
test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L)) # year boundary leap → reset to 1
21824+
test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L))
21825+
test(2342.6, week(as.IDate(c("2016-02-27","2016-02-28","2016-02-29","2016-03-01","2016-03-02"))), c(9L,9L,9L,9L,9L))

src/idatetime.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "data.table.h"
22

3+
static int week_warning_issued = 0;
4+
35
static const int YEARS400 = 146097;
46
static const int YEARS100 = 36524;
57
static const int YEARS4 = 1461;
@@ -64,7 +66,7 @@ void convertSingleDate(int x, datetype type, void *out)
6466
yday -= YEARS1 + leap;
6567
*(int *)out = ++yday;
6668
if (type == WEEK)
67-
*(int *)out = (*(int *)out / 7) + 1;
69+
*(int *)out = ((*(int *)out - 1) / 7) + 1;
6870
return;
6971
}
7072

@@ -143,6 +145,29 @@ SEXP convertDate(SEXP x, SEXP type)
143145
else if (!strcmp(ctype_str, "yearqtr")) { ctype = YEARQTR; ansint = false; }
144146
else internal_error(__func__, "invalid type, should have been caught before"); // # nocov
145147

148+
if (ctype == WEEK) {
149+
if (!week_warning_issued) {
150+
SEXP dt_week_warn_opt = GetOption(install("datatable.warn.week.change"), R_NilValue);
151+
if (!isLogical(dt_week_warn_opt) || LOGICAL(dt_week_warn_opt)[0] != FALSE) {
152+
for (int i = 0; i < n; i++) {
153+
if (ix[i] == NA_INTEGER) continue;
154+
155+
int yday;
156+
convertSingleDate(ix[i], YDAY, &yday);
157+
158+
int old_week = (yday / 7) + 1;
159+
int new_week = ((yday - 1) / 7) + 1;
160+
161+
if (new_week != old_week) {
162+
Rf_warning("data.table::week() behavior has changed and is now sequential (day 1-7 is week 1). The first week of the year may differ from previous versions. To suppress this warning, run: options(datatable.warn.week.change = FALSE)");
163+
week_warning_issued = 1;
164+
break;
165+
}
166+
}
167+
}
168+
}
169+
}
170+
146171
if (ansint) {
147172
SEXP ans = PROTECT(allocVector(INTSXP, n));
148173
int *ansp = INTEGER(ans);

0 commit comments

Comments
 (0)