16

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

一些背景:我正在使用fasttime来自 S.Urbanek 的包,它接受字符串并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"

编辑/解决方案,@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
4

3 回答 3

14

要更改变量的tz属性,POSIXct最好先转换为字符或数字,然后再转换为POSIXct. 相反,您可以使用包的force_tz功能lubridate

library(lubridate)

datetime2 <- force_tz(datetime, tzone = "CET")
datetime2
attributes(datetime2)
于 2013-03-22T17:06:59.373 回答
13

编辑:

我之前的解决方案是将字符值传递给origin(即origin="1970-01-01")。这只适用于这里,因为现在已经在 R-devel 中修复了一个错误 ( #PR14973 )。

origin被强制POSIXct使用调用的tz参数as.POSIXct,而不是"GMT"像记录的那样。行为已更改以匹配文档,在这种情况下,这意味着您必须为 theoriginas.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。

于 2013-03-22T17:09:33.140 回答
4

包的替代方法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.
于 2016-07-08T08:33:18.830 回答