diff --git a/NAMESPACE b/NAMESPACE index cd7027c77d..c0dff9067c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -153,7 +153,7 @@ if (getRversion() >= "3.6.0") { # IDateTime support: export(as.IDate,as.ITime,IDateTime) -export(second,minute,hour,yday,wday,mday,week,isoweek,month,quarter,year,yearmon,yearqtr) +export(second,minute,hour,yday,wday,mday,week,isoweek,isoyear,month,quarter,year,yearmon,yearqtr) S3method("[", ITime) S3method("+", IDate) diff --git a/NEWS.md b/NEWS.md index 598e534d26..f6e86d20f1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -67,6 +67,8 @@ 14. `fcoalesce()` and `setcoalesce()` gain `nan` argument to control whether `NaN` values should be treated as missing (`nan=NA`, the default) or non-missing (`nan=NaN`), [#4567](https://github.com/Rdatatable/data.table/issues/4567). This provides full compatibility with `nafill()` behavior. Thanks to @ethanbsmith for the feature request and @Mukulyadav2004 for the implementation. +15. New function `isoyear()` has been implemented as a complement to `isoweek()`, returning the ISO 8601 year corresponding to a given date, [#7154](https://github.com/Rdatatable/data.table/issues/7154). Thanks to @ben-schwen and @MichaelChirico for the suggestion and @venom1204 for the implementation. + ### BUG FIXES 1. `fread()` no longer warns on certain systems on R 4.5.0+ where the file owner can't be resolved, [#6918](https://github.com/Rdatatable/data.table/issues/6918). Thanks @ProfFancyPants for the report and PR. diff --git a/R/IDateTime.R b/R/IDateTime.R index 383ceb54e7..5b079a0298 100644 --- a/R/IDateTime.R +++ b/R/IDateTime.R @@ -355,7 +355,7 @@ isoweek = function(x) as.integer(format(as.IDate(x), "%V")) # nearest_thurs = as.IDate(7L * (as.integer(x + 3L) %/% 7L)) # year_start = as.IDate(format(nearest_thurs, '%Y-01-01')) # 1L + (nearest_thurs - year_start) %/% 7L - +isoyear = function(x) as.integer(format(as.IDate(x), "%G")) month = function(x) convertDate(as.IDate(x), "month") quarter = function(x) convertDate(as.IDate(x), "quarter") diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index a2549ccf6d..fd7e22eec1 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21549,3 +21549,11 @@ f = tempfile() writeLines(c('a', rep('0x1.ffffp0', 10000L), '0x1.ff\x9fp0', rep('0x1.ffffp0', 20000L)), f) test(2334, names(fread(f)), "a") unlink(f) + +# Tests for new isoyear() helper (complement to isoweek) #7154 +test(2335.1, isoyear(as.IDate("2019-12-30")), 2020L) # End of year edge case +test(2335.2, isoyear(as.IDate("2016-01-01")), 2015L) # Start of year edge case +test(2335.3, isoyear(as.IDate("2023-08-15")), 2023L) # Normal mid-year case +test(2335.4, isoyear(as.IDate(c("2019-12-30", "2016-01-01", "2023-08-15"))),c(2020L, 2015L, 2023L)) +test(2335.5, isoyear("2019-12-30"), 2020L) +test(2335.6, isoyear(as.Date("2019-12-30")), 2020L) diff --git a/man/IDateTime.Rd b/man/IDateTime.Rd index 64c75d3902..f1e5190afe 100644 --- a/man/IDateTime.Rd +++ b/man/IDateTime.Rd @@ -38,6 +38,7 @@ \alias{mday} \alias{week} \alias{isoweek} +\alias{isoyear} \alias{month} \alias{quarter} \alias{year} @@ -92,6 +93,7 @@ wday(x) mday(x) week(x) isoweek(x) +isoyear(x) month(x) quarter(x) year(x) @@ -187,6 +189,8 @@ which specify that the first week of the year is the one containing the first Th This convention ensures that week boundaries align consistently with year boundaries, accounting for both year transitions and varying day counts per week. +Similarly, \code{isoyear()} returns the ISO 8601 year corresponding to the ISO week. + } \value{ @@ -200,7 +204,7 @@ accounting for both year transitions and varying day counts per week. \code{itime} in \code{IDate} and \code{ITime} format. \code{second}, \code{minute}, \code{hour}, \code{yday}, \code{wday}, - \code{mday}, \code{week}, \code{month}, \code{quarter}, + \code{mday}, \code{week}, \code{isoweek}, \code{isoyear}, \code{month}, \code{quarter}, and \code{year} return integer values for second, minute, hour, day of year, day of week, day of month, week, month, quarter, and year, respectively. @@ -281,6 +285,17 @@ round(seqdates, "months") round(seqtimes, "hours") trunc(seqtimes, "hours") +# Examples for isoyear() and isoweek() +d1 = as.IDate("2019-12-30") +year(d1) +isoweek(d1) +isoyear(d1) + +d2 = as.IDate("2016-01-01") +year(d2) +isoweek(d2) +isoyear(d2) + } \keyword{utilities}