Что вы думаете о том, чтобы не изменять объекты, а вместо этого сохранять временные метки так же, как сохраняется история? R сохраняет историю вашей консоли в файл .Rhistory
в папке, в которой вы работаете (т.е. getwd()
).
Я позволю R сохранить временные метки (в формате Unix, количество секунд с начала эпохи = 1 января 1970 г. 0:00:00) до .Rtimestamps
, но только если это установлено в качестве опции:
#' @export
#' @noRd
`<-` = function(...) {
if (!is.null(getOption("recordTimestamps"))
& interactive()
& environmentName(parent.frame()) == "R_GlobalEnv") {
# only save timestamp when set in options, in interactive mode and in global env.
if (getOption("recordTimestamps")) {
write(
x = paste(
as.character(match.call())[2],
as.double(Sys.time()),
sep = ","),
file = ".Rtimestamps",
append = TRUE)
}
}
eval.parent(
replace(
match.call(),
1,
list(base::`<-`)))
}
Использование:
options(recordTimestamps = TRUE) # only first time of course
a <- 123
# wait 5 seconds and change it
a <- 456
Теперь вам нужно получить только те даты, которые вы можете сделать с некоторыми вспомогательными функциями, которые печатают действительные классы POSIXct:
#' @export
#' @noRd
ctime <- function(object) {
target_object <- deparse(substitute(object))
get_cmtime(target_object, 1)
}
#' @export
#' @noRd
mtime <- function(object) {
target_object <- deparse(substitute(object))
get_cmtime(target_object, 2)
}
get_cmtime <- function(target_object, mode) {
if (!is.null(getOption("recordTimestamps")) & interactive()) {
# only get dates when set in options and when in interactive mode
if (getOption("recordTimestamps") & file.exists(".Rtimestamps")) {
lines <- readLines(con <- file(".Rtimestamps"), warn = FALSE, encoding = "UTF-8")
close(con)
target_lines <- lines[grepl(paste0("^(", target_object, "),"), lines)]
if (length(target_lines) > 0) {
if (mode == 1) {
# get first value, second element
timestamp <- unlist(strsplit(target_lines[1], ","))[2]
} else if (mode == 2) {
# get last value, second element
timestamp <- unlist(strsplit(target_lines[length(target_lines)], ","))[2]
}
## transform to date
return(as.POSIXct(origin = "1970-01-01", x = as.double(timestamp)))
} else {
return(NA)
}
}
}
}
И теперь это работает так:
> a
[1] 456
> ctime(a)
[1] "2018-02-07 10:43:03 CET"
> mtime(a)
[1] "2018-02-07 10:43:08 CET"