关于posixct:r,write_csv正在将所有时间/日期更改为UTC

r, write_csv is changing all times/dates to UTC

我发现了一个非常恼人的问题,我想与社区分享。这是一个问题,我找到了一个可接受的解决方案(详情如下),但我现在有几个后续问题。我对时间戳和posix变量的了解是有限的,特别是plyr、dplyr和readr如何处理这些变量。

在处理posix变量(aka,日期和时间戳)时,我发现write_csv from readr将这些变量改为utc time。

我正在从API下载数据并保留时间戳。每次获取数据时,我都将其绑定到现有文件并保存该文件。我的时区是MDT,我使用MDT时间请求数据,然后我试图用UTC时间绑定到一个文件,时间不匹配……这会变得混乱和令人沮丧。实际上,我试图创建的漂亮的时间戳数据库正在变成一堆垃圾。

为了解决这个问题,我使用以下方法将posix time列转换为character列:

1
df.time <- as.character(df.time)

这允许我将文件保存在与API返回给我的时间戳一致的时区中。

这将引出以下一系列问题:

  • 有没有一个程序可以跨时区连接POSIX变量?例如,如果是中午的MDT,则是下午6点的UTC。我可以加入两个基于这些时间戳的数据帧而不必先将它们转换为同一时区吗?
  • 有没有可能阻止写csv将posix变量更改为utc?
  • 是否有一个csv写函数不改变posix变量?
  • 编辑:我已经包含了一些我所说的示例数据:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    > df1 <- as.data.frame(fromJSON("https://api.pro.coinbase.com/products/BTC-USD/candles?start=2018-07-23&12:57:00?stop=2018-07-23&19:34:58granularity=300"))
    > colnames(df1) <- c("time","low","high","open","close","volume")
    > df1$time <- anytime(df1$time)
    > df1Sort <- df1[order(df1$time),]
    > head(df1Sort, 5)
                       time     low    high    open   close    volume
    299 2018-07-23 16:13:00 7747.00 7747.01 7747.01 7747.01 9.2029168
    298 2018-07-23 16:14:00 7743.17 7747.01 7747.00 7747.01 7.0205668
    297 2018-07-23 16:15:00 7745.47 7745.73 7745.67 7745.73 0.9075707
    296 2018-07-23 16:16:00 7745.72 7745.73 7745.72 7745.73 4.6715157
    295 2018-07-23 16:17:00 7745.72 7745.73 7745.72 7745.72 2.4921921
    > write_csv(df1Sort,"df1Sort.csv", col_names = TRUE)
    > df2 <- read_csv("df1Sort.csv", col_names = TRUE)
    Parsed with column specification:
    cols(
      time = col_datetime(format =""),
      low = col_double(),
      high = col_double(),
      open = col_double(),
      close = col_double(),
      volume = col_double()
    )
    > head(df2, 5)
    # A tibble: 5 x 6
      time                  low  high  open close volume
      <dttm>              <dbl> <dbl> <dbl> <dbl>  <dbl>
    1 2018-07-23 22:13:00  7747  7747  7747  7747  9.20
    2 2018-07-23 22:14:00  7743  7747  7747  7747  7.02
    3 2018-07-23 22:15:00  7745  7746  7746  7746  0.908
    4 2018-07-23 22:16:00  7746  7746  7746  7746  4.67
    5 2018-07-23 22:17:00  7746  7746  7746  7746  2.49


    看起来你在使用Tidyverse的库;你看过Lubridate库吗?

    as_date()的帮助文件可以帮助您在附加/加入数据之前将日期时间变量转换为所需时区。

    例如:

    1
    2
    3
    4
    5
    6
    > dt_utc <- ymd_hms("2010-08-03 00:50:50")
    > dt_utc
    [1]"2010-08-03 00:50:50 UTC"

    > as_datetime(dt_utc, tz ="Australia/Melbourne")
    [1]"2010-08-03 10:50:50 AEST"


  • "有没有一个程序可以跨时区连接POSIX变量…不必先将它们转换到同一时区?"

    也许吧?但如果是这样的话,他们几乎肯定只是在转变成UTC,并对你隐瞒。我不知道R中有什么类似的东西。(data.table是我所知道的唯一一个可以加入除完全相等以外的任何东西的包,它没有这个特性。)如果我是你,我会把所有东西都转换成一个时区,可能是UTC。

    对于更多关于最佳实践的阅读,这个以SQL为中心的答案似乎非常好。

  • "是否有可能阻止写入csv将posix变量更改为utc?"

    不是内置的。?write_csv文档非常清楚:它没有列出任何选项,并且说"posixct的格式是iso8601"。

  • "是否有一个csv写入函数不改变posix变量?"

    当然,内置的write.csv不会更改为utc(我认为它使用系统设置),data.table::fwrite提供了相当多的选项。如果你想控制你的日期是如何保存的,我想你最好的办法是把它们转换成你想要的任何格式的character,然后任何一个写函数都可以处理它们。你应该查看?data.table::fwrite文档,它有很好的信息。他们警告说,"write.csv"的选择可能非常缓慢。

  • 你的问题应该包括可重复的例子。这是一个:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    t = as.POSIXct("2018-01-01 01:30:00", tz ="Africa/Addis_Ababa")
    t
    # [1]"2018-01-01 01:30:00 EAT"

    d = data.frame(t)

    library(readr)
    write_csv(d,"tz_test.csv")
    system("head tz_test.csv")
    # 2017-12-31T22:30:00Z

    library(data.table)
    fwrite(d,"tz_test_dt.csv", dateTimeAs ="write.csv")
    system("head tz_test_dt.csv")
    # t
    # 2018-01-01 01:30:00

    write.csv(d,"tz_test_base.csv")
    system("head tz_test_base.csv")
    #"","t"
    #"1",2018-01-01 01:30:00