Skip to content

Commit

Permalink
Require a "T" before hour-only times; require calendar months and day…
Browse files Browse the repository at this point in the history
…s not to include "00"
  • Loading branch information
billdenney committed Nov 10, 2021
1 parent df6dd93 commit 3f7a398
Show file tree
Hide file tree
Showing 2 changed files with 258 additions and 122 deletions.
54 changes: 38 additions & 16 deletions R/iso8601_regexp.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ pattern_ISO8601_calendar_datetime <- function(truncated=0, ...) {
stopifnot(truncated >= 0 & truncated <= 6)
# Min truncated is 2 because 3 will be handled below with the addition of the
# "T"
pattern_time <- pattern_ISO8601_time(truncated=min(truncated, 2), ...)
pattern_time <- pattern_ISO8601_time(truncated=min(truncated, 3), require_T=TRUE, ...)
pattern_time_aug <-
pattern_ISO8601_truncated_helper(
paste0("T", pattern_time),
pattern_time,
allow_truncation=truncated >= 3
)
pattern_ISO8601_calendar_date(
truncated=max(truncated - 3, 0),
time_pattern=pattern_time_aug,
time_pattern=pattern_time,
...
)
}
Expand Down Expand Up @@ -114,9 +114,9 @@ pattern_ISO8601_calendar_date <- function(truncated=0, allow_before_year_1583=FA
} else {
"(158[3-9]|159[0-9]|1[6-9][0-9]{2}|[2-9][0-9]{3})"
}
pattern_month <- "-(0[0-9]|1[0-2])"
pattern_month <- "-(0[1-9]|1[0-2])"
# Not confirming that the date is valid for the month
pattern_day_number <- "[012][0-9]|3[01]"
pattern_day_number <- "0[1-9]|[12][0-9]|3[01]"
pattern_day <-
if (nchar(time_pattern) == 0) {
sprintf("-(%s)", pattern_day_number)
Expand Down Expand Up @@ -159,10 +159,12 @@ pattern_ISO8601_calendar_date <- function(truncated=0, allow_before_year_1583=FA
#' @param pattern_decimal_mark What regular expression patterns should be
#' allowed for the decimal mark? Comma and period are both allowed in the
#' standard and by default.
#' @param allow_leap_second Should leap seconds (61 seconds in a minute) be
#' allowed?
#' @param timezone Should the timezone be optional (NA, default), required
#' (TRUE), or omitted (FALSE)?
#' @param allow_leap_second Should leap seconds (61 seconds in a minute) be
#' allowed?
#' @param require_T Require the "T" at the beginning of the time? TRUE, FALSE,
#' or NA (optional)
#' @param ... Passed to \code{pattern_ISO8601_timezone()}
#' @family ISO8601 patterns
#' @export
Expand All @@ -171,7 +173,8 @@ pattern_ISO8601_time <- function(truncated=0,
allow_fractional_minutes=FALSE,
allow_fractional_seconds=TRUE,
fractional_digits=Inf, pattern_decimal_mark=c("\\.", ","),
timezone=NA, allow_leap_second=FALSE, ...) {
timezone=NA, allow_leap_second=FALSE, require_T=NA,
...) {
stopifnot(is.numeric(truncated))
stopifnot(length(truncated) == 1)
stopifnot(!is.na(truncated))
Expand Down Expand Up @@ -202,8 +205,19 @@ pattern_ISO8601_time <- function(truncated=0,
stopifnot(is.logical(allow_leap_second))
stopifnot(length(allow_leap_second) == 1)
stopifnot(!is.na(allow_leap_second))

stopifnot(is.logical(require_T))
stopifnot(length(require_T) == 1)

pattern_hour <- "([01][0-9]|2[0-3])"
pattern_hour_number <- "([01][0-9]|2[0-3])"
pattern_hour_t <- paste0("T", pattern_hour_number)
if (is.na(require_T)) {
pattern_hour <- paste0("T?", pattern_hour_number)
} else if (require_T) {
pattern_hour <- pattern_hour_t
} else {
pattern_hour <- pattern_hour_number
}
pattern_minute <- ":([0-5][0-9])"
partial_pattern_second_whole <-
if (allow_leap_second) {
Expand Down Expand Up @@ -236,12 +250,20 @@ pattern_ISO8601_time <- function(truncated=0,

# Put it together
pattern_second_aug <- pattern_ISO8601_truncated_helper(pattern_second, allow_truncation=truncated >= 1)
pattern_minute_aug <-
pattern_ISO8601_truncated_helper(
paste0(pattern_minute, pattern_second_aug),
allow_truncation=truncated >= 2
)
pattern_hour_aug <-
# To support the requirement of "T", pattern_minute_aug is not truncated by
# itself.
pattern_minute_aug <- paste0(pattern_minute, pattern_second_aug)
# T is required at the beginning for hour-only times
if (truncated >= 2) {
pattern_hour_aug <-
sprintf(
"(?:%s|%s)",
pattern_hour_t,
paste0(pattern_hour, pattern_minute_aug)
)
} else {
pattern_hour_aug <- paste0(pattern_hour, pattern_minute_aug)
}
if (!isFALSE(timezone)) {
pattern_timezone <-
pattern_ISO8601_truncated_helper(
Expand All @@ -250,7 +272,7 @@ pattern_ISO8601_time <- function(truncated=0,
)
ret <-
pattern_ISO8601_truncated_helper(
paste0(pattern_hour, pattern_minute_aug, pattern_timezone),
paste0(pattern_hour_aug, pattern_timezone),
allow_truncation=truncated >= 3
)
} else {
Expand Down
Loading

0 comments on commit 3f7a398

Please sign in to comment.