[Rd] Another issue with Sys.timezone
Stephen Berman
stephen.berman at gmx.net
Sun Oct 15 01:53:12 CEST 2017
(I reported the test failure mentioned below to R-help but was advised
that this list is the right one to address the issue; in the meantime I
investigated the matter somewhat more closely, including searching
recent R-devel postings, since I haven't been following this list.)
Last May there were two reports here of problems with Sys.timezone, one
where the zoneinfo directory is in a nonstandard location
(https://stat.ethz.ch/pipermail/r-devel/2017-May/074267.html) and the
other where the system lacks the file /etc/localtime
(https://stat.ethz.ch/pipermail/r-devel/2017-May/074275.html). My
system exhibits a third case: it lacks /etc/timezone and does not set TZ
systemwide, but it does have /etc/localtime, which is a copy of, rather
than a symlink to, a file under zoneinfo. On this system Sys.timezone()
returns NA and the Sys.timezone test in reg-tests-1d fails. However, on
my system I can get the (abbreviated) timezone in R by using as.POSIXlt,
e.g. as.POSIXlt(Sys.time())$zone. If Sys.timezone took advantage of
this, e.g. as below, it would be useful on such systems as mine and the
regression test would pass.
my.Sys.timezone <-
function (location = TRUE)
{
tz <- Sys.getenv("TZ", names = FALSE)
if (!location || nzchar(tz))
return(Sys.getenv("TZ", unset = NA_character_))
lt <- normalizePath("/etc/localtime")
if (grepl(pat <- "^/usr/share/zoneinfo/", lt) ||
grepl(pat <- "^/usr/share/zoneinfo.default/", lt))
sub(pat, "", lt)
else if (lt == "/etc/localtime")
if (!file.exists("/etc/timezone"))
return(as.POSIXlt(Sys.time())$zone)
else if (dir.exists("/usr/share/zoneinfo") && {
info <- file.info(normalizePath("/etc/timezone"), extra_cols = FALSE)
(!info$isdir && info$size <= 200L)
} && {
tz1 <- tryCatch(readBin("/etc/timezone", "raw", 200L),
error = function(e) raw(0L))
length(tz1) > 0L && all(tz1 %in% as.raw(c(9:10, 13L, 32:126)))
} && {
tz2 <- gsub("^[[:space:]]+|[[:space:]]+$", "", rawToChar(tz1))
tzp <- file.path("/usr/share/zoneinfo", tz2)
file.exists(tzp) && !dir.exists(tzp) &&
identical(file.size(normalizePath(tzp)), file.size(lt))
})
tz2
else NA_character_
}
One problem with this is that the zone component of as.POSIXlt only
holds the abbreviated timezone, not the Olson name. I don't know how to
get the Olson name using only R functions, but maybe it would be good
enough to return the abbreviated timezone where possible, e.g. as above.
(On my system I can get the Olson name of the timezone in R with a shell
pipeline, e.g.: system("find /usr/share/zoneinfo/ -type f | xargs md5sum
| grep $(md5sum /etc/localtime | cut -d ' ' -f 1) | head -n 1 | cut -d
'/' -f 5,6"), but the last part of this is tailored to my configuration
and the whole thing is not OS-neutral, so it isn't suitable for
Sys.timezone.)
Steve Berman
More information about the R-devel
mailing list