修改POSIXct对象的时区而不更改显示

时间:2013-03-22 16:46:48

标签: r timezone posixct

我有一个POSIXct对象,想要更改它的tz属性WITHOUT R来解释它(解释它意味着改变日期时间在屏幕上的显示方式)。

一些背景知识:我正在使用来自S.Urbanek的fasttime包,它将字符串转换为POSIXct非常快。问题是该字符串应代表“GMT”中的日期时间,而不是我的数据。

我最终得到一个POSIXct对象tz=GMT,实际上它是tz=GMT+1,如果我用

更改时区
attr(datetime, "tzone") <- "Europe/Paris";
datetime  <- .POSIXct(datetime,tz="Europe/Paris"); 

然后它将“显示”为GMT+2(基础值永远不会改变)。

编辑:这是一个例子

datetime=as.POSIXct("2011-01-01 12:32:23.234",tz="GMT")
attributes(datetime)
#$tzone
#[1] "GMT"
datetime
#[1] "2011-01-01 12:32:23.233 GMT"

如何在没有R的情况下更改此属性以解释它如何更改tzone并且仍将日期时间显示为"2011-01-01 12:32:23.233"

EDIT / SOLUTION,@ GSee的解决方案相当快,lubridate :: force_tz非常慢

datetime=rep(as.POSIXct("2011-01-01 12:32:23.234",tz="GMT"),1e5)
f <- function(x,tz) return(as.POSIXct(as.numeric(x), origin="1970-01-01", tz=tz))
> system.time(datetime2 <- f(datetime,"Europe/Paris"))
   user  system elapsed 
   0.01    0.00    0.02 
> system.time(datetime3 <- force_tz(datetime,"Europe/Paris"))
   user  system elapsed 
   5.94    0.02    5.98 
identical(datetime2,datetime3)
[1] TRUE

3 个答案:

答案 0 :(得分:10)

EDITED:

我之前的解决方案是将字符值传递给origin(即origin="1970-01-01")。这只能在这里工作,因为在R-devel中现在有#PR14973的错误(been fixed)。

origin使用POSIXct调用的tz参数被强制转移到as.POSIXct,而不是"GMT",因为它已记录在案。该行为已更改为与文档相匹配,在这种情况下,这意味着您必须为originas.POSIXct调用指定时区。

datetime
#[1] "2011-01-01 12:32:23.233 GMT"
as.POSIXct(as.numeric(datetime), origin=as.POSIXct("1970-01-01", tz="Europe/Paris"),
           tz="Europe/Paris")
#[1] "2011-01-01 12:32:23.233 CET"

这也适用于旧版本的R。

答案 1 :(得分:8)

要更改tz变量的POSIXct属性,最好不要将其转换为字符或数字,然后再转换回POSIXct。相反,您可以使用force_tz

lubridate功能
library(lubridate)

datetime2 <- force_tz(datetime, tzone = "CET")
datetime2
attributes(datetime2)

答案 2 :(得分:2)

lubridate包的替代方法是通过转换为字符类型返回:

recastTimezone.POSIXct <- function(x, tz) return(
  as.POSIXct(as.character(x), origin = as.POSIXct("1970-01-01"), tz = tz))

(改编自GSee的回答)

不知道这是否有效,但它适用于夏令时的时区。

测试代码:

x <- as.POSIXct('2003-01-03 14:00:00', tz = 'Etc/UTC')
x
recastTimezone.POSIXct(x, tz = 'Australia/Melbourne')

输出:

[1] "2003-01-03 14:00:00 UTC"
[1] "2003-01-03 14:00:00 AEDT" # Nothing is changed apart from the time zone.

如果我将as.character()替换为as.numeric()(如GSee所做的那样),则输出:

[1] "2003-01-03 14:00:00 UTC"
[1] "2003-01-03 15:00:00 AEDT" # An hour is added.