如何在xts中更改时区

时间:2016-12-16 14:24:58

标签: r timezone xts

我想告诉r我的数据是否在UTC时区,以便我可以将它们转移到America/New_York。但是当我使用indexTZ()时,它会改变时间。

我希望16:00 UTC小时成为纽约时差12:00。

    test = read.zoo(paste0(datadir,"test_.csv"), 
                  index = 1,FUN = as.POSIXct, header = T, sep = ",") 
    test = as.xts(test)
    head(test)


    > QQQ.Open QQQ.High QQQ.Low QQQ.Close QQQ.Volume
    > 
    > 2016-09-10 16:38:00  4665.75  4665.75 4665.75   4665.75          1
    > 2016-09-11 14:13:00  4665.75  4665.75 4665.75   4665.75          1
    > 2016-09-11 22:01:00  4661.25  4667.25 4657.25   4666.75        932
    > 2016-09-11 22:02:00  4666.75  4667.25 4663.25   4665.00        174
    > 2016-09-11 22:03:00  4665.00  4667.00 4665.00   4666.50         66


    indexTZ(test)<- "UTC"
    head(test)

                    QQQ.Open QQQ.High QQQ.Low QQQ.Close QQQ.Volume
2016-09-10 20:38:00  4665.75  4665.75 4665.75   4665.75          1
2016-09-11 18:13:00  4665.75  4665.75 4665.75   4665.75          1
2016-09-12 02:01:00  4661.25  4667.25 4657.25   4666.75        932
2016-09-12 02:02:00  4666.75  4667.25 4663.25   4665.00        174
2016-09-12 02:03:00  4665.00  4667.00 4665.00   4666.50         66
Warning message:
timezone of object (UTC) is different than current timezone ().


> test_dt$hour1 = strftime(test_dt$index, format = "%H", tz = "America/New_York")

> test_dt$hour2 = strftime(test_dt$index, format = "%H", tz = "UTC")

> table(test_dt$hour1)

14 16 22 
 1  1  3 

> table(test_dt$hour2)

02 18 20 
 3  1  1 

3 个答案:

答案 0 :(得分:3)

