Я читаю данные с другой платформы, где комбинация строк, перечисленных ниже, используется для выражения временных меток:
\* = current time
t = current day (00:00)
mo = month
d = days
h = hours
m = minutes
Например, *-3d
— это текущее время минус 3 дня, t-3h
— это три часа до сегодняшнего утра (вчера полночь).
Я хотел бы иметь возможность вводить эти уравнения в R и получать соответствующее значение POSIXct
. Я пытаюсь использовать регулярное выражение в приведенной ниже функции, но теряю числовой множитель для каждой строки:
strTimeConverter <- function(z){
ret <- stringi::stri_replace_all_regex(
str = z,
pattern = c('^\\*',
'^t',
'([[:digit:]]{1,})mo',
'([[:digit:]]{1,})d',
'([[:digit:]]{1,})h',
'([[:digit:]]{1,})m'),
replacement = c('Sys.time()',
'Sys.Date()',
'*lubridate::months(1)',
'*lubridate::days(1)',
'*lubridate::hours(1)',
'*lubridate::minutes(1)'),
vectorize_all = F
)
return(ret)
# return(eval(expr = parse(text = ret)))
}
> strTimeConverter('*-5mo+3d+4h+2m')
[1] "Sys.time()-*lubridate::months(1)+*lubridate::days(1)+*lubridate::hours(1)+*lubridate::minutes(1)"
> strTimeConverter('t-5mo+3d+4h+2m')
[1] "Sys.Date()-*lubridate::months(1)+*lubridate::days(1)+*lubridate::hours(1)+*lubridate::minutes(1)"
Ожидаемый результат:
# *-5mo+3d+4h+2m
"Sys.time()-5*lubridate::months(1)+3*lubridate::days(1)+4*lubridate::hours(1)+4*lubridate::minutes(1)"
# t-5mo+3d+4h+2m
"Sys.Date()-5*lubridate::months(1)+3*lubridate::days(1)+4*lubridate::hours(1)+4*lubridate::minutes(1)"
Я предполагал, что заключение [[:digit]]{1,}
в круглые скобки ()
сохранит их, но очевидно, что это не работает. Я определил шаблон следующим образом, иначе код заменяет повторяющиеся вхождения, например. *
преобразуется в Sys.time()
, но затем m
в Sys.time()
заменяется на *lubridate::minutes(1)
.
Я планирую преобразовать (ожидаемый) вывод в дату-время R, используя eval(parse(text = ...))
- в настоящее время закомментировано в функции.
Я открыт для использования других пакетов или подходов.
Обновить
Немного поработав, я обнаружил, что приведенная ниже версия работает — я заменяю строки в таком порядке, чтобы вновь замененные символы не заменялись снова:
strTimeConverter <- function(z){
ret <- stringi::stri_replace_all_regex(
str = z,
pattern = c('y', 'd', 'h', 'mo', 'm', '^t', '^\\*'),
replacement = c('*years(1)',
'*days(1)',
'*hours(1)',
'*days(30)',
'*minutes(1)',
'Sys.Date()',
'Sys.time()'),
vectorize_all = F
)
ret <- gsub(pattern = '\\*', replacement = '*lubridate::', x = ret)
rdate <- (eval(expr = parse(text = ret)))
attr(rdate, 'tzone') <- 'UTC'
return(rdate)
}
sample_string <- '*-5mo+3d+4h+2m'
strTimeConverter(sample_string)
Это работает, но не очень элегантно и, скорее всего, потерпит неудачу, поскольку я вынужден включать другие выражения (например, yd
для дня года, например, 124).