Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #1765 -- new isoweek function produces ISO 8601-consistent week numbering as an integer #1829

Merged
merged 1 commit into from
Aug 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ S3method(na.omit, data.table)

# IDateTime support:
export(as.IDate,as.ITime,IDateTime)
export(second,minute,hour,yday,wday,mday,week,month,quarter,year)
export(second,minute,hour,yday,wday,mday,week,isoweek,month,quarter,year)

export(as.chron.IDate, as.chron.ITime)
export(as.Date.IDate) # workaround for zoo bug, see #1500
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@

43. `first()` is now exported to return the first element of vectors, data.frames and data.tables.

44. Added `second` and `minute` extraction functions which, like extant `hour`/`yday`/`week`/etc, always return an integer, [#874](https://github.com/Rdatatable/data.table/issues/874). Thanks to @bthieurmel for the FR and @MichaelChirico for the PR.
44. Added `second` and `minute` extraction functions which, like extant `hour`/`yday`/`week`/etc, always return an integer, [#874](https://github.com/Rdatatable/data.table/issues/874). Also added ISO 8601-consistent weeks in `isoweek`, [#1765](https://github.com/Rdatatable/data.table/issues/1765). Thanks to @bthieurmel and @STATWORX for the FRs and @MichaelChirico for the PRs.

44. `shift()` understands and operates on list-of-list inputs as well, [#1595](https://github.com/Rdatatable/data.table/issues/1595). Thanks to @enfascination and to @chris for [asking on SO](http://stackoverflow.com/q/38900293/559784).

Expand Down
19 changes: 19 additions & 0 deletions R/IDateTime.R
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,25 @@ yday <- function(x) as.POSIXlt(x)$yday + 1L
wday <- function(x) as.POSIXlt(x)$wday + 1L
mday <- function(x) as.POSIXlt(x)$mday
week <- function(x) yday(x) %/% 7L + 1L
isoweek <- function(x) {
#ISO 8601-conformant week, as described at
# https://en.wikipedia.org/wiki/ISO_week_date

#Approach:
# * Find nearest Thursday to each element of x
# * Find the number of weeks having passed between
# January 1st of the year of the nearest Thursdays and x

xlt <- as.POSIXlt(x)

#We want Thursday to be 3 (4 by default in POSIXlt), so
# subtract 1 and re-divide; also, POSIXlt increment by seconds
nearest_thurs <- xlt + (3 - ((xlt$wday - 1) %% 7)) * 86400

year_start <- as.POSIXct(paste0(as.POSIXlt(nearest_thurs)$year + 1900L, "-01-01"))

as.integer(1 + unclass(difftime(nearest_thurs, year_start, units = "days")) %/% 7)
}
month <- function(x) as.POSIXlt(x)$mon + 1L
quarter <- function(x) as.POSIXlt(x)$mon %/% 3L + 1L
year <- function(x) as.POSIXlt(x)$year + 1900L
Expand Down
14 changes: 14 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -9204,6 +9204,20 @@ test(1701.6, A[B, .(x.x, get("x.x"), x.y), on="x", by=.EACHI], data.table(x=c(2,
dt = data.table(a=1L)
test(1701.7, dt[dt, .(xa=x.a, ia=i.a), .EACHI, on="a"], data.table(a=1L, xa=1L, ia=1L))

# ISO 8601-consistent week numbering, #1765
# test cases via https://en.wikipedia.org/wiki/ISO_week_date
test_cases <- c("2005-01-01", "2005-01-02", "2005-12-31",
"2007-01-01", "2007-12-30", "2007-12-31",
"2008-01-01", "2008-12-28", "2008-12-29",
"2008-12-30", "2008-12-31", "2009-01-01",
"2009-12-31", "2010-01-01",
"2010-01-02", "2010-01-03")

test_values <- c(53L, 53L, 52L, 1L, 52L, 1L, 1L,
52L, 1L, 1L, 1L, 1L, 53L, 53L, 53L, 53L)

test(1702, isoweek(test_cases), test_values)

##########################

# TODO: Tests involving GForce functions needs to be run with optimisation level 1 and 2, so that both functions are tested all the time.
Expand Down
5 changes: 4 additions & 1 deletion man/IDateTime.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
\alias{wday}
\alias{mday}
\alias{week}
\alias{isoweek}
\alias{month}
\alias{quarter}
\alias{year}
Expand Down Expand Up @@ -73,6 +74,7 @@ yday(x)
wday(x)
mday(x)
week(x)
isoweek(x)
month(x)
quarter(x)
year(x)
Expand Down Expand Up @@ -135,7 +137,7 @@ intervals. \code{as.POSIXlt} is also useful. For example,
\code{as.POSIXlt(x)$mon} is the integer month. The R base convenience
functions \code{weekdays}, \code{months}, and \code{quarters} can also
be used, but these return character values, so they must be converted to
factors for use with data.table.
factors for use with data.table. \code{isoweek} is ISO 8601-consistent.

The \code{round} method for IDate's is useful for grouping and plotting. It can
round to weeks, months, quarters, and years.
Expand Down Expand Up @@ -168,6 +170,7 @@ round to weeks, months, quarters, and years.

H. Wickham, http://gist.github.com/10238.

ISO 8601, http://www.iso.org/iso/home/standards/iso8601.htm
}

\author{ Tom Short, t.short@ieee.org }
Expand Down