From 28a9496957a00be6055b292465ab94bbecbf928a Mon Sep 17 00:00:00 2001 From: Doug Kelkhoff <18220321+dgkf@users.noreply.github.com> Date: Thu, 21 Jul 2022 09:48:11 -0700 Subject: [PATCH] documenting parse_iso8601_as_timespan (#29) --- DESCRIPTION | 2 +- R/class_partial_time_compat_lubridate.R | 14 +++---- R/parse_iso8601.R | 55 ++++++++++++++++++++++++- README.Rmd | 4 +- README.md | 14 +++++-- man/parse_iso8601_helpers.Rd | 53 ++++++++++++++++++++++++ man/parse_timespan.Rd | 24 +++++++++++ man/parttime_access_and_assign.Rd | 14 +++---- pkgdown/_pkgdown.yml | 27 +++++++----- 9 files changed, 173 insertions(+), 34 deletions(-) create mode 100644 man/parse_iso8601_helpers.Rd create mode 100644 man/parse_timespan.Rd diff --git a/DESCRIPTION b/DESCRIPTION index cbfac4f..b0ae4b0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,4 +33,4 @@ Suggests: rmarkdown VignetteBuilder: knitr Roxygen: list(markdown = TRUE) -URL: https://dgkf.github.io/parttime +URL: https://dgkf.github.io/parttime/, https://github.com/dgkf/parttime diff --git a/R/class_partial_time_compat_lubridate.R b/R/class_partial_time_compat_lubridate.R index be752b3..8172088 100644 --- a/R/class_partial_time_compat_lubridate.R +++ b/R/class_partial_time_compat_lubridate.R @@ -136,7 +136,7 @@ tz <- function(x) UseMethod("tz") year.partial_time <- gen_get_field_fn("year") #' @rdname parttime_access_and_assign -#' @usage \\method{year}{partial_time}(x) <- value +#' @usage \method{year}{partial_time}(x) <- value #' @export `year<-.partial_time` <- gen_set_field_fn("year") @@ -157,7 +157,7 @@ methods::setMethod( month.partial_time <- gen_get_field_fn("month") #' @rdname parttime_access_and_assign -#' @usage \\method{month}{partial_time}(x) <- value +#' @usage \method{month}{partial_time}(x) <- value #' @export `month<-.partial_time` <- gen_set_field_fn("month") @@ -178,7 +178,7 @@ methods::setMethod( mday.partial_time <- gen_get_field_fn("day") #' @rdname parttime_access_and_assign -#' @usage \\method{day}{partial_time}(x) <- value +#' @usage \method{day}{partial_time}(x) <- value #' @export `day<-.partial_time` <- gen_set_field_fn("day") @@ -199,7 +199,7 @@ methods::setMethod( hour.partial_time <- gen_get_field_fn("hour") #' @rdname parttime_access_and_assign -#' @usage \\method{hour}{partial_time}(x) <- value +#' @usage \method{hour}{partial_time}(x) <- value #' @export `hour<-.partial_time` <- gen_set_field_fn("hour") @@ -220,7 +220,7 @@ methods::setMethod( minute.partial_time <- gen_get_field_fn("min") #' @rdname parttime_access_and_assign -#' @usage \\method{minute}{partial_time}(x) <- value +#' @usage \method{minute}{partial_time}(x) <- value #' @export `minute<-.partial_time` <- gen_set_field_fn("min") @@ -243,7 +243,7 @@ second.partial_time <- function(x) { } #' @rdname parttime_access_and_assign -#' @usage \\method{second}{partial_time}(x) <- value +#' @usage \method{second}{partial_time}(x) <- value #' @export `second<-.partial_time` <- function(x, value) { sec <- trunc(value) @@ -272,7 +272,7 @@ tz.partial_time <- function(x) { } #' @rdname parttime_access_and_assign -#' @usage \\method{tz}{partial_time}(x) <- value +#' @usage \method{tz}{partial_time}(x) <- value #' @export `tz<-.partial_time` <- function(x, value) { set_field(x, c("tzhour", "tzmin"), cbind(tzhour = value %/% 60, tzmin = value %% 60)) diff --git a/R/parse_iso8601.R b/R/parse_iso8601.R index de94696..6743fd1 100644 --- a/R/parse_iso8601.R +++ b/R/parse_iso8601.R @@ -1,6 +1,7 @@ #' slightly modified from parsedate - added 'secfrac' capture group #' #' @keywords internal +#' re_iso8601 <- paste0( "^\\s*", "(?[\\+-]?\\d{4}(?!\\d{2}\\b))", @@ -74,6 +75,16 @@ parse_iso8601 <- function(x, warn = TRUE, ...) { } + +#' Parse iso8601 datetime strings as timespan array +#' +#' @note A timespan array is an internal data structure used as the backend +#' representation of timespan objects. It consists of two parttime-like matrices +#' (with the addition of an "inclusive" column), one for the lower- and +#' upper-bounds of the timespan. Collectively, this amounts to a three +#' dimensional array. +#' +#' @inheritParams parse_iso8601 #' #' @keywords internal #' @rdname parse_timespan @@ -144,40 +155,80 @@ parse_iso8601_matrix <- function(dates) { match_m } + + +#' Inspecting and manipulating intermediate iso8601 matrices +#' +#' An "iso8601 matrix" is a matrix of the various capture groups extraced from a +#' an iso8601 datetime string. These groups represent a superset of the fields +#' used by partial time objects, including representation for less common +#' datetime formats like yeardays, yearweeks or weekdays. Because the standard +#' provides a number of different combinations of fields that represent valid +#' strings, these functions serves to provide convenience functions for testing +#' or manipulating these less canonical representations. +#' +#' @param x A \code{numeric} matrix of possible iso8601 fields +#' @param fields A \code{character} vector of fields +#' +#' @section is_iso8601_* functions: +#' Test whether rows of the matrix represent a specific form, as evident by +#' non-missing values in specific fields. +#' +#' @keywords internal +#' +#' @name parse_iso8601_helpers +#' @rdname parse_iso8601_helpers +#' is_iso8601_form <- function(x, fields) { apply(!is.na(x[, fields, drop = FALSE]), 1, all) } +#' @keywords internal +#' @rdname parse_iso8601_helpers is_iso8601_weekday <- function(x) { is_iso8601_form(x, c("year", "week", "weekday")) } +#' @keywords internal +#' @rdname parse_iso8601_helpers is_iso8601_yearday <- function(x) { is_iso8601_form(x, c("year", "yearday")) } +#' @keywords internal +#' @rdname parse_iso8601_helpers is_iso8601_minfrac <- function(x) { is_iso8601_form(x, "frac") } +#' @section recalc_* functions: +#' Calculate canonical datetime fields from alternative representations +#' +#' @keywords internal +#' @rdname parse_iso8601_helpers +#' recalc_md_from_weekday <- function(x) { dates <- strptime( - paste(x[,"year"], x[,"week"], x[,"weekday"] - 1L, sep = "-"), + paste(x[, "year"], x[, "week"], x[, "weekday"] - 1L, sep = "-"), format = "%Y-%U-%w" ) cbind(month = dates$mon + 1L, day = dates$mday) } +#' @keywords internal +#' @rdname parse_iso8601_helpers recalc_md_from_yearday <- function(x) { dates <- strptime( - paste(x[,"year"], x[,"yearday"], sep = "-"), + paste(x[, "year"], x[, "yearday"], sep = "-"), format = "%Y-%j" ) cbind(month = dates$mon + 1L, day = dates$mday) } +#' @keywords internal +#' @rdname parse_iso8601_helpers recalc_sec_from_minfrac <- function(x) { cbind(sec = (x[, "frac"] * 60) %/% 1, secfrac = (x[, "frac"] * 60) %% 1) } diff --git a/README.Rmd b/README.Rmd index 48f3c0e..e41eb34 100644 --- a/README.Rmd +++ b/README.Rmd @@ -12,9 +12,9 @@ knitr::opts_chunk$set(collapse = TRUE) # parttime -[![status](https://img.shields.io/static/v1?label=status&message=experimental&color=red)]() +[![status](https://img.shields.io/static/v1?label=status&message=developing&color=orange)]() [![R-CMD-check](https://github.com/dgkf/parttime/workflows/R-CMD-check/badge.svg)](https://github.com/dgkf/parttime/actions) -[![Coverage](https://codecov.io/gh/dgkf/parttime/branch/master/graph/badge.svg)](https://app.codecov.io/gh/dgkf/parttime?branch=master) +[![Coverage](https://codecov.io/gh/dgkf/parttime/branch/main/graph/badge.svg)](https://app.codecov.io/gh/dgkf/parttime?branch=main) A package for a partial datetime class and generics diff --git a/README.md b/README.md index b71ca82..5b08ebf 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ -[![status](https://img.shields.io/static/v1?label=status&message=experimental&color=red)]() +[![status](https://img.shields.io/static/v1?label=status&message=developing&color=orange)]() [![R-CMD-check](https://github.com/dgkf/parttime/workflows/R-CMD-check/badge.svg)](https://github.com/dgkf/parttime/actions) -[![Coverage](https://codecov.io/gh/dgkf/parttime/branch/master/graph/badge.svg)](https://app.codecov.io/gh/dgkf/parttime?branch=master) +[![Coverage](https://codecov.io/gh/dgkf/parttime/branch/main/graph/badge.svg)](https://app.codecov.io/gh/dgkf/parttime?branch=main) A package for a partial datetime class and generics @@ -163,10 +163,13 @@ iso8601_dates <- c( ) as.parttime(iso8601_dates) +## Warning in warn_repr_data_loss(x, includes = "week", excludes = "weekday"): Date strings including week and excluding weekday can not be fully +## represented. To avoid loss of datetime resolution, such partial dates +## are best represented as timespans. See `?timespan`. ## [15]> ## [1] NA "2001" ## [3] "2002-01-01" "2004-09-01" -## [5] "2005" "2006-01-13" +## [5] "2005" "2006-01-12" ## [7] "2007-10-01 08" "2008-09-20 08:35" ## [9] "2009-08-12 08:35:02.880" "2010-07-22 08:35:32.000" ## [11] "2011-06-13 08:35:32.123" "2012-05-23 08:35:32.123" @@ -253,6 +256,9 @@ tibble(dates = iso8601_dates) %>% parttimes = as.parttime(dates), imputed_times = impute_time_min(parttimes) ) +## Warning in warn_repr_data_loss(x, includes = "week", excludes = "weekday"): Date strings including week and excluding weekday can not be fully +## represented. To avoid loss of datetime resolution, such partial dates +## are best represented as timespans. See `?timespan`. ## # A tibble: 15 × 3 ## dates parttimes imputed_times ## @@ -261,7 +267,7 @@ tibble(dates = iso8601_dates) %>% ## 3 2002-01-01 2002-01-01 2002-01-01 00:00:00.000-1200 ## 4 2004-245 2004-09-01 2004-09-01 00:00:00.000-1200 ## 5 2005-W13 2005 2005-01-01 00:00:00.000-1200 -## 6 2006-W02-5 2006-01-13 2006-01-13 00:00:00.000-1200 +## 6 2006-W02-5 2006-01-12 2006-01-12 00:00:00.000-1200 ## 7 2007-10-01T08 2007-10-01 08 2007-10-01 08:00:00.000-1200 ## 8 2008-09-20T08:35 2008-09-20 08:35 2008-09-20 08:35:00.000-1200 ## 9 2009-08-12T08:35.0… 2009-08-12 08:35:02.880 2009-08-12 08:35:02.880-1200 diff --git a/man/parse_iso8601_helpers.Rd b/man/parse_iso8601_helpers.Rd new file mode 100644 index 0000000..113bbc5 --- /dev/null +++ b/man/parse_iso8601_helpers.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parse_iso8601.R +\name{parse_iso8601_helpers} +\alias{parse_iso8601_helpers} +\alias{is_iso8601_form} +\alias{is_iso8601_weekday} +\alias{is_iso8601_yearday} +\alias{is_iso8601_minfrac} +\alias{recalc_md_from_weekday} +\alias{recalc_md_from_yearday} +\alias{recalc_sec_from_minfrac} +\title{Inspecting and manipulating intermediate iso8601 matrices} +\usage{ +is_iso8601_form(x, fields) + +is_iso8601_weekday(x) + +is_iso8601_yearday(x) + +is_iso8601_minfrac(x) + +recalc_md_from_weekday(x) + +recalc_md_from_yearday(x) + +recalc_sec_from_minfrac(x) +} +\arguments{ +\item{x}{A \code{numeric} matrix of possible iso8601 fields} + +\item{fields}{A \code{character} vector of fields} +} +\description{ +An "iso8601 matrix" is a matrix of the various capture groups extraced from a +an iso8601 datetime string. These groups represent a superset of the fields +used by partial time objects, including representation for less common +datetime formats like yeardays, yearweeks or weekdays. Because the standard +provides a number of different combinations of fields that represent valid +strings, these functions serves to provide convenience functions for testing +or manipulating these less canonical representations. +} +\section{is_iso8601_* functions}{ + +Test whether rows of the matrix represent a specific form, as evident by +non-missing values in specific fields. +} + +\section{recalc_* functions}{ + +Calculate canonical datetime fields from alternative representations +} + +\keyword{internal} diff --git a/man/parse_timespan.Rd b/man/parse_timespan.Rd new file mode 100644 index 0000000..edc16e3 --- /dev/null +++ b/man/parse_timespan.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parse_iso8601.R +\name{parse_iso8601_as_timespan} +\alias{parse_iso8601_as_timespan} +\title{Parse iso8601 datetime strings as timespan array} +\usage{ +parse_iso8601_as_timespan(x, ...) +} +\arguments{ +\item{x}{A \code{character} vector of iso8601 datetime strings} + +\item{...}{Additional arguments unused} +} +\description{ +Parse iso8601 datetime strings as timespan array +} +\note{ +A timespan array is an internal data structure used as the backend +representation of timespan objects. It consists of two parttime-like matrices +(with the addition of an "inclusive" column), one for the lower- and +upper-bounds of the timespan. Collectively, this amounts to a three +dimensional array. +} +\keyword{internal} diff --git a/man/parttime_access_and_assign.Rd b/man/parttime_access_and_assign.Rd index 1a31209..9b4f32f 100644 --- a/man/parttime_access_and_assign.Rd +++ b/man/parttime_access_and_assign.Rd @@ -74,43 +74,43 @@ tz(x) <- value \method{year}{partial_time}(x) -\\method{year}{partial_time}(x) <- value +\method{year}{partial_time}(x) <- value \S4method{year}{partial_time}(x) <- value \method{month}{partial_time}(x) -\\method{month}{partial_time}(x) <- value +\method{month}{partial_time}(x) <- value \S4method{month}{partial_time}(x) <- value \method{mday}{partial_time}(x) -\\method{day}{partial_time}(x) <- value +\method{day}{partial_time}(x) <- value \S4method{day}{partial_time}(x) <- value \method{hour}{partial_time}(x) -\\method{hour}{partial_time}(x) <- value +\method{hour}{partial_time}(x) <- value \S4method{hour}{partial_time}(x) <- value \method{minute}{partial_time}(x) -\\method{minute}{partial_time}(x) <- value +\method{minute}{partial_time}(x) <- value \S4method{minute}{partial_time}(x) <- value \method{second}{partial_time}(x) -\\method{second}{partial_time}(x) <- value +\method{second}{partial_time}(x) <- value \S4method{second}{partial_time}(x) <- value \method{tz}{partial_time}(x) -\\method{tz}{partial_time}(x) <- value +\method{tz}{partial_time}(x) <- value } \arguments{ \item{x}{A time-like object to access or assign to} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index c1de240..4716360 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -13,14 +13,27 @@ reference: - title: Class Helpers contents: - starts_with("has_partial") - - starts_with("is.na") - starts_with("is_") -- title: Generic methods +- title: Generics +- subtitle: "base generics" contents: + - starts_with("is.na") - matches("^max\\b") - matches("^min\\b") - matches("^pmax\\b") - matches("^pmin\\b") +- subtitle: "stats-style timeseries accessors" + contents: + - start + - end +- subtitle: "lubridate-style accessors & assignment" + desc: > + `lubridate` interoperability with available generics (such as `year` and + `year<-`) + contents: + - parttime_access_and_assign + - starts_with("as.interval") + - is.timespan - title: Operators contents: - starts_with("Ops\\.") @@ -40,7 +53,7 @@ reference: - to_gmt - trim - title: Indexing and indexed assignment - desc: | + desc: > Base-R-style vector indexing and assignment as a vector, or accessors to the underlying matrix. contents: @@ -48,14 +61,6 @@ reference: - "[[.partial_time" - "[<-.partial_time" - "[[<-.partial_time" -- title: "lubridate-style accessors & assignment" - desc: | - `lubridate` interoperability with available generics (such as `year` and - `year<-`) - contents: - - parttime_access_and_assign - - starts_with("as.interval") - - is.timespan - title: "vctrs interoperability" contents: - starts_with("vec_")