I am finding that axis.POSIXct uses the local timezone for deciding where to put tic marks, even if the data being plotted are in another time zone. The solution is to use attr() to copy from the 'x' (provided as an argument) to the 'z' (used for the 'at' locations). I have pasted my proposed solution in section 1 below (as a diff). Then, in section 2, I'll put some test code that I wrote, when I was figuring this out. I am not entirely sure whether it's OK, or helpful, to post a diff here. I don't understand the R development model well enough to know how to suggest changes, and ?axis.POSIXct does not list an author, so that's why I'm posting here. (All of this matters because I am sharing code with people working in different timezones; I want the timezone of the data to carry over to the graph.) Section 1: patch to axis.POSIXct =================== (Note that the line numbers may be wrong; I'm not working with the source for axis.POSIXct, but rather with the output from a listing of the function in the terminal). ~$ diff -Naur axis.POSIXct.R my.axis.POSIXct.R --- axis.POSIXct.R 2009-03-04 16:22:18.000000000 -0400 +++ my.axis.POSIXct.R 2009-03-04 16:22:56.000000000 -0400 @@ -1,4 +1,4 @@ -axis.POSIXct <- function (side, x, at, format, labels = TRUE, ...) +my.axis.POSIXct <- function (side, x, at, format, labels = TRUE, ...) { mat <- missing(at) || is.null(at) if (!mat) @@ -9,6 +9,7 @@ else 3:4] d <- range[2] - range[1] z <- c(range, x[is.finite(x)]) + attr(z, "tzone") <- attr(x, "tzone") if (d < 1.1 * 60) { sc <- 1 if (missing(format)) @@ -41,6 +42,7 @@ zz <- pretty(z/sc) z <- zz * sc class(z) <- c("POSIXt", "POSIXct") + attr(z, "tzone") <- attr(x, "tzone") if (sc == 60 * 60 * 24) z <- as.POSIXct(round(z, "days")) if (missing(format)) @@ -48,6 +50,7 @@ } else if (d < 1.1 * 60 * 60 * 24 * 365) { class(z) <- c("POSIXt", "POSIXct") + attr(z, "tzone") <- attr(x, "tzone") zz <- as.POSIXlt(z) zz$mday <- zz$wday <- zz$yday <- 1 zz$isdst <- -1 @@ -65,6 +68,7 @@ } else { class(z) <- c("POSIXt", "POSIXct") + attr(z, "tzone") <- attr(x, "tzone") zz <- as.POSIXlt(z) zz$mday <- zz$wday <- zz$yday <- 1 zz$isdst <- -1 ~$ Section 2. Test code ============ # fake some data, and draw a vertical line at midnight ... note how # the latter will be in the wrong place (unless the computer is set to UTC). tc <- c("2008-06-28 15:50:00 UTC","2008-06-28 20:50:00 UTC","2008-06-29 01:50:00 UTC", "2008-06-29 06:50:00 UTC","2008-06-29 11:50:00 UTC","2008-06-29 16:50:00 UTC", "2008-06-29 21:50:00 UTC","2008-06-30 02:50:00 UTC","2008-06-30 07:50:00 UTC", "2008-06-30 12:50:00 UTC") t <- as.POSIXct(tc, tz="UTC") # note using UTC p <- c(2.4998, 0.4687, 2.7120, 2.0676, 0.5614, 2.6121, 0.5161, 2.9572, 2.2567, 0.3820) t0 <- as.POSIXct("2008-06-29 00:00:00", tz="UTC") par(mfrow=c(2,1)) plot(t, p, type='l') abline(v=t0, col='red') plot(t, p, type='l', axes=FALSE) box() axis(2) source("~/my.axis.POSIXct.R") my.axis.POSIXct(side=1, x=t) abline(v=t0, col='red') -- View this message in context: http://www.nabble.com/patch-for-axis.POSIXct-%28related-to-timezones%29-tp22338700p22338700.html Sent from the R devel mailing list archive at Nabble.com.
Prof Brian Ripley
2009-Mar-05 07:50 UTC
[Rd] patch for axis.POSIXct (related to timezones)
This is the appropriate forum, and thank you for the comments. At a quick look it might be simpler to use the 'tz' argument to as.POSIXlt, but I'll look in more detail and commit a change later today. On Wed, 4 Mar 2009, Dan Kelley wrote:> > I am finding that axis.POSIXct uses the local timezone for deciding where to > put tic marks, even if the data being plotted are in another time zone. The > solution is to use attr() to copy from the 'x' (provided as an argument) to > the 'z' (used for the 'at' locations). > > I have pasted my proposed solution in section 1 below (as a diff). Then, in > section 2, I'll put some test code that I wrote, when I was figuring this > out. > > I am not entirely sure whether it's OK, or helpful, to post a diff here. I > don't understand the R development model well enough to know how to suggest > changes, and ?axis.POSIXct does not list an author, so that's why I'm > posting here. > > (All of this matters because I am sharing code with people working in > different timezones; I want the timezone of the data to carry over to the > graph.) > > Section 1: patch to axis.POSIXct > ===================> > (Note that the line numbers may be wrong; I'm not working with the source > for axis.POSIXct, but rather with the output from a listing of the function > in the terminal). > > ~$ diff -Naur axis.POSIXct.R my.axis.POSIXct.R > --- axis.POSIXct.R 2009-03-04 16:22:18.000000000 -0400 > +++ my.axis.POSIXct.R 2009-03-04 16:22:56.000000000 -0400 > @@ -1,4 +1,4 @@ > -axis.POSIXct <- function (side, x, at, format, labels = TRUE, ...) > +my.axis.POSIXct <- function (side, x, at, format, labels = TRUE, ...) > { > mat <- missing(at) || is.null(at) > if (!mat) > @@ -9,6 +9,7 @@ > else 3:4] > d <- range[2] - range[1] > z <- c(range, x[is.finite(x)]) > + attr(z, "tzone") <- attr(x, "tzone") > if (d < 1.1 * 60) { > sc <- 1 > if (missing(format)) > @@ -41,6 +42,7 @@ > zz <- pretty(z/sc) > z <- zz * sc > class(z) <- c("POSIXt", "POSIXct") > + attr(z, "tzone") <- attr(x, "tzone") > if (sc == 60 * 60 * 24) > z <- as.POSIXct(round(z, "days")) > if (missing(format)) > @@ -48,6 +50,7 @@ > } > else if (d < 1.1 * 60 * 60 * 24 * 365) { > class(z) <- c("POSIXt", "POSIXct") > + attr(z, "tzone") <- attr(x, "tzone") > zz <- as.POSIXlt(z) > zz$mday <- zz$wday <- zz$yday <- 1 > zz$isdst <- -1 > @@ -65,6 +68,7 @@ > } > else { > class(z) <- c("POSIXt", "POSIXct") > + attr(z, "tzone") <- attr(x, "tzone") > zz <- as.POSIXlt(z) > zz$mday <- zz$wday <- zz$yday <- 1 > zz$isdst <- -1 > ~$ > > > Section 2. Test code > ============> > # fake some data, and draw a vertical line at midnight ... note how > # the latter will be in the wrong place (unless the computer is set to UTC). > tc <- c("2008-06-28 15:50:00 UTC","2008-06-28 20:50:00 UTC","2008-06-29 > 01:50:00 UTC", > "2008-06-29 06:50:00 UTC","2008-06-29 11:50:00 UTC","2008-06-29 > 16:50:00 UTC", > "2008-06-29 21:50:00 UTC","2008-06-30 02:50:00 UTC","2008-06-30 > 07:50:00 UTC", > "2008-06-30 12:50:00 UTC") > t <- as.POSIXct(tc, tz="UTC") # note using UTC > > p <- c(2.4998, 0.4687, 2.7120, 2.0676, 0.5614, 2.6121, 0.5161, 2.9572, > 2.2567, 0.3820) > > t0 <- as.POSIXct("2008-06-29 00:00:00", tz="UTC") > par(mfrow=c(2,1)) > plot(t, p, type='l') > abline(v=t0, col='red') > > plot(t, p, type='l', axes=FALSE) > box() > axis(2) > source("~/my.axis.POSIXct.R") > my.axis.POSIXct(side=1, x=t) > abline(v=t0, col='red') > > > > -- > View this message in context: http://www.nabble.com/patch-for-axis.POSIXct-%28related-to-timezones%29-tp22338700p22338700.html > Sent from the R devel mailing list archive at Nabble.com. > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Some time ago, I posted a note about what I considered to be a bug in axis.POSIXt() for R 2.8.x, relating to whether timezones in the data are obeyed on the axes. A link to that note, and to a quick and helpful response, is at the following URL http://www.nabble.com/patch-for-axis.POSIXct-%28related-to-timezones%29-td22338700.html#a22338700 and I note that R 2.9.0 has been adjusted to help with this. However, there are still problems. I do apologize for not having performed a test build prior to the 2.9.0 release; this was partly because I find test builds difficult on my OSX box, and partly because I have written replacement code and mostly use that. But today I tried R 2.9.0, and the problem persists ... sometimes. Test code is given below. The top panel is correct, but the bottom one is incorrect. The problem relates to the time interval. # test code (top panel, OK; bottom panel, incorrect times on x axis) par(mar=c(2,2,2,1)) par(mfrow=c(2,1)) start <- as.POSIXct("2008-05-01 00:00:00", tz="UTC") end <- as.POSIXct("2008-05-01 00:10:00", tz="UTC") plot(c(start, end), c(0, 1), ylab="") mtext(paste(start, "to", end), side=3) start <- as.POSIXct("2008-05-01 00:00:00", tz="UTC") end <- as.POSIXct("2008-05-01 01:10:00", tz="UTC") plot(c(start, end), c(0, 1), ylab="") mtext(paste(start, "to", end), side=3) -- View this message in context: http://www.nabble.com/patch-for-axis.POSIXct-%28related-to-timezones%29-tp22338700p23454737.html Sent from the R devel mailing list archive at Nabble.com.