From 6effc50505af2195acf4b89f8adcd0884fc293af Mon Sep 17 00:00:00 2001 From: sorhawell Date: Sat, 9 Dec 2023 23:31:30 +0100 Subject: [PATCH 1/4] fix posixct conv back and forth --- src/rust/src/conversion_r_to_s.rs | 2 +- src/rust/src/conversion_s_to_r.rs | 14 +++++++------- tests/testthat/test-expr_datetime.R | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/rust/src/conversion_r_to_s.rs b/src/rust/src/conversion_r_to_s.rs index 9eb49faf6..17becfa46 100644 --- a/src/rust/src/conversion_r_to_s.rs +++ b/src/rust/src/conversion_r_to_s.rs @@ -219,7 +219,7 @@ fn recursive_robjname2series_tree(x: &Robj, name: &str) -> pl::PolarsResult { diff --git a/src/rust/src/conversion_s_to_r.rs b/src/rust/src/conversion_s_to_r.rs index 0cfa1cf09..80b27befe 100644 --- a/src/rust/src/conversion_s_to_r.rs +++ b/src/rust/src/conversion_s_to_r.rs @@ -186,19 +186,19 @@ pub fn pl_series_to_list( }), Datetime(tu, opt_tz) => { - let tu_i64: i64 = match tu { - pl::TimeUnit::Nanoseconds => 1_000_000_000, - pl::TimeUnit::Microseconds => 1_000_000, - pl::TimeUnit::Milliseconds => 1_000, + let tu_f64: f64 = match tu { + pl::TimeUnit::Nanoseconds => 1_000_000_000.0, + pl::TimeUnit::Microseconds => 1_000_000.0, + pl::TimeUnit::Milliseconds => 1_000.0, }; //resolve timezone let tz = opt_tz.as_ref().map(|s| s.as_str()).unwrap_or(""); - s.cast(&Int64)? - .i64() + s.cast(&Float64)? + .f64() .map(|ca| { ca.into_iter() - .map(|opt| opt.map(|val| (val / tu_i64) as f64)) + .map(|opt| opt.map(|val| val / tu_f64)) .collect_robj() }) // TODO set_class and set_attrib reallocates the vector, find some way to modify without. diff --git a/tests/testthat/test-expr_datetime.R b/tests/testthat/test-expr_datetime.R index 921574c9a..8971e4532 100644 --- a/tests/testthat/test-expr_datetime.R +++ b/tests/testthat/test-expr_datetime.R @@ -18,6 +18,18 @@ test_that("pl$lit posix", { pl$lit(as.POSIXct("2022-01-01", tz = "GMT"))$to_r(), as.POSIXct("2022-01-01", tz = "GMT") ) + + + x = as.POSIXct( + c( + "2020-01-01 13:45:48.343", "2020-01-01 13:45:48.815" + , "2020-01-01 13:45:49.289", "2020-01-01 13:45:49.974" + , "2020-01-01 13:45:51.190", "2020-01-01 13:45:51.631" + ), tz = "UTC" + ) + expect_identical(pl$lit(x)$to_r(), x) #preserve millisecond precision + expect_failure(expect_identical(pl$lit(x)$to_r(), x+0.001)) #control, detect 1ms offset + }) @@ -846,3 +858,7 @@ test_that("$dt$time()", { c(0.00e+00, 2.16e+13, 4.32e+13, 6.48e+13, 0.00e+00) ) }) + + + + From 3e428c1b74b1f044b800f2e58c7d11ec1f782de2 Mon Sep 17 00:00:00 2001 From: eitsupi Date: Sun, 10 Dec 2023 03:22:23 +0000 Subject: [PATCH 2/4] auto formatting --- tests/testthat/test-expr_datetime.R | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/testthat/test-expr_datetime.R b/tests/testthat/test-expr_datetime.R index 8971e4532..ea9d921dd 100644 --- a/tests/testthat/test-expr_datetime.R +++ b/tests/testthat/test-expr_datetime.R @@ -22,14 +22,14 @@ test_that("pl$lit posix", { x = as.POSIXct( c( - "2020-01-01 13:45:48.343", "2020-01-01 13:45:48.815" - , "2020-01-01 13:45:49.289", "2020-01-01 13:45:49.974" - , "2020-01-01 13:45:51.190", "2020-01-01 13:45:51.631" - ), tz = "UTC" + "2020-01-01 13:45:48.343", "2020-01-01 13:45:48.815", + "2020-01-01 13:45:49.289", "2020-01-01 13:45:49.974", + "2020-01-01 13:45:51.190", "2020-01-01 13:45:51.631" + ), + tz = "UTC" ) - expect_identical(pl$lit(x)$to_r(), x) #preserve millisecond precision - expect_failure(expect_identical(pl$lit(x)$to_r(), x+0.001)) #control, detect 1ms offset - + expect_identical(pl$lit(x)$to_r(), x) # preserve millisecond precision + expect_failure(expect_identical(pl$lit(x)$to_r(), x + 0.001)) # control, detect 1ms offset }) @@ -858,7 +858,3 @@ test_that("$dt$time()", { c(0.00e+00, 2.16e+13, 4.32e+13, 6.48e+13, 0.00e+00) ) }) - - - - From 2d29101834a30e9eb18f503c013f527cfeedb199 Mon Sep 17 00:00:00 2001 From: eitsupi Date: Sun, 10 Dec 2023 03:33:04 +0000 Subject: [PATCH 3/4] docs: update news --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index d286dd108..c98ae68ea 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,6 +28,8 @@ alternatives to `$str$strptime()` (#558). - The `dim()` function for DataFrame and LazyFrame correctly returns integer instead of double (#577). +- The conversion of R's `POSIXct` class to Polars datetime now works correctly with millisecond + precision (#589). # polars 0.11.0 From 8042dc1b7c557f86cd83cbc728ceb7e22651c85f Mon Sep 17 00:00:00 2001 From: eitsupi Date: Sun, 10 Dec 2023 03:45:35 +0000 Subject: [PATCH 4/4] test: move the test case --- tests/testthat/test-datatype.R | 34 ++++++++++++++++++++++++++++ tests/testthat/test-expr_datetime.R | 35 ----------------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/tests/testthat/test-datatype.R b/tests/testthat/test-datatype.R index b524cedfb..8f3041ffc 100644 --- a/tests/testthat/test-datatype.R +++ b/tests/testthat/test-datatype.R @@ -32,3 +32,37 @@ test_that("plStruct", { err_state = result(pl$Struct(bin = pl$Binary, pl$Boolean, bob = 42)) }) + + +test_that("POSIXct data conversion", { + expect_identical( + pl$lit(as.POSIXct("2022-01-01"))$to_r(), + as.POSIXct("2022-01-01") + ) + + expect_identical( + pl$lit(as.POSIXct("2022-01-01", tz = "GMT"))$to_r(), + as.POSIXct("2022-01-01", tz = "GMT") + ) + + expect_identical( + pl$lit(as.POSIXct("2022-01-01", tz = "HST"))$to_r(), + as.POSIXct("2022-01-01", tz = "HST") + ) + + expect_identical( + pl$lit(as.POSIXct("2022-01-01", tz = "GMT"))$to_r(), + as.POSIXct("2022-01-01", tz = "GMT") + ) + + + x = as.POSIXct( + c( + "2020-01-01 13:45:48.343", + "2020-01-01 13:45:48.343999" + ), + tz = "UTC" + ) + # POSIXct is converted to datetime[ms], so sub-ms precision is lost + expect_identical(pl$lit(x)$to_r(), as.POSIXct(c("2020-01-01 13:45:48.343", "2020-01-01 13:45:48.343"), tz = "UTC")) +}) diff --git a/tests/testthat/test-expr_datetime.R b/tests/testthat/test-expr_datetime.R index ea9d921dd..02141c27e 100644 --- a/tests/testthat/test-expr_datetime.R +++ b/tests/testthat/test-expr_datetime.R @@ -1,38 +1,3 @@ -test_that("pl$lit posix", { - expect_identical( - pl$lit(as.POSIXct("2022-01-01"))$to_r(), - as.POSIXct("2022-01-01") - ) - - expect_identical( - pl$lit(as.POSIXct("2022-01-01", tz = "GMT"))$to_r(), - as.POSIXct("2022-01-01", tz = "GMT") - ) - - expect_identical( - pl$lit(as.POSIXct("2022-01-01", tz = "HST"))$to_r(), - as.POSIXct("2022-01-01", tz = "HST") - ) - - expect_identical( - pl$lit(as.POSIXct("2022-01-01", tz = "GMT"))$to_r(), - as.POSIXct("2022-01-01", tz = "GMT") - ) - - - x = as.POSIXct( - c( - "2020-01-01 13:45:48.343", "2020-01-01 13:45:48.815", - "2020-01-01 13:45:49.289", "2020-01-01 13:45:49.974", - "2020-01-01 13:45:51.190", "2020-01-01 13:45:51.631" - ), - tz = "UTC" - ) - expect_identical(pl$lit(x)$to_r(), x) # preserve millisecond precision - expect_failure(expect_identical(pl$lit(x)$to_r(), x + 0.001)) # control, detect 1ms offset -}) - - test_that("pl$date_range", { t1 = as.POSIXct("2022-01-01") t2 = as.POSIXct("2022-01-02")