From 63355f3ea78251b6ad5fc94f9d4151d400a07a98 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Tue, 21 Oct 2025 18:36:58 +0000 Subject: [PATCH 01/14] accomodated breaking change --- NEWS.md | 2 ++ inst/tests/tests.Rraw | 10 +++++++++- src/idatetime.c | 27 ++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 60cb1dd0ce..3bcf941f76 100644 --- a/NEWS.md +++ b/NEWS.md @@ -333,6 +333,8 @@ 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. +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. + ### NOTES 1. The following in-progress deprecations have proceeded: diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 2e1284aea6..67dbe307c7 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA)) +test(2236.4, suppressWarnings(week(x)), c(45L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA)) test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) 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 # leading cmnt b ', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b"))) + +# week() sequential numbering fix tests #2611 +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 +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 +test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L)) # year boundary non-leap → reset to 1 +test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L)) # year boundary leap → reset to 1 +test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L)) +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)) diff --git a/src/idatetime.c b/src/idatetime.c index eaeb35a96f..3066a66c76 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -1,5 +1,7 @@ #include "data.table.h" +static int week_warning_issued = 0; + static const int YEARS400 = 146097; static const int YEARS100 = 36524; static const int YEARS4 = 1461; @@ -64,7 +66,7 @@ void convertSingleDate(int x, datetype type, void *out) yday -= YEARS1 + leap; *(int *)out = ++yday; if (type == WEEK) - *(int *)out = (*(int *)out / 7) + 1; + *(int *)out = ((*(int *)out - 1) / 7) + 1; return; } @@ -143,6 +145,29 @@ SEXP convertDate(SEXP x, SEXP type) else if (!strcmp(ctype_str, "yearqtr")) { ctype = YEARQTR; ansint = false; } else internal_error(__func__, "invalid type, should have been caught before"); // # nocov + if (ctype == WEEK) { + if (!week_warning_issued) { + SEXP dt_week_warn_opt = GetOption(install("datatable.warn.week.change"), R_NilValue); + if (!isLogical(dt_week_warn_opt) || LOGICAL(dt_week_warn_opt)[0] != FALSE) { + for (int i = 0; i < n; i++) { + if (ix[i] == NA_INTEGER) continue; + + int yday; + convertSingleDate(ix[i], YDAY, &yday); + + int old_week = (yday / 7) + 1; + int new_week = ((yday - 1) / 7) + 1; + + if (new_week != old_week) { + 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)"); + week_warning_issued = 1; + break; + } + } + } + } + } + if (ansint) { SEXP ans = PROTECT(allocVector(INTSXP, n)); int *ansp = INTEGER(ans); From 647720149073364bd8043614905ab706a03cdaa6 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 12:06:48 +0000 Subject: [PATCH 02/14] updated logic --- NEWS.md | 4 ++-- inst/tests/tests.Rraw | 3 ++- src/idatetime.c | 54 +++++++++++++++++++++++++++++++------------ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3bcf941f76..4aa12d5bfc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,6 +38,8 @@ 1. `data.table(x=1, )`, where `` is an expression resulting in a 1-column matrix without column names, will eventually have names `x` and `V2`, not `x` and `V1`, consistent with `data.table(x=1, )` where `` results in an atomic vector, for example `data.table(x=1, cbind(1))` and `data.table(x=1, 1)` will both have columns named `x` and `V2`. In this release, the matrix case continues to be named `V1`, but the new behavior can be activated by setting `options(datatable.old.matrix.autoname)` to `FALSE`. See point 5 under Bug Fixes for more context; this change will provide more internal consistency as well as more consistency with `data.frame()`. +2. The `week()` function will be fixed in a future release to correctly calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current (buggy) behavior remains the default. A one-time deprecation warning will be issued when the old and new behaviors differ; this can be suppressed with `options(datatable.warn.week.deprecation = FALSE)`. Users can opt-in to the correct behavior now with the temporary option `options(datatable.week.new = TRUE)`. See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report. + ### NEW FEATURES 1. New `sort_by()` method for data.tables, [#6662](https://github.com/Rdatatable/data.table/issues/6662). It uses `forder()` to improve upon the data.frame method and also matches `DT[order(...)]` behavior with respect to locale. Thanks @rikivillalba for the suggestion and PR. @@ -333,8 +335,6 @@ 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. -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. - ### NOTES 1. The following in-progress deprecations have proceeded: diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 67dbe307c7..859b2ad33c 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, suppressWarnings(week(x)), c(45L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA)) +test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning="The current behavior of data.table::week() is deprecated") test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA)) @@ -21817,6 +21817,7 @@ b ', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b"))) # week() sequential numbering fix tests #2611 +options(datatable.week.new = TRUE) 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 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 test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L)) # year boundary non-leap → reset to 1 diff --git a/src/idatetime.c b/src/idatetime.c index 3066a66c76..5ec6b1953b 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -1,6 +1,6 @@ #include "data.table.h" -static int week_warning_issued = 0; +static int week_deprecation_warning_issued = 0; static const int YEARS400 = 146097; static const int YEARS100 = 36524; @@ -65,8 +65,15 @@ void convertSingleDate(int x, datetype type, void *out) if (yday >= YEARS1 + leap) yday -= YEARS1 + leap; *(int *)out = ++yday; - if (type == WEEK) - *(int *)out = ((*(int *)out - 1) / 7) + 1; + if (type == WEEK) { + SEXP opt_new = GetOption(install("datatable.week.new"), R_NilValue); + bool use_new_behavior = isLogical(opt_new) && LOGICAL(opt_new)[0] == TRUE; + if (use_new_behavior) { + *(int *)out = ((*(int *)out - 1) / 7) + 1; + } else { + *(int *)out = (*(int *)out / 7) + 1; + } + } return; } @@ -146,26 +153,43 @@ SEXP convertDate(SEXP x, SEXP type) else internal_error(__func__, "invalid type, should have been caught before"); // # nocov if (ctype == WEEK) { - if (!week_warning_issued) { - SEXP dt_week_warn_opt = GetOption(install("datatable.warn.week.change"), R_NilValue); - if (!isLogical(dt_week_warn_opt) || LOGICAL(dt_week_warn_opt)[0] != FALSE) { - for (int i = 0; i < n; i++) { - if (ix[i] == NA_INTEGER) continue; + SEXP ans = PROTECT(allocVector(INTSXP, n)); + int *ansp = INTEGER(ans); - int yday; - convertSingleDate(ix[i], YDAY, &yday); + SEXP opt_new = GetOption(install("datatable.week.new"), R_NilValue); + bool use_new_behavior = isLogical(opt_new) && LOGICAL(opt_new)[0] == TRUE; - int old_week = (yday / 7) + 1; - int new_week = ((yday - 1) / 7) + 1; + bool can_warn = false; + if (!use_new_behavior && !week_deprecation_warning_issued) { + SEXP opt_warn_depr = GetOption(install("datatable.warn.week.deprecation"), R_NilValue); + can_warn = !isLogical(opt_warn_depr) || LOGICAL(opt_warn_depr)[0] != FALSE; + } + for (int i = 0; i < n; i++) { + if (ix[i] == NA_INTEGER) { + ansp[i] = NA_INTEGER; + continue; + } + int yday; + convertSingleDate(ix[i], YDAY, &yday); + + if (use_new_behavior) { + ansp[i] = ((yday - 1) / 7) + 1; + } else { + int old_week = (yday / 7) + 1; + ansp[i] = old_week; + if (can_warn) { + int new_week = ((yday - 1) / 7) + 1; if (new_week != old_week) { - 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)"); - week_warning_issued = 1; - break; + Rf_warning("The current behavior of data.table::week() is deprecated and will be fixed in a future version to be sequential (day 1-7 is week 1). To opt-in to the new behavior now, run: options(datatable.week.new = TRUE). To suppress this warning, run: options(datatable.warn.week.deprecation = FALSE)"); + week_deprecation_warning_issued = 1; + can_warn = false; } } } } + UNPROTECT(1); + return ans; } if (ansint) { From 3e053a2c9660c632dc84d0c724b6efc61874417d Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 12:37:45 +0000 Subject: [PATCH 03/14] .. --- src/idatetime.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/idatetime.c b/src/idatetime.c index 5ec6b1953b..9abf6d4a0e 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -60,20 +60,11 @@ void convertSingleDate(int x, datetype type, void *out) int leap = !years1 && (years4 || !years100); - if (type == YDAY || type == WEEK) { + if (type == YDAY) { int yday = days + 31 + 28 + leap; if (yday >= YEARS1 + leap) yday -= YEARS1 + leap; *(int *)out = ++yday; - if (type == WEEK) { - SEXP opt_new = GetOption(install("datatable.week.new"), R_NilValue); - bool use_new_behavior = isLogical(opt_new) && LOGICAL(opt_new)[0] == TRUE; - if (use_new_behavior) { - *(int *)out = ((*(int *)out - 1) / 7) + 1; - } else { - *(int *)out = (*(int *)out / 7) + 1; - } - } return; } From b78b3d8a53a15b7e47865cb2da41fd5e1d756a08 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 18:02:11 +0000 Subject: [PATCH 04/14] updated tests --- inst/tests/tests.Rraw | 15 +++++++-------- src/idatetime.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 859b2ad33c..1d2801d5b0 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning="The current behavior of data.table::week() is deprecated") +test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning="The current behavior of data.table::week() is deprecated", options = list(datatable.warn.week.deprecation = NULL)) test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA)) @@ -21817,10 +21817,9 @@ b ', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b"))) # week() sequential numbering fix tests #2611 -options(datatable.week.new = TRUE) -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 -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 -test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L)) # year boundary non-leap → reset to 1 -test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L)) # year boundary leap → reset to 1 -test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L)) -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)) +test(2342.1, week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L), options = list(datatable.week.new = TRUE)) +test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L), options = list(datatable.week.new = TRUE)) +test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week.new = TRUE)) +test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week.new = TRUE)) +test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L), options = list(datatable.week.new = TRUE)) +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), options = list(datatable.week.new = TRUE)) \ No newline at end of file diff --git a/src/idatetime.c b/src/idatetime.c index 9abf6d4a0e..23c7d54ef4 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -172,7 +172,7 @@ SEXP convertDate(SEXP x, SEXP type) if (can_warn) { int new_week = ((yday - 1) / 7) + 1; if (new_week != old_week) { - Rf_warning("The current behavior of data.table::week() is deprecated and will be fixed in a future version to be sequential (day 1-7 is week 1). To opt-in to the new behavior now, run: options(datatable.week.new = TRUE). To suppress this warning, run: options(datatable.warn.week.deprecation = FALSE)"); + warning("The current behavior of data.table::week() is deprecated and will be fixed in a future version to be sequential (day 1-7 is week 1). To opt-in to the new behavior now, run: options(datatable.week.new = TRUE). To suppress this warning, run: options(datatable.warn.week.deprecation = FALSE)"); week_deprecation_warning_issued = 1; can_warn = false; } From d4d0b2d929139310b6ae4823171cbafff7d51fba Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 20:08:42 +0000 Subject: [PATCH 05/14] sequential and legacy --- NEWS.md | 5 ++++- inst/tests/tests.Rraw | 14 +++++++------- src/idatetime.c | 25 +++++++++++-------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4aa12d5bfc..912cc801c1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,7 +38,10 @@ 1. `data.table(x=1, )`, where `` is an expression resulting in a 1-column matrix without column names, will eventually have names `x` and `V2`, not `x` and `V1`, consistent with `data.table(x=1, )` where `` results in an atomic vector, for example `data.table(x=1, cbind(1))` and `data.table(x=1, 1)` will both have columns named `x` and `V2`. In this release, the matrix case continues to be named `V1`, but the new behavior can be activated by setting `options(datatable.old.matrix.autoname)` to `FALSE`. See point 5 under Bug Fixes for more context; this change will provide more internal consistency as well as more consistency with `data.frame()`. -2. The `week()` function will be fixed in a future release to correctly calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current (buggy) behavior remains the default. A one-time deprecation warning will be issued when the old and new behaviors differ; this can be suppressed with `options(datatable.warn.week.deprecation = FALSE)`. Users can opt-in to the correct behavior now with the temporary option `options(datatable.week.new = TRUE)`. See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report. +2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior remains the default, and a one-time deprecation warning will be issued. Users can control this behavior with the temporary option `options(datatable.week = "...")`: + * `"sequential"`: Opt-in to the new, sequential behavior (no warning). + * `"legacy"`: Continue using the legacy behavior but suppress the deprecation warning. +See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom12_04 for the PR. ### NEW FEATURES diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 1d2801d5b0..28c308ddb2 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning="The current behavior of data.table::week() is deprecated", options = list(datatable.warn.week.deprecation = NULL)) +test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning = "The default behavior of data.table::week() is deprecated", options = list(datatable.week = NULL)) test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA)) @@ -21817,9 +21817,9 @@ b ', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b"))) # week() sequential numbering fix tests #2611 -test(2342.1, week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L), options = list(datatable.week.new = TRUE)) -test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L), options = list(datatable.week.new = TRUE)) -test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week.new = TRUE)) -test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week.new = TRUE)) -test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L), options = list(datatable.week.new = TRUE)) -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), options = list(datatable.week.new = TRUE)) \ No newline at end of file +test(2342.1, week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L), options = list(datatable.week = "sequential")) +test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L), options = list(datatable.week = "sequential")) +test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) +test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) +test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L), options = list(datatable.week = "sequential")) +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), options = list(datatable.week = "sequential")) \ No newline at end of file diff --git a/src/idatetime.c b/src/idatetime.c index 23c7d54ef4..163bdeda07 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -147,14 +147,12 @@ SEXP convertDate(SEXP x, SEXP type) SEXP ans = PROTECT(allocVector(INTSXP, n)); int *ansp = INTEGER(ans); - SEXP opt_new = GetOption(install("datatable.week.new"), R_NilValue); - bool use_new_behavior = isLogical(opt_new) && LOGICAL(opt_new)[0] == TRUE; + SEXP opt = GetOption(install("datatable.week"), R_NilValue); + const char *mode = isString(opt) && length(opt) == 1 ? CHAR(STRING_ELT(opt, 0)) : "default"; - bool can_warn = false; - if (!use_new_behavior && !week_deprecation_warning_issued) { - SEXP opt_warn_depr = GetOption(install("datatable.warn.week.deprecation"), R_NilValue); - can_warn = !isLogical(opt_warn_depr) || LOGICAL(opt_warn_depr)[0] != FALSE; - } + bool use_sequential = !strcmp(mode, "sequential"); + bool use_legacy = !strcmp(mode, "legacy"); + bool can_warn = !use_sequential && !use_legacy && !week_deprecation_warning_issued; for (int i = 0; i < n; i++) { if (ix[i] == NA_INTEGER) { @@ -163,19 +161,18 @@ SEXP convertDate(SEXP x, SEXP type) } int yday; convertSingleDate(ix[i], YDAY, &yday); + int new_week = ((yday - 1) / 7) + 1; - if (use_new_behavior) { - ansp[i] = ((yday - 1) / 7) + 1; + if (use_sequential) { + ansp[i] = new_week; } else { int old_week = (yday / 7) + 1; ansp[i] = old_week; - if (can_warn) { - int new_week = ((yday - 1) / 7) + 1; - if (new_week != old_week) { - warning("The current behavior of data.table::week() is deprecated and will be fixed in a future version to be sequential (day 1-7 is week 1). To opt-in to the new behavior now, run: options(datatable.week.new = TRUE). To suppress this warning, run: options(datatable.warn.week.deprecation = FALSE)"); + if (can_warn && new_week != old_week) { + warning(_("The default behavior of data.table::week() is deprecated. It will be changed to 'sequential' in a future version. To opt-in to the new behavior now, run: options(datatable.week = 'sequential'). To suppress this warning and continue using the legacy behavior, run: options(datatable.week = 'legacy').")); week_deprecation_warning_issued = 1; can_warn = false; - } + } } } From 5967661bfbcb5e6318956c3a04072390f1f92031 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 23:37:41 +0000 Subject: [PATCH 06/14] updated test --- inst/tests/tests.Rraw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 28c308ddb2..35c0ae2046 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), warning = "The default behavior of data.table::week() is deprecated", options = list(datatable.week = NULL)) +test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), options = list(datatable.week = "legacy")) test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA)) From 7951e5a3f986d2bc473da5a26e170e53a4664105 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Thu, 23 Oct 2025 05:13:39 +0530 Subject: [PATCH 07/14] Update NEWS.md Co-authored-by: Benjamin Schwendinger <52290390+ben-schwen@users.noreply.github.com> --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 912cc801c1..686b0aa325 100644 --- a/NEWS.md +++ b/NEWS.md @@ -41,7 +41,7 @@ 2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior remains the default, and a one-time deprecation warning will be issued. Users can control this behavior with the temporary option `options(datatable.week = "...")`: * `"sequential"`: Opt-in to the new, sequential behavior (no warning). * `"legacy"`: Continue using the legacy behavior but suppress the deprecation warning. -See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom12_04 for the PR. +See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the PR. ### NEW FEATURES From 86112e538839259a1d4979de7082ff4e3abc0d2a Mon Sep 17 00:00:00 2001 From: venom1204 Date: Thu, 23 Oct 2025 05:13:52 +0530 Subject: [PATCH 08/14] Update src/idatetime.c Co-authored-by: Benjamin Schwendinger <52290390+ben-schwen@users.noreply.github.com> --- src/idatetime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idatetime.c b/src/idatetime.c index 163bdeda07..c7081c2ba5 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -169,7 +169,7 @@ SEXP convertDate(SEXP x, SEXP type) int old_week = (yday / 7) + 1; ansp[i] = old_week; if (can_warn && new_week != old_week) { - warning(_("The default behavior of data.table::week() is deprecated. It will be changed to 'sequential' in a future version. To opt-in to the new behavior now, run: options(datatable.week = 'sequential'). To suppress this warning and continue using the legacy behavior, run: options(datatable.week = 'legacy').")); + warning(_("The default behavior of week() is changing. Previously ('legacy' mode), week numbers advanced every 7th day of the year. The new 'sequential' mode ensures the first week always has 7 days. For example, as.IDate('2023-01-07') returns week 2 in legacy mode but week 1 in sequential mode (week 2 starts on '2023-01-08'). To adopt the new behavior now, set options(datatable.week = 'sequential'). To keep the old results and silence this warning, set options(datatable.week = 'legacy'). See https://github.com/Rdatatable/data.table/issues/2611")); week_deprecation_warning_issued = 1; can_warn = false; From 77a0cf69cd57f1f89d83824cd4172bfab0e6741f Mon Sep 17 00:00:00 2001 From: venom1204 Date: Wed, 22 Oct 2025 23:46:09 +0000 Subject: [PATCH 09/14] .. --- inst/tests/tests.Rraw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 35c0ae2046..a86ed94fac 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21817,7 +21817,7 @@ b ', comment.char = '#', strip.white = FALSE, sep = ","), data.table(a=c(" ", "b"))) # week() sequential numbering fix tests #2611 -test(2342.1, week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L), options = list(datatable.week = "sequential")) +test(2342.1, options = c(datatable.week = "sequential"), week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L)) test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L), options = list(datatable.week = "sequential")) test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) From 0d292d603eb4ad1eafb6428a30b7f486977ebb10 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Thu, 23 Oct 2025 11:27:36 +0000 Subject: [PATCH 10/14] tests --- inst/tests/tests.Rraw | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index a86ed94fac..88c95ff569 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18384,7 +18384,7 @@ x = c("1111-11-11", "2019-01-01", "2019-02-28", "2019-03-01", "2019-12-31", "202 test(2236.1, yday(x), c(315L, 1L, 59L, 60L, 365L, 60L, 61L, 366L, 1L, 366L, 60L, NA)) test(2236.2, mday(x), c(11L, 1L, 28L, 1L, 31L, 29L, 1L, 31L, 1L, 31L, 1L, NA)) test(2236.3, wday(x), c(7L, 3L, 5L, 6L, 3L, 7L, 1L, 5L, 1L, 2L, 2L, NA)) -test(2236.4, week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA), options = list(datatable.week = "legacy")) +test(2236.4, options = c(datatable.week = "legacy"), week(x), c(46L, 1L, 9L, 9L, 53L, 9L, 9L, 53L, 1L, 53L, 9L, NA)) test(2236.5, month(x), c(11L, 1L, 2L, 3L, 12L, 2L, 3L, 12L, 1L, 12L, 3L, NA)) test(2236.6, quarter(x), c(4L, 1L, 1L, 1L, 4L, 1L, 1L, 4L, 1L, 4L, 1L, NA)) test(2236.7, year(x), c(1111L, 2019L, 2019L, 2019L, 2019L, 2020L, 2020L, 2020L, 2040L, 2040L, 2100L, NA)) @@ -21822,4 +21822,5 @@ test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L, test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L), options = list(datatable.week = "sequential")) -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), options = list(datatable.week = "sequential")) \ No newline at end of file +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), options = list(datatable.week = "sequential")) +test(2342.7, week(as.IDate("1970-01-07")), 2L, warning = "The default behavior of week() is changing", options = list(datatable.week = NULL)) From 21f8841c15a1cfd7a45626b5f5140444af20398c Mon Sep 17 00:00:00 2001 From: venom1204 Date: Thu, 23 Oct 2025 18:58:52 +0000 Subject: [PATCH 11/14] removed one time error --- NEWS.md | 6 +++--- src/idatetime.c | 8 ++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index 686b0aa325..969e7ac0ca 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,11 +38,11 @@ 1. `data.table(x=1, )`, where `` is an expression resulting in a 1-column matrix without column names, will eventually have names `x` and `V2`, not `x` and `V1`, consistent with `data.table(x=1, )` where `` results in an atomic vector, for example `data.table(x=1, cbind(1))` and `data.table(x=1, 1)` will both have columns named `x` and `V2`. In this release, the matrix case continues to be named `V1`, but the new behavior can be activated by setting `options(datatable.old.matrix.autoname)` to `FALSE`. See point 5 under Bug Fixes for more context; this change will provide more internal consistency as well as more consistency with `data.frame()`. -2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior remains the default, and a one-time deprecation warning will be issued. Users can control this behavior with the temporary option `options(datatable.week = "...")`: +2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior remains the default, and a deprecation warning will be issued when the old and new behaviors differ. Users can control this behavior with the temporary option `options(datatable.week = "...")`: * `"sequential"`: Opt-in to the new, sequential behavior (no warning). * `"legacy"`: Continue using the legacy behavior but suppress the deprecation warning. -See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the PR. - + See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the PR. + ### NEW FEATURES 1. New `sort_by()` method for data.tables, [#6662](https://github.com/Rdatatable/data.table/issues/6662). It uses `forder()` to improve upon the data.frame method and also matches `DT[order(...)]` behavior with respect to locale. Thanks @rikivillalba for the suggestion and PR. diff --git a/src/idatetime.c b/src/idatetime.c index c7081c2ba5..ec3ce3ed3a 100644 --- a/src/idatetime.c +++ b/src/idatetime.c @@ -1,7 +1,5 @@ #include "data.table.h" -static int week_deprecation_warning_issued = 0; - static const int YEARS400 = 146097; static const int YEARS100 = 36524; static const int YEARS4 = 1461; @@ -152,7 +150,7 @@ SEXP convertDate(SEXP x, SEXP type) bool use_sequential = !strcmp(mode, "sequential"); bool use_legacy = !strcmp(mode, "legacy"); - bool can_warn = !use_sequential && !use_legacy && !week_deprecation_warning_issued; + bool can_warn = !use_sequential && !use_legacy; for (int i = 0; i < n; i++) { if (ix[i] == NA_INTEGER) { @@ -170,9 +168,7 @@ SEXP convertDate(SEXP x, SEXP type) ansp[i] = old_week; if (can_warn && new_week != old_week) { warning(_("The default behavior of week() is changing. Previously ('legacy' mode), week numbers advanced every 7th day of the year. The new 'sequential' mode ensures the first week always has 7 days. For example, as.IDate('2023-01-07') returns week 2 in legacy mode but week 1 in sequential mode (week 2 starts on '2023-01-08'). To adopt the new behavior now, set options(datatable.week = 'sequential'). To keep the old results and silence this warning, set options(datatable.week = 'legacy'). See https://github.com/Rdatatable/data.table/issues/2611")); - week_deprecation_warning_issued = 1; - can_warn = false; - + can_warn = false; } } } From fb250d4967edc8c7028b906273417e645a05c3e5 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Fri, 24 Oct 2025 17:59:12 +0000 Subject: [PATCH 12/14] updated new --- NEWS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 969e7ac0ca..a0949f3318 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,10 +38,10 @@ 1. `data.table(x=1, )`, where `` is an expression resulting in a 1-column matrix without column names, will eventually have names `x` and `V2`, not `x` and `V1`, consistent with `data.table(x=1, )` where `` results in an atomic vector, for example `data.table(x=1, cbind(1))` and `data.table(x=1, 1)` will both have columns named `x` and `V2`. In this release, the matrix case continues to be named `V1`, but the new behavior can be activated by setting `options(datatable.old.matrix.autoname)` to `FALSE`. See point 5 under Bug Fixes for more context; this change will provide more internal consistency as well as more consistency with `data.frame()`. -2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior remains the default, and a deprecation warning will be issued when the old and new behaviors differ. Users can control this behavior with the temporary option `options(datatable.week = "...")`: +2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior, where week numbers advance every 7th day of the year (e.g., day 7 starts week 2), remains the default, and a deprecation warning will be issued when the old and new behaviors differ. Users can control this behavior with the temporary option `options(datatable.week = "...")`: * `"sequential"`: Opt-in to the new, sequential behavior (no warning). * `"legacy"`: Continue using the legacy behavior but suppress the deprecation warning. - See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the PR. +See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the implementation. ### NEW FEATURES From e8e33e764477e314b47404a2815cdc247e9a1d40 Mon Sep 17 00:00:00 2001 From: venom1204 Date: Fri, 24 Oct 2025 18:01:27 +0000 Subject: [PATCH 13/14] tests --- inst/tests/tests.Rraw | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 88c95ff569..609977b991 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21818,9 +21818,9 @@ b # week() sequential numbering fix tests #2611 test(2342.1, options = c(datatable.week = "sequential"), week(as.IDate("1970-01-01") + 0:7), c(1L,1L,1L,1L,1L,1L,1L,2L)) -test(2342.2, week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L), options = list(datatable.week = "sequential")) -test(2342.3, week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) -test(2342.4, week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L), options = list(datatable.week = "sequential")) -test(2342.5, week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L), options = list(datatable.week = "sequential")) -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), options = list(datatable.week = "sequential")) -test(2342.7, week(as.IDate("1970-01-07")), 2L, warning = "The default behavior of week() is changing", options = list(datatable.week = NULL)) +test(2342.2, options = c(datatable.week = "sequential"), week(as.IDate(c("2012-02-28","2012-02-29","2012-03-01"))), c(9L,9L,9L)) +test(2342.3, options = c(datatable.week = "sequential"), week(as.IDate(c("2019-12-31","2020-01-01"))), c(53L,1L)) +test(2342.4, options = c(datatable.week = "sequential"), week(as.IDate(c("2020-12-31","2021-01-01"))), c(53L,1L)) +test(2342.5, options = c(datatable.week = "sequential"), week(as.IDate("2021-01-06") + 0:6), c(1L,1L,2L,2L,2L,2L,2L)) +test(2342.6, options = c(datatable.week = "sequential"), 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)) +test(2342.7, options = c(datatable.week = "default"), week(as.IDate("1970-01-07")), 2L, warning = "The default behavior of week() is changing") \ No newline at end of file From eff4fad67b38a956b2277f9cba8029292e3f0eb3 Mon Sep 17 00:00:00 2001 From: Benjamin Schwendinger <52290390+ben-schwen@users.noreply.github.com> Date: Sat, 25 Oct 2025 13:28:38 +0200 Subject: [PATCH 14/14] remove double space --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index a0949f3318..3face7519b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -41,7 +41,7 @@ 2. The behavior of `week()` will be changed in a future release to calculate weeks sequentially (days 1-7 as week 1), which is a potential breaking change. For now, the current "legacy" behavior, where week numbers advance every 7th day of the year (e.g., day 7 starts week 2), remains the default, and a deprecation warning will be issued when the old and new behaviors differ. Users can control this behavior with the temporary option `options(datatable.week = "...")`: * `"sequential"`: Opt-in to the new, sequential behavior (no warning). * `"legacy"`: Continue using the legacy behavior but suppress the deprecation warning. -See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the implementation. +See [#2611](https://github.com/Rdatatable/data.table/issues/2611) for details. Thanks @MichaelChirico for the report and @venom1204 for the implementation. ### NEW FEATURES