test_that("defined(POSIXct) preserves values, can be coerced back", { p <- as.POSIXct("2024-01-01 12:00:00", tz = "UTC" ) + (0:2) * 3600 p_def <- defined(p, label = "Time variable", unit = "hour") expect_true(is.defined(p_def)) expect_true(inherits(p_def, "haven_labelled_defined")) expect_true(inherits(p_def, "POSIXct")) expect_equal(var_unit(p_def), "hour") expect_equal(var_label(p_def), "Time variable") expect_equal(attr(as.POSIXct(p_def), "tzone"), "UTC") expect_equal( as.numeric(unclass(p_def)), as.numeric(unclass(p)) ) }) test_that("as.Date coercion can strip attributes if needed", { p <- as.POSIXct("2024-01-01 12:00:00", tz = "UTC" ) + (0:2) * 3600 p_def <- defined(p, label = "Time variable", unit = "hour") stripped_attributes <- names(attributes(as.POSIXct(p_def, TRUE))) expect_equal(stripped_attributes, c("class", "tzone")) }) test_that("as.POSIXct.haven_labelled_defined respects user-initiated tz change", { # base POSIXct in UTC base_time <- as.POSIXct("2024-01-01 12:00:00", tz = "UTC") # wrap in defined()/haven_labelled_defined with metadata x <- defined( base_time, label = "Timestamp", unit = "seconds" ) target_tz <- "Europe/Budapest" # user explicitly requests a new time zone out <- as.POSIXct(x, tz = target_tz, strip_attributes = FALSE) # what base R would do without the wrapper expected <- base::as.POSIXct(base_time, tz = target_tz) # 1) Class and wrapper removal expect_s3_class(out, "POSIXct") expect_true(inherits(out, "POSIXt")) expect_false(inherits(out, "haven_labelled_defined")) # 2) Instant in time: same as base R's conversion expect_identical(as.numeric(out), as.numeric(expected)) # 3) Time zone: whatever base R uses, we mirror expect_identical(attr(out, "tzone"), attr(expected, "tzone")) # 4) Metadata: by default strip_attributes = TRUE, so we keep it expect_identical(attr(out, "label"), "Timestamp") expect_identical(attr(out, "unit"), "seconds") }) test_that("as.POSIXct.haven_labelled_defined strips attributes when requested", { base_time <- as.POSIXct("2024-01-01 12:00:00", tz = "UTC") x <- defined( base_time, label = "Timestamp", unit = "seconds" ) target_tz <- "Europe/Budapest" out <- as.POSIXct(x, tz = target_tz, strip_attributes = TRUE) expected <- base::as.POSIXct(base_time, tz = target_tz) # Still matches base R conversion expect_identical(as.numeric(out), as.numeric(expected)) expect_identical(attr(out, "tzone"), attr(expected, "tzone")) # Metadata stripped expect_null(attr(out, "label")) expect_null(attr(out, "unit")) })