【问题标题】:How to change timezones in xts如何在 xts 中更改时区
【发布时间】:2016-12-16 14:24:57
【问题描述】:

我想告诉 r 我的数据位于 UTC 时区,这样我就可以将它们转移到 America/New_York。但是当我使用indexTZ() 时,它改变了时代。

我希望 16:00 UTC 时间变成 12:00 NY 时间。

    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 

【问题讨论】:

    标签: r timezone xts


    【解决方案1】:

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

    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>
    

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

    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> 
    

    所以我正确理解了您的问题,您需要做两件事:“撤消”您拥有的本地时间,然后移动到所需的时区。

    我也为此编写了一个帮助程序——在 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> 
    

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

    【讨论】:

      【解决方案2】:

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

      再现你原来的情况:

      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
      

      【讨论】:

        【解决方案3】:

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

        例如:

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

        【讨论】:

          猜你喜欢
          • 2014-11-14
          • 1970-01-01
          • 2016-06-14
          • 2011-03-14
          • 2019-04-25
          • 2011-05-26
          • 2017-09-07
          • 2023-03-27
          • 2020-02-27
          相关资源
          最近更新 更多