From ea7fd32a79d8a5a7457123a647bdb71a3cb4aeba Mon Sep 17 00:00:00 2001 From: DavisVaughan Date: Thu, 18 Mar 2021 10:04:42 -0400 Subject: [PATCH] Floor double Dates before casting to integer with `duration_days()` We are generally a bit more lax with Dates and POSIXct. For POSIXct, we already floor to get rid of fractional seconds, so this just adds similar behavior for Dates and fractional days. --- R/date.R | 3 +++ tests/testthat/test-date.R | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/R/date.R b/R/date.R index 41840222..3e50eee9 100644 --- a/R/date.R +++ b/R/date.R @@ -2,6 +2,9 @@ as_sys_time.Date <- function(x) { names <- names(x) x <- unstructure(x) + if (is.double(x)) { + x <- floor(x) + } x <- duration_days(x) new_sys_time_from_fields(x, PRECISION_DAY, names) } diff --git a/tests/testthat/test-date.R b/tests/testthat/test-date.R index b73ac5ff..176523a2 100644 --- a/tests/testthat/test-date.R +++ b/tests/testthat/test-date.R @@ -5,6 +5,26 @@ test_that("invalid dates must be resolved when converting to a Date", { expect_snapshot_error(as.Date(year_month_day(2019, 2, 31))) }) +# ------------------------------------------------------------------------------ +# as_sys_time() + +test_that("converting to sys-time floors fractional dates (#191)", { + x <- new_date(c(-0.5, 1.5)) + y <- new_date(c(-1, 1)) + + expect_identical(as_sys_time(x), as_sys_time(y)) + expect_identical(as.Date(as_sys_time(x)), y) +}) + +test_that("converting to sys-time works with integer storage dates", { + # These can occur from `seq.Date(from, to, length.out)` + x <- structure(1L, class = "Date") + y <- new_date(1) + + expect_identical(as_sys_time(x), as_sys_time(y)) + expect_identical(as.Date(as_sys_time(x)), y) +}) + # ------------------------------------------------------------------------------ # as_weekday()