转移时区有点棘手。您需要先退后一步,并意识到实际存储的时间是一个数字(自1970年1月1日以来的秒数)表示绝对时间。即我看到我如何代表纽约和莫斯科当地时间的同一时间点(&#34;纪元&#34;):

R> format(as.POSIXct(0,origin="1970-01-01"), tz="UTC")
[1] "1970-01-01"
R> format(as.POSIXct(0,origin="1970-01-01"), tz="America/New_York")
[1] "1969-12-31 19:00:00"
R> format(as.POSIXct(0,origin="1970-01-01"), tz="Europe/Moscow")
[1] "1970-01-01 03:00:00"
R>

现在,您存储的时间可能已解析为localtime。也就是说它们包含一个偏移存储区作为时区。通过改变你只是相对于前一次移动:

R> as.POSIXct("2016-09-10 16:38:00")  # CDT as I am in Chicago
[1] "2016-09-10 16:38:00 CDT"
R> format(as.POSIXct("2016-09-10 16:38:00"), tz="America/New_York")
[1] "2016-09-10 17:38:00"
R> format(as.POSIXct("2016-09-10 16:38:00"), tz="America/Los_Angeles")
[1] "2016-09-10 14:38:00"
R> 

所以我理解你的问题,你需要做两件事:&#39;撤消&#39;你当地的时间,然后移动到所需的时区。

我也为此写了一个帮助 - 在RcppCCTZ包中。以下是toTz()函数的一个示例:

R> example(toTz)

toTzR> toTz(Sys.time(), "America/New_York", "Europe/London")
[1] "2016-12-17 01:04:14.184086 CST"

toTzR> # this redoes the 'Armstrong on the moon in NYC and Sydney' example
toTzR> # note that the default print method will print the return object in _your local time_
toTzR> toTz(ISOdatetime(1969,7,20,22,56,0,tz="UTC"), "America/New_York", "Australia/Sydney", verbose=TRUE)
1969-07-20 22:56:00 -0400
1969-07-21 12:56:00 +1000
[1] "1969-07-20 21:56:00 CDT"

toTzR> # whereas explicitly formating for Sydney time does the right thing
toTzR> format(toTz(ISOdatetime(1969,7,20,22,56,0,tz="UTC"), 
toTz+             "America/New_York", "Australia/Sydney", verbose=TRUE), 
toTz+        tz="Australia/Sydney")
1969-07-20 22:56:00 -0400
1969-07-21 12:56:00 +1000
[1] "1969-07-21 12:56:00"

这也显示了确保您打印到所需时区的额外难度 - 只有第二个示例显示正确的悉尼时间,因为我们明确告诉format()使用它。

回到你的例子:

R> x <- xts(1:2, Sys.time() + 0:1)
R> x
                          [,1]
2016-12-16 20:13:43.29767    1
2016-12-16 20:13:44.29767    2
R> tzone(x) <- "America/New_York"
R> x
                          [,1]
2016-12-16 21:13:43.29767    1
2016-12-16 21:13:44.29767    2
Warning message:
timezone of object (America/New_York) is different than current timezone (). 
R> index(x) <- index(x) - 60*60  # dirty method, last resort
R> x
                          [,1]
2016-12-16 20:13:43.29767    1
2016-12-16 20:13:44.29767    2
Warning message:
timezone of object (America/New_York) is different than current timezone (). 
R> tzone(x)
                TZ 
"America/New_York" 
R> 

所以我明确地将数字值更改了60分钟,以说明我将时间换了一个小时(从芝加哥,我当地时间到纽约)。

答案 1 :(得分:3)

您的数据可能已加载为“America / New_York”时间,此时您可能应将时区指定为“UTC”。 (您可以将时区参数作为FUN=POSIXct的passthrough参数传递。)

重现原始状况:

data <- " 2016-09-10 16:38:00  4665.75  4665.75 4665.75   4665.75          1
2016-09-11 14:13:00  4665.75  4665.75 4665.75   4665.75          1
2016-09-11 22:01:00  4661.25  4667.25 4657.25   4666.75        932
2016-09-11 22:02:00  4666.75  4667.25 4663.25   4665.00        174
2016-09-11 22:03:00  4665.00  4667.00 4665.00   4666.50         66"

data = read.table(text = data,
                  col.names = c("date", "time", "Open" ,  "High", "Low", "Close", "Volume")
                  )
# assumes data is loaded in America/New_York time zone
x_data <- xts(order.by = as.POSIXct(paste(data$date, data$time), tz = "America/New_York"), data[3:NCOL(data)])


x_data
# Open    High     Low   Close Volume
# 2016-09-10 16:38:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 14:13:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 22:01:00 4661.25 4667.25 4657.25 4666.75    932
# 2016-09-11 22:02:00 4666.75 4667.25 4663.25 4665.00    174
# 2016-09-11 22:03:00 4665.00 4667.00 4665.00 4666.50     66

indexTZ(x_data) <- "UTC"

# This reproduces your situation (problem):
head(x_data)
# Open    High     Low   Close Volume
# 2016-09-10 20:38:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 18:13:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-12 02:01:00 4661.25 4667.25 4657.25 4666.75    932
# 2016-09-12 02:02:00 4666.75 4667.25 4663.25 4665.00    174
# 2016-09-12 02:03:00 4665.00 4667.00 4665.00 4666.50     66


# This is what you probably wanted to do. Set the initial timezone to "UTC" when you loaded the data into R and created your `POSIXct` objects.

x_data <- xts(order.by = as.POSIXct(paste(data$date, data$time), tz = "UTC"), data[3:NCOL(data)])
head(x_data)
# Open    High     Low   Close Volume
# 2016-09-10 16:38:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 14:13:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 22:01:00 4661.25 4667.25 4657.25 4666.75    932
# 2016-09-11 22:02:00 4666.75 4667.25 4663.25 4665.00    174
# 2016-09-11 22:03:00 4665.00 4667.00 4665.00 4666.50     66
indexTZ(x_data) <- "America/New_York"
# Now you get your desired outcome:
head(x_data)
# Open    High     Low   Close Volume
# 2016-09-10 12:38:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 10:13:00 4665.75 4665.75 4665.75 4665.75      1
# 2016-09-11 18:01:00 4661.25 4667.25 4657.25 4666.75    932
# 2016-09-11 18:02:00 4666.75 4667.25 4663.25 4665.00    174
# 2016-09-11 18:03:00 4665.00 4667.00 4665.00 4666.50     66

答案 2 :(得分:0)

啊哈,是的,答案是使用正确的时区创建xts对象:

e.g:

S = as.xts(test, tz = "UTC")