[R] Clean method to convert date and time between time zones keeping it in POSIXct format

MacQueen, Don macqueen1 at llnl.gov
Mon May 9 20:38:34 CEST 2016

I think setting the attribute is the best way to "convert", and the
following will hopefully explain why. (And I would tend to agree with
William Dunlap that a function to set the attribute might help userRs.)

R always stores POSIXct objects internally in seconds since an origin in
UTC. I would not think in terms of converting; I would think in terms of

t1 <- as.POSIXct("2016-05-09 10:00:00", tz="America/New_York")
t2 <- t1
attributes(t2)$tzone <- 'UTC'

> print(t1)
[1] "2016-05-09 10:00:00 EDT"
> print(t2)
[1] "2016-05-09 14:00:00 UTC"

> as.numeric(t1)
[1] 1462802400
> as.numeric(t2)
[1] 1462802400

The actual value of t2 is the same as t1, it has not been "converted"
(because to me conversion implies change, and there has been no change in
the value of t2). R has been merely been told to display it in UTC when

Similarly, when a character string is converted to POSIXct, R has to be
told what timezone to use to convert it to seconds since the origin in
UTC. If a timezone is not specified, the user's local (default) timezone
is used.

> t3 <- as.POSIXct("2016-05-09 10:00:00")
> t3
[1] "2016-05-09 10:00:00 PDT"
> as.numeric(t3)
[1] 1462813200

The number of seconds for t3 is different than for t1 and t2, and this is
because I am not in the America/New_York timezone

And, in fact,

> (as.numeric(t3) - as.numeric(t1))/3600
[1] 3

Indicating that PDT and America/New_York are three hours apart, as indeed
they are.

To me, this version
  t4 <- as.POSIXct(format(t1, tz="UTC"), tz="UTC")
doesn't recognize the distinction between internal storage and display,
and the fact that there is no real conversion.

> identical(t2, t4)
[1] TRUE

To go a little further,

> attributes(t3)
[1] "POSIXct" "POSIXt"

[1] ""

If a timezone is not specified when the object is created, then the tzone
attribute is set to "" and R displays using the local timezone.

> t3
[1] "2016-05-09 10:00:00 PDT"

I can change the local timezone:

> Sys.setenv(TZ='UTC')
> t3
[1] "2016-05-09 17:00:00 UTC"

t3 has not changed, but how it is displayed has changed.

Given all this, it's helpful that the format() function for POSIXt objects
has a tz argument.

> format(t3, tz='US/Pacific')
[1] "2016-05-09 10:00:00"

Indicating again that t3 has not changed; I've just manipulated to rules
for how it is displayed.


Don MacQueen

Lawrence Livermore National Laboratory
7000 East Ave., L-627
Livermore, CA 94550

On 5/9/16, 6:24 AM, "R-help on behalf of Arnaud Mosnier"
<r-help-bounces at r-project.org on behalf of a.mosnier at gmail.com> wrote:

>Dear UseRs,
>I know two ways to convert dates and time from on time zone to another but
>I am pretty sure that there is a better (cleaner) way to do that.
>Here are the methods I know:
>## The longest way ...
>T1 <- as.POSIXct("2016-05-09 10:00:00", format="%Y-%m-%d %H:%M:%S",
>T2 <- as.POSIXct(format(T1, tz="UTC"), tz="UTC") # format convert it to
>character, so I have to convert it back to POSIXct afterward.
>## The shortest but probably not the cleanest ...
>attributes(T1)$tzone <- "UTC"
>	[[alternative HTML version deleted]]
>R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>PLEASE do read the posting guide
>and provide commented, minimal, self-contained, reproducible code.

More information about the R-help mailing list