Skip to content
Open
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: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

12. `print.data.table()` now truncates long character columns and list-column summaries by default to avoid horizontal console overflow, [#7718](https://github.com/Rdatatable/data.table/issues/7718). When `datatable.prettyprint.char` is `NULL` (the default), the truncation limit is now dynamically calculated based on the available console width. Use `options(datatable.prettyprint.char=Inf)` for the old default behavior (never truncate). Thanks @tdhock for the report and @venom1204 for the fix.

13. `as.IDate()` and `as.ITime()` now preserve names, matching base `as.Date()` behavior, [#7252](https://github.com/Rdatatable/data.table/issues/7252). Thanks @DavisVaughan for the report and @venom1204 for the PR.

### Notes

1. {data.table} now depends on R 3.5.0 (2018).
Expand Down
47 changes: 33 additions & 14 deletions R/IDateTime.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

as.IDate = function(x, ...) UseMethod("as.IDate")

copy_names = function(ans, nm) {
if (!is.null(nm)) setattr(ans, "names", nm)
ans
}

as.IDate.default = function(x, ..., tz = attr(x, "tzone", exact=TRUE)) {
if (is.null(tz)) tz = "UTC"
if (is.character(x)) {
Expand All @@ -15,32 +20,36 @@ as.IDate.default = function(x, ..., tz = attr(x, "tzone", exact=TRUE)) {
}

as.IDate.numeric = function(x, origin = "1970-01-01", ...) {
nm = names(x)
if (origin=="1970-01-01") {
# standard epoch
x = as.integer(x)
class(x) = c("IDate", "Date")
# We used to use structure() here because class(x)<- copied several times in R before v3.1.0
# Since R 3.1.0 improved class()<- and data.table's oldest oldest supported R is now 3.1.0, we can use class<- again
# structure() contains a match() and replace for specials, which we don't need.
# class()<- ensures at least 1 shallow copy as appropriate is returned.
x
copy_names(x, nm)
} else {
# only call expensive as.IDate.character if we have to
as.IDate(origin, ...) + as.integer(x)
ans = as.IDate(origin, ...) + as.integer(x)
copy_names(ans, nm)
}
}

as.IDate.Date = function(x, ...) {
x = as.integer(x) # if already integer, x will be left unchanged as the original input
class(x) = c("IDate", "Date") # class()<- will copy if as.integer() did not create, and may not if it did we hope
x # always return a new object
nm = names(x)
x = as.integer(x)
class(x) = c("IDate", "Date")
copy_names(x, nm)
}

as.IDate.POSIXct = function(x, tz = attr(x, "tzone", exact=TRUE), ...) {
if (is_utc(tz))
(setattr(as.integer(as.numeric(x) %/% 86400L), "class", c("IDate", "Date"))) # %/% returns new object so can use setattr() on it; wrap with () to return visibly
else
if (is_utc(tz)) {
ans = as.integer(as.numeric(x) %/% 86400L)
setattr(ans, "class", c("IDate", "Date"))
copy_names(ans, names(x))
} else {
as.IDate(as.Date(x, tz = tz %||% '', ...))
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we remove the blank line here?

as.IDate.IDate = function(x, ...) x
Expand Down Expand Up @@ -155,13 +164,19 @@ as.ITime.POSIXct = function(x, tz = attr(x, "tzone", exact=TRUE), ...) {
}

as.ITime.numeric = function(x, ms = 'truncate', ...) {
nm = names(x)
secs = clip_msec(x, ms) %% 86400L # the %% here ensures a local copy is obtained; the truncate as.integer() may not copy
(setattr(secs, "class", "ITime"))
setattr(secs, "class", "ITime")
copy_names(secs, nm)
}

as.ITime.character = function(x, format, ...) {
nm = names(x)
x = unclass(x)
if (!missing(format)) return(as.ITime(strptime(x, format = format, ...), ...))
if (!missing(format)) {
ans = as.ITime(strptime(x, format = format, ...), ...)
return(copy_names(ans, nm))
}
# else allow for mixed formats, such as test 1189 where seconds are caught despite varying format
y = strptime(x, format = "%H:%M:%OS", ...)
w = which(is.na(y))
Expand All @@ -181,12 +196,16 @@ as.ITime.character = function(x, format, ...) {
w = w[!nna]
}
}
as.ITime(y, ...)
ans = as.ITime(y, ...)
copy_names(ans, nm)
}

as.ITime.POSIXlt = function(x, ms = 'truncate', ...) {
nm = names(x)
secs = clip_msec(x$sec, ms)
(setattr(with(x, secs + min * 60L + hour * 3600L), "class", "ITime")) # () wrap to return visibly
ans = with(x, secs + min * 60L + hour * 3600L)
setattr(ans, "class", "ITime")
copy_names(ans, nm)
}

as.ITime.times = function(x, ms = 'truncate', ...) {
Expand Down
12 changes: 12 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -21669,3 +21669,15 @@ test(2375.3, print(data.table(x=c("short", "abcdefghijklmnopqrstuvwxyz"))), outp
test(2375.4, print(data.table(x="abcdefghijklmnopqrstuvwxyz")), output="abcdefghijklmnopqrstuvwxyz", options=list(width=200, datatable.prettyprint.char=NULL))
test(2375.5, print(data.table(id=1L, score=99.1, txt="abcdefghijklmnopqrstuvwxyz")), output="abcdefghijklmn...", options=list(width=20, datatable.prettyprint.char=NULL))
test(2375.6, print(data.table(x=rep("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1e6)), topn=1), output="1000000: ABCDEFGHIJKLM...", options=list(width=25, datatable.prettyprint.char=NULL))

# #7252 as.IDate()/as.ITime preserve names
test(2376.01, names(as.IDate(c(a = "2019-01-01"))), "a")
test(2376.02, names(c(a = as.IDate("2019-01-01"))), "a")
test(2376.03, names(as.ITime(c(a = "12:00:00"))), "a")
test(2376.04, names(as.IDate(structure(as.POSIXct("2019-01-01 12:00:00"), names = "a"))), "a")
test(2376.05, names(as.ITime(structure(3600, names = "a"))), "a")
test(2376.06, names(as.IDate(c(a = 18000))), "a")
test(2376.07, names(as.IDate(c(a = 1), origin = "2020-01-01")), "a")
test(2376.08, names(as.ITime(c(a = "12-00-00"), format = "%H-%M-%S")), "a")
test(2376.09, names(as.IDate(as.POSIXct(c(a = "2019-01-01"), tz="UTC"))), "a")
test(2376.10, names(as.IDate(as.POSIXct(c(a = "2019-01-01"), tz="America/New_York"))), "a")
Loading