Search code examples
rtimezoneepochposixct

converting seconds from the Epoch into localtime


Suppose I have a few timestamps given as integers (seconds) from the Unix Epoch (1970-01-01 00:00:00Z).

How do I convert them into the proper date-time in the local timezone? I've been looking at the as.POSIXct help page as well as related questions on SO. It's easy to do in UTC, but for some reason I can't seem able to do it straightforwardly for the local timezone, or for another timezone (BTW, I happen to be in "America/Los_Angeles", or "PST5PDT", which becomes "PST or "PDT" depending of whether daytime savings is in effect at the specified time; so I usually specify the location-based timezone rather than "PST" or "PDT", which are finicky).

Setup for the examples:

z <- c(1360527317,1363019665)

Quick verification in perl:

echo -n 1360527317,1363019665 | perl -ne '
use POSIX /strftime/;
$fmt = "%Y-%m-%d %H:%M:%S";
for (split /,/) {
  $loc=strftime("$fmt %Z", localtime($_));
  $gmt=strftime("$fmt GMT", gmtime($_));
  print "$_: $loc $gmt\n";
}'
# gives:
1360527317: 2013-02-10 12:15:17 PST 2013-02-10 20:15:17 GMT
1363019665: 2013-03-11 09:34:25 PDT 2013-03-11 16:34:25 GMT

First, the obvious (in UTC):

as.POSIXct(z, origin='1970-01-01', tz='GMT')
# --> [1] "2013-02-10 20:15:17 GMT" "2013-03-11 16:34:25 GMT"

Here are things I tried that DON'T work:

as.POSIXct(z, origin='1970-01-01')
# --> (wrong) [1] "2013-02-10 20:15:17 PST" "2013-03-11 17:34:25 PDT"

as.POSIXct(z, origin='1970-01-01 00:00:00 Z')
# --> (wrong) [1] "2013-02-10 20:15:17 PST" "2013-03-11 17:34:25 PDT"

as.POSIXct(z, origin='1970-01-01', tz='America/Los_Angeles')
# --> (wrong) [1] "2013-02-10 20:15:17 PST" "2013-03-11 17:34:25 PDT"

At my wits' end, here is something that gives me the correct outcome:

now=Sys.time(); now+(z-unclass(now))
# --> [1] "2013-02-10 12:15:17 PST" "2013-03-11 09:34:25 PDT"

And BTW on my system:

now=Sys.time()
now
# --> [1] "2013-03-13 18:26:05 PDT"
unclass(now)
# --> [1] 1363224365

So it appears that my settings and local timezone are correct.

Any idea what I'm doing wrong with the lines that don't work above?

In the meantime, I'll be using the following trick, hopefully useful to someone else:

localtime <- function(t) {
  now = Sys.time();
  return(now+(unclass(t)-unclass(now)))
}
# quick test:
localtime(Sys.time())
# --> [1] "2013-03-13 18:33:40 PDT"
localtime(z)
# --> [1] "2013-02-10 12:15:17 PST" "2013-03-11 09:34:25 PDT"

Solution

  • Try passing a Date to origin instead of a string

    as.POSIXct(z, origin=as.Date('1970-01-01'), tz='America/Los_Angeles')