diff --git a/NEWS.md b/NEWS.md index 7aeb2497ce..10816c1353 100644 --- a/NEWS.md +++ b/NEWS.md @@ -299,6 +299,8 @@ 18. Added a note to `?setkey` clarifying that `setkey` always uses C-locale sorting (as has been noted in `?setorder`). Thanks @JBreidaks for the report in [#2114](https://github.com/Rdatatable/data.table/issues/2114). +19. `hour()`/`minute()`/`second()` are much faster for `ITime` input, [#3518](https://github.com/Rdatatable/data.table/issues/3158). + ### Changes in [v1.12.2](https://github.com/Rdatatable/data.table/milestone/14?closed=1) (07 Apr 2019) diff --git a/R/IDateTime.R b/R/IDateTime.R index c0e31bc248..3c28fa909f 100644 --- a/R/IDateTime.R +++ b/R/IDateTime.R @@ -303,28 +303,22 @@ as.POSIXlt.ITime = function(x, ...) { ################################################################### second = function(x) { - if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) { - # if we know the object is in UTC, can calculate the hour much faster - as.integer(as.numeric(x) %% 60L) - } else { - as.integer(as.POSIXlt(x)$sec) - } + # if we know the object is in UTC, can calculate the hour much faster + if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) return(as.integer(as.numeric(x) %% 60L)) + if (inherits(x, 'ITime')) return(as.integer(x) %% 60L) + as.integer(as.POSIXlt(x)$sec) } minute = function(x) { - if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) { - # ever-so-slightly faster than x %% 3600L %/% 60L - as.integer(as.numeric(x) %/% 60L %% 60L) - } else { - as.POSIXlt(x)$min - } + # ever-so-slightly faster than x %% 3600L %/% 60L + if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) return(as.integer(as.numeric(x) %/% 60L %% 60L)) + if (inherits(x, 'ITime')) return(as.integer(x) %/% 60L %% 60L) + as.POSIXlt(x)$min } hour = function(x) { - if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) { - # ever-so-slightly faster than x %% 86400L %/% 3600L - as.integer(as.numeric(x) %/% 3600L %% 24L) - } else { - as.POSIXlt(x)$hour - } + # ever-so-slightly faster than x %% 86400L %/% 3600L + if (inherits(x, 'POSIXct') && identical(attr(x, 'tzone', exact=TRUE), 'UTC')) return(as.integer(as.numeric(x) %/% 3600L %% 24L)) + if (inherits(x, 'ITime')) return(as.integer(x) %/% 3600L %% 24L) + as.POSIXlt(x)$hour } yday = function(x) as.POSIXlt(x)$yday + 1L wday = function(x) (unclass(as.IDate(x)) + 4L) %% 7L + 1L diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index c9067a2b42..8c72cf6c29 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -13361,6 +13361,10 @@ z = .POSIXct(3725, 'UTC') test(1962.101, second(z), 5L) test(1962.102, minute(z), 2L) test(1962.103, hour(z), 1L) +z = as.ITime(z) +test(1962.201, second(z), 5L) +test(1962.202, minute(z), 2L) +test(1962.203, hour(z), 1L) # positive and negative values for shift, #1708 DT = data.table(x = 1:10, y = 10:1)