Dave X
Dave X

Reputation: 5127

Determine and set timezone in POSIXct, POSIXlt, strptime, etc. in R

t.ct = as.POSIXct("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z")
t.lt = as.POSIXlt("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z")
t.st =   strptime("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z")

These seem to be the same times:

> t.ct -t.lt
Time difference of 0 secs
> t.ct -t.st
Time difference of 0 secs
> str(t.ct)
 POSIXct[1:1], format: "2009-01-04 21:19:00"
> str(t.lt)
 POSIXlt[1:1], format: "2009-01-04 21:19:00"
> str(t.st)
 POSIXlt[1:1], format: "2009-01-04 21:19:00"
> 

But these appear to have different timezone information in them, and it is not what I'd expect:

>     strftime(t.ct,"%Y-%m-%d %H:%M:%S %z")
[1] "2009-01-04 21:19:00 -0500"
>     strftime(t.lt,"%Y-%m-%d %H:%M:%S %z")
[1] "2009-01-04 21:19:00 +1200"
>     strftime(t.st,"%Y-%m-%d %H:%M:%S %z")
[1] "2009-01-04 21:19:00 +1200"
> 

The timezone on my Mac is:

> Sys.timezone()
[1] "America/New_York"

The questions Difference between as.POSIXct/as.POSIXlt and strptime for converting character vectors to POSIXct/POSIXlt and as.POSIXlt ignores tz argument seemed related, but didn't clarify this for me.

How do I definitively set a time and use it?

Update:

From user3293236's answer below, it seems one should always declare the timezone of the string, and if you are parsing the '-hhmm' offset, then always use tz="UTC":

t.ct = as.POSIXct("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z", tz="UTC")
t.lt = as.POSIXlt("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z", tz="UTC")
t.st =   strptime("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z", tz="UTC")

Upvotes: 7

Views: 10064

Answers (1)

Buggy
Buggy

Reputation: 2100

If you do not use a timezone specifically, POSIXct and POSIXlt will reference to your local timezone. However, this is not entirely reliable. POSIXlt will not display the timezone in the output string.

Note, the tzone argument is not set.

t.ct <- as.POSIXct("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z")
t.lt <- as.POSIXlt("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z")
t.ct
t.lt
attr(t.ct,"tzone") #""
attr(t.lt,"tzone") #NULL

If you do want to avoid ambiguous behaviour, you have to specifiy a time zone. The output string will still be different (by default POSIXlt shows no timezone), but the attribute is the same

t.ct <- as.POSIXct("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z", tz="Europe/Helsinki")
t.lt <- as.POSIXlt("2009-01-05 14:19 +1200", format="%Y-%m-%d %H:%M %z", tz="Europe/Helsinki")
t.ct
t.lt
attr(t.ct,"tzone") #Europe/Helsinki
attr(t.lt,"tzone") #Europe/Helsinki

Now, if you want to change time zones after the original assignment:

attr(t.ct, "tzone") <- "UTC" #this will SHIFT the time zone to UTC
attr(t.lt, "tzone") <- "UTC" #this will REPLACE the time zone to UTC
t.ct
t.lt

As for your problem with strftime and %z, this does not give you the time zone attribute. The difference in your case, probably comes from a combination of string formatting, object conversions and time zone formating, IMO. But maybe somebody more knowledgable, can clarify this.

Upvotes: 11

Related Questions