test_that("Serial number dates convert correctly", { expect_equal(excel_numeric_to_date(42370), as.Date("2016-01-01")) expect_equal(excel_numeric_to_date(42370, "modern"), as.Date("2016-01-01")) expect_equal(excel_numeric_to_date(40908, "mac pre-2011"), as.Date("2016-01-01")) }) test_that("Bad inputs handled appropriately", { expect_error(excel_numeric_to_date("hello"), "argument `date_num` must be of class numeric") expect_error(excel_numeric_to_date(40908, "bad string"), "argument 'date_system' must be one of 'mac pre-2011' or 'modern'") expect_error(excel_numeric_to_date(40908, 4), "argument 'date_system' must be one of 'mac pre-2011' or 'modern'") }) test_that("time handling works correctly", { expect_equal( excel_numeric_to_date(42370, include_time=TRUE), as.POSIXct("2016-01-01"), ignore_attr = TRUE, # ignore timezone info="Time inclusion works with an integer date" ) expect_equal( excel_numeric_to_date(42370.521, include_time=TRUE), as.POSIXct("2016-01-01 12:30:14"), ignore_attr = TRUE, # ignore timezone info="Time inclusion works with a fractional date/time and seconds rounded" ) expect_equal( excel_numeric_to_date(42370.521, include_time=TRUE, round_seconds=FALSE), as.POSIXct("2016-01-01 12:30:14.4"), ignore_attr = TRUE, # ignore timezone info="Time inclusion works with a fractional date/time and seconds not rounded" ) expect_equal( excel_numeric_to_date(42370.521, include_time=FALSE), as.Date("2016-01-01"), info="Time inclusion works with a fractional date/time and only the date kept." ) }) test_that("time handling at the edge of a minute works correctly", { expect_equal( excel_numeric_to_date(42001.1, include_time = TRUE), as.POSIXct("2014-12-28 02:24:00"), ignore_attr = TRUE, # ignore timezone info = "60 seconds gets converted to 0 seconds, +1 minute" ) }) test_that("time handling at the edge of the next date works correctly", { expect_warning(excel_numeric_to_date(42002 - 0.0005/86400, include_time=TRUE, round_seconds=FALSE), regexp="1 date_num values are within 0.001 sec of a later date and were rounded up to the next day.") # suppress warning on next two tests, that aspect is identical to preceding call where warning is checked expect_equal( suppressWarnings( excel_numeric_to_date(42002 - 0.0005/86400, include_time=TRUE, round_seconds=FALSE) ), as.POSIXct("2014-12-29"), ignore_attr = TRUE # ignore timezone ) expect_equal( suppressWarnings( excel_numeric_to_date(42002 - 0.0005/86400, include_time=TRUE, round_seconds=TRUE) ), as.POSIXct("2014-12-29"), ignore_attr = TRUE # ignore timezone ) expect_equal( excel_numeric_to_date(42002 - 0.0011/86400, include_time=TRUE, round_seconds=FALSE), as.POSIXct("2014-12-28 23:59:59.998"), ignore_attr = TRUE # ignore timezone ) expect_equal( excel_numeric_to_date(42002 - 0.0011/86400, include_time=TRUE, round_seconds=TRUE), as.POSIXct("2014-12-29"), ignore_attr = TRUE # ignore timezone ) }) test_that("excel_numeric_to_date handles NA", { expect_equal( excel_numeric_to_date(NA), as.Date(NA_character_), info="Return NA output of the correct class (Date) for NA input." ) expect_equal( excel_numeric_to_date(NA, include_time=TRUE), as.POSIXct(NA_character_, tz=Sys.timezone()), info="Return NA output of the correct class (POSIXct) for NA input." ) expect_equal( excel_numeric_to_date(c(43088, NA)), as.Date(floor(c(43088, NA)), origin = "1899-12-30"), info="Return NA output as part of a vector of inputs correctly" ) expect_equal( excel_numeric_to_date(c(43088, NA), include_time=TRUE, tz = "UTC"), as.POSIXct(as.Date(floor(c(43088, NA)), origin = "1899-12-30", tz = "UTC")), ignore_attr = TRUE, # ignore timezone info="Return NA output as part of a vector of inputs correctly" ) }) test_that("excel_numeric_to_date returns a POSIXct object when include_time is requested", { expect_s3_class( excel_numeric_to_date(c(43088, NA), include_time=TRUE), c("POSIXct", "POSIXt") ) }) test_that("time zone setting works", { expect_equal( attr(excel_numeric_to_date(43001.11, include_time = TRUE), "tzone"), Sys.timezone(), info="Defaults to the local timezone" ) expect_equal( attr(excel_numeric_to_date(43001.11, include_time = TRUE, tz = "America/New_York"), "tzone"), "America/New_York" ) expect_equal( attr(excel_numeric_to_date(43001.11, include_time = TRUE, tz = "Europe/Zurich"), "tzone"), "Europe/Zurich" ) expect_error( excel_numeric_to_date(43001.11, include_time = TRUE, tz = "nonsense"), info="Invalid timezone gives an error" ) }) test_that("integer Excel dates do not overflow (ref issue #241)", { expect_equal(excel_numeric_to_date(42370L), excel_numeric_to_date(42370)) }) test_that("daylight savings time handling (issue #420)", { expect_warning( expect_equal( excel_numeric_to_date(43170.09, include_time=TRUE, tz="America/New_York"), as.POSIXct(NA_real_, tz="America/New_York", origin="1900-01-01") ), regexp="NAs introduced by coercion, possible daylight savings time issue with input. Consider `tz='UTC'`.", fixed=TRUE ) expect_equal( excel_numeric_to_date(43170.09, include_time=TRUE, tz="UTC"), as.POSIXct("2018-03-11 02:09:36", tz="UTC") ) }) test_that("Nonexistent 29 Feb 1900 exists in Excel but not in accurate calendars", { expect_warning( expect_equal( excel_numeric_to_date(59:61), as.Date(c("1900-02-28", NA, "1900-03-01")) ), regexp="NAs introduced by coercion, Excel leap day bug detected in `date_num`. 29 February 1900 does not exist.", fixed=TRUE ) }) test_that("Negative dates are invalid in Excel (issue #423)", { expect_warning( expect_equal( excel_numeric_to_date(-1:1), as.Date(c("1899-12-30", "1899-12-31", "1900-01-01")) ), regexp="Only `date_num` >= 1 are valid in Excel, creating an earlier date than Excel supports.", fixed=TRUE ) })