# ------------------------------------------------------------------------------ # vec_proxy_compare() # Really testing `vec_proxy()` and `vec_ptype2()` / `vec_cast()` test_that("can't compare zoned-times with different zones", { x <- as_zoned_time(sys_days(0), "America/New_York") y <- as_zoned_time(sys_days(0), "UTC") expect_snapshot(error = TRUE, x > y) }) test_that("can compare zoned-times with same zone", { x <- as_zoned_time(sys_days(0:1), "America/New_York") expect_false(x[1] > x[2]) expect_true(x[1] < x[2]) }) # ------------------------------------------------------------------------------ # print() / obj_print_data() / obj_print_footer() test_that("normal print method works", { x <- as_zoned_time(as_sys_time(year_month_day(2019, 1:5, 1)), "America/New_York") expect_snapshot(x) }) test_that("can limit with `max`", { x <- as_zoned_time(as_sys_time(year_month_day(2019, 1:5, 1)), "America/New_York") expect_snapshot(print(x, max = 2)) expect_snapshot(print(x, max = 4)) # no footer if length >= max expect_snapshot(print(x, max = 5)) expect_snapshot(print(x, max = 6)) }) test_that("`max` defaults to `getOption('max.print')` but can be overridden", { local_options(max.print = 3) x <- as_zoned_time(as_sys_time(year_month_day(2019, 1:5, 1)), "America/New_York") expect_snapshot(x) expect_snapshot(print(x, max = 4)) expect_snapshot(print(x, max = 5)) }) # ------------------------------------------------------------------------------ # as_zoned_time() test_that("`as_zoned_time()` has good default error", { expect_snapshot(error = TRUE, { as_zoned_time(1) }) }) # ------------------------------------------------------------------------------ # as_year_month_day() test_that("can't convert zoned-time directly to calendar", { x <- as_zoned_time(as_naive_time(year_month_day(2019, 1, 1)), "America/New_York") expect_snapshot({ (expect_error(as_year_month_day(x), class = "clock_error_unsupported_conversion")) }) }) # ------------------------------------------------------------------------------ # as.character() test_that("as.character() works", { expect <- "2019-01-01T01:02:03-05:00[America/New_York]" x <- zoned_time_parse_complete(expect) expect_identical(as.character(x), expect) }) # ------------------------------------------------------------------------------ # zoned_time_parse_complete() test_that("can parse what we format with seconds precision zoned time", { zone <- "America/New_York" x <- as_zoned_time(as_naive_time(year_month_day(2019, 1, 1)), zone) expect_identical( zoned_time_parse_complete(format(x)), x ) }) test_that("can parse subsecond zoned time", { zone <- "America/New_York" x <- "2019-01-01T01:02:03.123-05:00[America/New_York]" y <- "2019-01-01T01:02:03.1234-05:00[America/New_York]" z <- "2019-01-01T01:02:03.123456789-05:00[America/New_York]" expect_identical( zoned_time_parse_complete(x, precision = "millisecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 2, 3, 123, subsecond_precision = "millisecond")), zone) ) expect_identical( zoned_time_parse_complete(y, precision = "microsecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 2, 3, 123400, subsecond_precision = "microsecond")), zone) ) expect_identical( zoned_time_parse_complete(z, precision = "nanosecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 2, 3, 123456789, subsecond_precision = "nanosecond")), zone) ) }) test_that("multiple formats can be used", { zone <- "America/New_York" x <- c( "1970-10-25 05:30:00-05:00[America/New_York]", "1970/10/25 05:30:00-05:00[America/New_York]" ) formats <- c( "%Y-%m-%d %H:%M:%S%Ez[%Z]", "%Y/%m/%d %H:%M:%S%Ez[%Z]" ) expect_identical( zoned_time_parse_complete(x, format = formats), as_zoned_time( as_naive_time(year_month_day(1970, 10, 25, 05, 30, c(00, 00))), zone ) ) }) test_that("cannot parse nonexistent time", { zone <- "America/New_York" x <- "1970-04-26T02:30:00-05:00[America/New_York]" expect_warning( expect_identical( zoned_time_parse_complete(x), as_zoned_time(naive_seconds(NA), zone) ) ) expect_snapshot(zoned_time_parse_complete(x)) }) test_that("ambiguous times are resolved by the offset", { zone <- "America/New_York" x <- c( "1970-10-25T01:30:00-04:00[America/New_York]", "1970-10-25T01:30:00-05:00[America/New_York]" ) expect_identical( zoned_time_parse_complete(x), as_zoned_time( as_naive_time(year_month_day(1970, 10, 25, 01, 30, c(00, 00))), zone, ambiguous = c("earliest", "latest") ) ) }) test_that("offset must align with unique offset", { zone <- "America/New_York" # Should be `-05:00` x <- "2019-01-01T01:02:03-03:00[America/New_York]" expect_warning( expect_identical( zoned_time_parse_complete(x), as_zoned_time(naive_seconds(NA), zone) ) ) expect_snapshot(zoned_time_parse_complete(x)) }) test_that("offset must align with one of two possible ambiguous offsets", { zone <- "America/New_York" # Should be `-04:00` or `-05:00` x <- c( "1970-10-25T01:30:00-03:00[America/New_York]", "1970-10-25T01:30:00-06:00[America/New_York]" ) expect_warning( expect_identical( zoned_time_parse_complete(x), as_zoned_time(naive_seconds(c(NA, NA)), zone) ) ) expect_snapshot(zoned_time_parse_complete(x)) }) test_that("cannot have differing zone names", { x <- c( "2019-01-01T01:02:03-05:00[America/New_York]", "2019-01-01T01:02:03-08:00[America/Los_Angeles]" ) expect_snapshot(error = TRUE, zoned_time_parse_complete(x)) }) test_that("zone name must be valid", { x <- "2019-01-01T01:02:03-05:00[America/New_Yor]" expect_snapshot(error = TRUE, zoned_time_parse_complete(x)) }) test_that("empty input uses UTC time zone (#162)", { expect_identical( zoned_time_parse_complete(character()), as_zoned_time(naive_seconds(), "UTC") ) expect_identical( zoned_time_parse_complete(character(), precision = "nanosecond"), as_zoned_time(as_naive_time(duration_nanoseconds()), "UTC") ) }) test_that("all `NA`s uses UTC time zone (#162)", { expect_identical( zoned_time_parse_complete(c(NA_character_, NA_character_)), as_zoned_time(naive_seconds(c(NA, NA)), "UTC") ) }) test_that("all failures uses UTC time zone (#162)", { expect_warning( expect_identical( zoned_time_parse_complete(c("foo", "bar")), as_zoned_time(naive_seconds(c(NA, NA)), "UTC") ) ) }) test_that("`x` is translated to UTF-8", { x <- "2019-f\u00E9vrier-01 01:02:03-05:00[America/New_York]" x <- iconv(x, from = "UTF-8", to = "latin1") locale <- clock_locale("fr") format <- "%Y-%B-%d %H:%M:%S%Ez[%Z]" expect_identical(Encoding(x), "latin1") expect_identical(Encoding(locale$labels$month[2]), "UTF-8") expect_identical( zoned_time_parse_complete(x, format = format, locale = locale), as_zoned_time(as_naive_time(year_month_day(2019, 2, 1, 1, 2, 3)), "America/New_York") ) }) test_that("leftover subseconds result in a parse failure", { x <- "2019-01-01T01:01:01.1238-05:00[America/New_York]" # This is fine expect_identical( zoned_time_parse_complete(x, precision = "microsecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 1, 1, 123800, subsecond_precision = "microsecond")), "America/New_York") ) # This defaults to `%6S`, which parses `01.123` then stops, # leaving a `8` for `%z` to parse, resulting in a failure. Because everything # fails, we get a UTC time zone. expect_warning( expect_identical( zoned_time_parse_complete(x, precision = "millisecond"), as_zoned_time(naive_seconds(NA) + duration_milliseconds(NA), zone = "UTC") ), class = "clock_warning_parse_failures" ) }) test_that("parsing rounds parsed subsecond components more precise than the resulting container (#207) (#230) (undocumented)", { x <- "2019-01-01 01:01:01.1238-05:00[America/New_York]" # Requesting `%7S` parses the full `01.1238`, and the `1238` portion is rounded up expect_identical( zoned_time_parse_complete(x, precision = "millisecond", format = "%Y-%m-%d %H:%M:%7S%Ez[%Z]"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 1, 1, 124, subsecond_precision = "millisecond")), "America/New_York") ) }) test_that("parsing fails when undocumented rounding behavior would result in invalid 60 second component (#230) (undocumented)", { x <- "2019-01-01 01:01:59.550-05:00[America/New_York]" # Requesting `%6S` parses the full `59.550`, which is immediately rounded to `60` which looks invalid. # The correct way to do this is to parse the milliseconds, then round. expect_warning( expect_identical( zoned_time_parse_complete(x, precision = "second", format = "%Y-%m-%d %H:%M:%6S%Ez[%Z]"), as_zoned_time(as_naive_time(year_month_day(NA, NA, NA, NA, NA, NA)), zone = "UTC") ), class = "clock_warning_parse_failures" ) }) # ------------------------------------------------------------------------------ # zoned_time_parse_abbrev() test_that("can parse with abbreviation and zone name", { expect_identical( zoned_time_parse_abbrev("2019-01-01 01:02:03 EST", "America/New_York"), zoned_time_parse_complete("2019-01-01T01:02:03-05:00[America/New_York]") ) }) test_that("can parse when abbreviation is an offset", { expect_identical( zoned_time_parse_abbrev("2019-01-01 01:02:03 +11", "Australia/Lord_Howe"), zoned_time_parse_complete("2019-01-01T01:02:03+11:00[Australia/Lord_Howe]") ) expect_identical( zoned_time_parse_abbrev("2019-10-01 01:02:03 +1030", "Australia/Lord_Howe"), zoned_time_parse_complete("2019-10-01T01:02:03+10:30[Australia/Lord_Howe]") ) }) test_that("can parse at more precise precisions", { expect_identical( zoned_time_parse_abbrev("2019-01-01 01:02:03.123 EST", "America/New_York", precision = "millisecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 2, 3, 123, subsecond_precision = "millisecond")), "America/New_York") ) expect_identical( zoned_time_parse_abbrev("2019-01-01 01:02:03.123456 EST", "America/New_York", precision = "nanosecond"), as_zoned_time(as_naive_time(year_month_day(2019, 1, 1, 1, 2, 3, 123456000, subsecond_precision = "nanosecond")), "America/New_York") ) }) test_that("abbreviation is used to resolve ambiguity", { x <- c( "1970-10-25 01:30:00 EDT", "1970-10-25 01:30:00 EST" ) expect <- c( "1970-10-25T01:30:00-04:00[America/New_York]", "1970-10-25T01:30:00-05:00[America/New_York]" ) expect_identical( zoned_time_parse_abbrev(x, "America/New_York"), zoned_time_parse_complete(expect) ) }) test_that("nonexistent times are NAs", { expect_warning( expect_identical( zoned_time_parse_abbrev("1970-04-26 02:30:00 EST", "America/New_York"), as_zoned_time(sys_seconds(NA), "America/New_York") ) ) }) test_that("abbreviation must match the one implied from naive + time zone name lookup", { x <- "1970-01-01 00:00:00 FOOBAR" expect_warning( expect_identical( zoned_time_parse_abbrev(x, "America/New_York"), as_zoned_time(sys_days(NA), "America/New_York") ) ) # Should be EST x <- "1970-01-01 00:00:00 EDT" expect_warning( expect_identical( zoned_time_parse_abbrev(x, "America/New_York"), as_zoned_time(sys_days(NA), "America/New_York") ) ) expect_snapshot(zoned_time_parse_abbrev(x, "America/New_York")) }) test_that("%Z must be used", { x <- "1970-01-01" expect_snapshot(error = TRUE, zoned_time_parse_abbrev(x, "America/New_York", format = "%Y-%m-%d") ) }) test_that("%z can be parsed (but is ignored really)", { expect <- zoned_time_parse_complete("1970-01-01T00:00:00-05:00[America/New_York]") x <- "1970-01-01 00:00:00-05:00 EST" expect_identical( zoned_time_parse_abbrev(x, "America/New_York", format = "%Y-%m-%d %H:%M:%S%Ez %Z"), expect ) }) test_that("%z that is incorrect technically slips through unnoticed", { expect <- zoned_time_parse_complete("1970-01-01T00:00:00-05:00[America/New_York]") x <- "1970-01-01 00:00:00-02:00 EST" expect_identical( zoned_time_parse_abbrev(x, "America/New_York", format = "%Y-%m-%d %H:%M:%S%Ez %Z"), expect ) }) test_that("%z must parse correctly if included", { expect <- as_zoned_time(sys_days(NA), "America/New_York") x <- "1970-01-01 00:00:00-0a:00 EST" expect_warning( result <- zoned_time_parse_abbrev(x, "America/New_York", format = "%Y-%m-%d %H:%M:%S%Ez %Z") ) expect_identical(result, expect) }) test_that("multiple formats can be attempted", { x <- c("1970-01-01 EST", "1970-01-01 05:06:07 EST") formats <- c("%Y-%m-%d %H:%M:%S %Z", "%Y-%m-%d %Z") expect <- as_zoned_time( as_naive_time(year_month_day(1970, 1, 1, c(0, 5), c(0, 6), c(0, 7))), "America/New_York" ) expect_identical( zoned_time_parse_abbrev(x, "America/New_York", format = formats), expect ) }) test_that("NA parses correctly", { expect_identical( zoned_time_parse_abbrev(NA_character_, "America/New_York"), as_zoned_time(sys_seconds(NA), "America/New_York") ) expect_identical( zoned_time_parse_abbrev(NA_character_, "America/New_York", precision = "nanosecond"), as_zoned_time(as_sys_time(duration_nanoseconds(NA)), "America/New_York") ) }) test_that("`x` is translated to UTF-8", { x <- "2019-f\u00E9vrier-01 01:02:03-05:00[EST]" x <- iconv(x, from = "UTF-8", to = "latin1") locale <- clock_locale("fr") format <- "%Y-%B-%d %H:%M:%S%Ez[%Z]" expect_identical(Encoding(x), "latin1") expect_identical(Encoding(locale$labels$month[2]), "UTF-8") expect_identical( zoned_time_parse_abbrev(x, "America/New_York", format = format, locale = locale), as_zoned_time(as_naive_time(year_month_day(2019, 2, 1, 1, 2, 3)), "America/New_York") ) }) # ------------------------------------------------------------------------------ # zoned_time_info() test_that("can get info of a zoned time (#295)", { zone <- "America/New_York" x <- as_zoned_time(as_naive_time(year_month_day(2019, 1, 1)), zone) x <- zoned_time_info(x) begin <- as_zoned_time(as_naive_time(year_month_day(2018, 11, 4, 1)), zone, ambiguous = "latest") end <- as_zoned_time(as_naive_time(year_month_day(2019, 03, 10, 3)), zone) expect_identical(x$begin, begin) expect_identical(x$end, end) expect_identical(x$offset, duration_seconds(-18000)) expect_identical(x$dst, FALSE) expect_identical(x$abbreviation, "EST") }) test_that("`NA` propagates", { x <- as_zoned_time(as_naive_time(year_month_day(NA, NA, NA)), "UTC") info <- zoned_time_info(x) expect_identical(info$begin, x) expect_identical(info$end, x) expect_identical(info$offset, duration_seconds(NA)) expect_identical(info$dst, NA) expect_identical(info$abbreviation, NA_character_) }) test_that("boundaries are handled right", { x <- as_zoned_time(as_naive_time(year_month_day(2019, 1, 1)), "UTC") x <- zoned_time_info(x) # Only snapshotting in case boundaries are different on CRAN expect_snapshot(x$begin) expect_snapshot(x$end) expect_identical(x$offset, duration_seconds(0)) expect_identical(x$dst, FALSE) expect_identical(x$abbreviation, "UTC") }) test_that("input must be a zoned-time", { expect_snapshot(error = TRUE, { zoned_time_info(1) }) }) # ------------------------------------------------------------------------------ # add_*() test_that("zoned-times don't support arithmetic", { x <- as_zoned_time(as_naive_time(year_month_day(2019, 1, 1)), "America/New_York") expect_snapshot(error = TRUE, add_years(x, 1)) expect_snapshot(error = TRUE, add_quarters(x, 1)) expect_snapshot(error = TRUE, add_months(x, 1)) expect_snapshot(error = TRUE, add_weeks(x, 1)) expect_snapshot(error = TRUE, add_days(x, 1)) expect_snapshot(error = TRUE, add_hours(x, 1)) expect_snapshot(error = TRUE, add_minutes(x, 1)) expect_snapshot(error = TRUE, add_seconds(x, 1)) expect_snapshot(error = TRUE, add_milliseconds(x, 1)) expect_snapshot(error = TRUE, add_microseconds(x, 1)) expect_snapshot(error = TRUE, add_nanoseconds(x, 1)) }) # ------------------------------------------------------------------------------ # vec_ptype() test_that("ptype is correct", { zones <- c("UTC", "America/New_York", "") for (zone in zones) { for (precision in precision_names()) { precision <- precision_to_integer(precision) if (precision < PRECISION_SECOND) { next } x <- duration_helper(0L, precision) x <- as_zoned_time(as_naive_time(x), zone) ptype <- duration_helper(integer(), precision) ptype <- as_zoned_time(as_naive_time(ptype), zone) expect_identical(vec_ptype(x), ptype) } } }) # ------------------------------------------------------------------------------ # vec_math() test_that("is.nan() works", { zone <- "America/New_York" x <- as_zoned_time(naive_days(c(2019, NA)), zone) expect_identical(is.nan(x), c(FALSE, FALSE)) }) test_that("is.finite() works", { zone <- "America/New_York" x <- as_zoned_time(naive_days(c(2019, NA)), zone) expect_identical(is.finite(x), c(TRUE, FALSE)) }) test_that("is.infinite() works", { zone <- "America/New_York" x <- as_zoned_time(naive_days(c(2019, NA)), zone) expect_identical(is.infinite(x), c(FALSE, FALSE)) }) # ------------------------------------------------------------------------------ # zoned_time_zone() test_that("can get the time zone of a zoned-time", { zone <- "America/New_York" x <- as_zoned_time(naive_days(0), zone) expect_identical(zoned_time_zone(x), zone) }) test_that("`zoned_time_zone()` validates `x`", { expect_snapshot(error = TRUE, { zoned_time_zone(1) }) }) # ------------------------------------------------------------------------------ # zoned_time_set_zone() test_that("can set the time zone of a zoned-time", { zone1 <- "America/New_York" zone2 <- "America/Los_Angeles" sys <- sys_days(0) x <- as_zoned_time(sys, zone1) y <- as_zoned_time(sys, zone2) expect_identical(zoned_time_set_zone(x, zone2), y) }) test_that("`zoned_time_set_zone()` validates `x`", { expect_snapshot(error = TRUE, { zoned_time_set_zone(1, "UTC") }) }) # ------------------------------------------------------------------------------ # zoned_time_precision() test_that("precision: can get the precision", { zone <- "America/New_York" expect_identical(zoned_time_precision(as_zoned_time(as_naive_time(duration_seconds(2:5)), zone)), "second") expect_identical(zoned_time_precision(as_zoned_time(as_naive_time(duration_nanoseconds(2:5)), zone)), "nanosecond") }) test_that("precision: can only be called on zoned-times", { expect_snapshot(error = TRUE, zoned_time_precision(duration_days())) })