diff --git a/NEWS.md b/NEWS.md index 21c97925..685aa781 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # scales (development version) - +* `fullseq()` and by extension `breaks_width()` can now deal with unsorted + ranges (#435). * New `label_date_short(leading)` argument to replace leading zeroes (#442) * `breaks_pretty()` will return the input limit when it has no range (#446) * `transform_exp()` now has more sensible breaks, available in `breaks_exp()` diff --git a/R/full-seq.R b/R/full-seq.R index 5d8c6bc1..1262737c 100644 --- a/R/full-seq.R +++ b/R/full-seq.R @@ -9,6 +9,7 @@ fullseq <- function(range, size, ...) UseMethod("fullseq") #' @export fullseq.numeric <- function(range, size, ..., pad = FALSE) { + range <- sort(range) if (zero_range(range)) { return(range + size * c(-1, 1) / 2) } @@ -30,6 +31,7 @@ fullseq.numeric <- function(range, size, ..., pad = FALSE) { #' @export fullseq.Date <- function(range, size, ...) { + range <- sort(range) seq(floor_date(range[1], size), ceiling_date(range[2], size), by = size) } #' @export @@ -37,6 +39,7 @@ fullseq.POSIXt <- function(range, size, ...) { # for subsecond interval support # seq() does not support partial secs in character strings + range <- sort(range) parsed <- parse_unit_spec(size) if (parsed$unit == "sec") { seq(floor_time(range[1], size), ceiling_time(range[2], size), by = parsed$mult) @@ -53,6 +56,7 @@ fullseq.difftime <- function(range, size, ...) { } input_units <- units(range) + range <- sort(range) x <- seq( round_any(as.numeric(range[1], units = "secs"), size_seconds, floor), diff --git a/tests/testthat/test-full-seq.R b/tests/testthat/test-full-seq.R index e22329bd..9460c845 100644 --- a/tests/testthat/test-full-seq.R +++ b/tests/testthat/test-full-seq.R @@ -1,15 +1,17 @@ test_that("works with numeric", { x <- c(0, 100) - expect_equal(fullseq(x, 50), c(0, 50, 100)) + expected <- c(0, 50, 100) + expect_equal(fullseq(x, 50), expected) + expect_equal(fullseq(rev(x), 50), expected) }) test_that("works with POSIXct", { x <- as.POSIXct(c("2000-01-01 08:29:58", "2000-01-01 08:30:10"), tz = "UTC") - expect_equal( - fullseq(x, "1 hour"), - as.POSIXct(c("2000-01-01 8:00:00 UTC", "2000-01-01 9:00:00 UTC"), tz = "UTC") - ) + expected <- as.POSIXct(c("2000-01-01 8:00:00 UTC", "2000-01-01 9:00:00 UTC"), tz = "UTC") + expect_equal(fullseq(x, "1 hour"), expected) + expect_equal(fullseq(rev(x), "1 hour"), expected) + expect_equal( fullseq(x, ".5 secs")[1:2], as.POSIXct(c("2000-01-01 08:29:58.0 UTC", "2000-01-01 08:29:58.5 UTC"), tz = "UTC") @@ -17,8 +19,10 @@ test_that("works with POSIXct", { }) test_that("works with Date", { - x <- as.Date("2012-01-01") + 1:30 - expect_equal(fullseq(x, "1 month"), as.Date(c("2012-01-01", "2012-02-01"))) + x <- as.Date("2012-01-01") + c(1, 30) + expected <- as.Date(c("2012-01-01", "2012-02-01", "2012-03-01")) + expect_equal(fullseq(x, "1 month"), expected) + expect_equal(fullseq(rev(x), "1 month"), expected) }) test_that("works with hms/difftime", { @@ -26,6 +30,7 @@ test_that("works with hms/difftime", { y <- as.difftime(c(0, 1800, 3600), units = "secs") expect_equal(fullseq(x, 1800), y) expect_equal(fullseq(x, "30 mins"), y) + expect_equal(fullseq(rev(x), "30 mins"), y) # Preserves units x <- as.difftime(c(0, 1), units = "hours")