From 11d1c9aeefeaa568edcefda09bc477116ffd300e Mon Sep 17 00:00:00 2001 From: Vitalie Spinu Date: Sun, 16 Jul 2023 11:17:37 +0200 Subject: [PATCH] [#682] Add type="year_start/end" argument to quarter function --- NEWS.md | 4 ++++ R/accessors-quarter.r | 28 ++++++++++++++++++---------- man/quarter.Rd | 20 +++++++++++--------- tests/testthat/test-accessors.R | 19 +++++++++++++++++-- 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/NEWS.md b/NEWS.md index ff13df9a..40394adf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,10 @@ Version 1.9.2.9000 ================== +### NEW FEATURES + +* [#682](https://github.com/tidyverse/lubridate/issues/682#issuecomment-1635910435) Add type="year_start/end" argument to `quarter()` which produces a complete description of the quarter. + ### BUG FIXES * [#1109](https://github.com/tidyverse/lubridate/issues/1109) Fix recycling of the year slot in `as.period(unit = "month")` with Periods and Intervals. diff --git a/R/accessors-quarter.r b/R/accessors-quarter.r index de419e70..6ab8ade8 100644 --- a/R/accessors-quarter.r +++ b/R/accessors-quarter.r @@ -5,18 +5,20 @@ NULL #' #' Quarters divide the year into fourths. Semesters divide the year into halfs. #' -#' @param x a date-time object of class POSIXct, POSIXlt, Date, chron, yearmon, -#' yearqtr, zoo, zooreg, timeDate, xts, its, ti, jul, timeSeries, fts or -#' anything else that can be converted with as.POSIXlt -#' @param type the format to be returned for the quarter. Can be one one of -#' "quarter" - return numeric quarter (default), "year.quarter" return -#' fractional numeric year.quarter, "date_first" or "date_last" which return -#' the date at the quarter's start and end. +#' @param x a date-time object of class POSIXct, POSIXlt, Date, chron, yearmon, yearqtr, +#' zoo, zooreg, timeDate, xts, its, ti, jul, timeSeries, fts or anything else that can +#' be converted with as.POSIXlt +#' @param type the format to be returned for the quarter. Can be one one of "quarter" - +#' return numeric quarter (default), "year.quarter" - return fractional numeric +#' year.quarter, "date_first" or "date_last" - return the date at the quarter's start +#' or end, "year_start/end" - return a full description of the quarter as a string +#' which includes the start and end of the year (ex. "2020/21 Q1"). #' @param fiscal_start numeric indicating the starting month of a fiscal year. #' @param with_year logical indicating whether or not to include the quarter or #' semester's year (deprecated; use the `type` parameter instead). -#' @return numeric or a vector of class POSIXct if `type` argument is -#' `date_first` or `date_last` +#' @return numeric or a vector of class POSIXct if `type` argument is `date_first` or +#' `date_last`. When `type` is `year.quarter` the year returned is the end year of the +#' financial year. #' @examples #' x <- ymd(c("2012-03-26", "2012-05-04", "2012-09-23", "2012-12-31")) #' quarter(x) @@ -49,9 +51,15 @@ quarter <- function(x, type = "quarter", fiscal_start = 1, with_year = identical switch(type, "quarter" = q, + "year_start/end" = , "year.quarter" = { nxt_year_months <- if (fs != 0) (fs + 1):12 - year(x) + (m %in% nxt_year_months) + (q / 10) + y = year(x) + (m %in% nxt_year_months) + out = y + (q / 10) + if (type == "year_start/end") { + out = sprintf("%d/%d Q%d", y - 1, y %% 100, q) + } + out }, "date_first" = , "date_last" = { diff --git a/man/quarter.Rd b/man/quarter.Rd index 2e835af7..78ea2a89 100644 --- a/man/quarter.Rd +++ b/man/quarter.Rd @@ -15,14 +15,15 @@ quarter( semester(x, with_year = FALSE) } \arguments{ -\item{x}{a date-time object of class POSIXct, POSIXlt, Date, chron, yearmon, -yearqtr, zoo, zooreg, timeDate, xts, its, ti, jul, timeSeries, fts or -anything else that can be converted with as.POSIXlt} +\item{x}{a date-time object of class POSIXct, POSIXlt, Date, chron, yearmon, yearqtr, +zoo, zooreg, timeDate, xts, its, ti, jul, timeSeries, fts or anything else that can +be converted with as.POSIXlt} -\item{type}{the format to be returned for the quarter. Can be one one of -"quarter" - return numeric quarter (default), "year.quarter" return -fractional numeric year.quarter, "date_first" or "date_last" which return -the date at the quarter's start and end.} +\item{type}{the format to be returned for the quarter. Can be one one of "quarter" - +return numeric quarter (default), "year.quarter" - return fractional numeric +year.quarter, "date_first" or "date_last" - return the date at the quarter's start +or end, "year_start/end" - return a full description of the quarter as a string +which includes the start and end of the year (ex. "2020/21 Q1").} \item{fiscal_start}{numeric indicating the starting month of a fiscal year.} @@ -30,8 +31,9 @@ the date at the quarter's start and end.} semester's year (deprecated; use the \code{type} parameter instead).} } \value{ -numeric or a vector of class POSIXct if \code{type} argument is -\code{date_first} or \code{date_last} +numeric or a vector of class POSIXct if \code{type} argument is \code{date_first} or +\code{date_last}. When \code{type} is \code{year.quarter} the year returned is the end year of the +financial year. } \description{ Quarters divide the year into fourths. Semesters divide the year into halfs. diff --git a/tests/testthat/test-accessors.R b/tests/testthat/test-accessors.R index 7df71337..fb37f97a 100644 --- a/tests/testthat/test-accessors.R +++ b/tests/testthat/test-accessors.R @@ -253,6 +253,7 @@ test_that("quarters accessor extracts correct quarter", { expect_equal(quarter(posct, type = "year.quarter"), 2010.4) expect_equal(quarter(posct, type = "date_first"), ymd("2010-10-01")) expect_equal(quarter(posct, type = "date_last"), ymd("2010-12-31")) + expect_equal(quarter(posct, type = "year_start/end"), "2009/10 Q4") expect_equal(quarter(posct, with_year = TRUE), 2010.4) expect_equal(quarter(posct, fiscal_start = 11), 1) expect_equal(quarter(posct, fiscal_start = -2), 1) @@ -266,6 +267,7 @@ test_that("quarters accessor extracts correct quarter", { expect_equal(quarter(poslt, type = "year.quarter"), 2010.4) expect_equal(quarter(poslt, type = "date_first"), ymd("2010-10-01")) expect_equal(quarter(poslt, type = "date_last"), ymd("2010-12-31")) + expect_equal(quarter(poslt, type = "year_start/end"), "2009/10 Q4") expect_equal(quarter(poslt, with_year = TRUE), 2010.4) expect_equal(quarter(poslt, fiscal_start = 11), 1) expect_equal(quarter(poslt, fiscal_start = -2), 1) @@ -279,6 +281,7 @@ test_that("quarters accessor extracts correct quarter", { expect_equal(quarter(date, type = "year.quarter"), 2010.4) expect_equal(quarter(date, type = "date_first"), ymd("2010-10-01")) expect_equal(quarter(date, type = "date_last"), ymd("2010-12-31")) + expect_equal(quarter(date, type = "year_start/end"), "2009/10 Q4") expect_equal(quarter(date, with_year = TRUE), 2010.4) expect_equal(quarter(date, fiscal_start = 11), 1) expect_equal(quarter(date, fiscal_start = -2), 1) @@ -306,8 +309,20 @@ test_that("quarters accessor extracts correct quarter", { c(2012.2, 2012.2, 2012.3, 2012.4, 2013.1) ) expect_equal( - quarter(x, type = "date_first", fiscal_start = 4), - ymd(c("2012-01-01", "2012-01-01", "2012-04-01", "2012-07-01", "2012-10-01")) + quarter(x, type = "year.quarter", fiscal_start = 11), + c(2012.2, 2012.2, 2012.3, 2012.4, 2013.1) + ) + expect_equal( + quarter(x, type = "year_start/end", fiscal_start = 11), + c("2011/12 Q2", "2011/12 Q2", "2011/12 Q3", "2011/12 Q4", "2012/13 Q1") + ) + expect_equal( + quarter(x, type = "year.quarter", fiscal_start = 4), + c(2012.4, 2012.4, 2013.1, 2013.2, 2013.3) + ) + expect_equal( + quarter(x, type = "year_start/end", fiscal_start = 4), + c("2011/12 Q4", "2011/12 Q4", "2012/13 Q1", "2012/13 Q2", "2012/13 Q3") ) expect_equal( quarter(x, type = "date_first", fiscal_start = 11),