【问题标题】:fwrite changes times of POSIXct valuesfwrite 更改 POSIXct 值的时间
【发布时间】:2017-11-09 10:27:20
【问题描述】:

我正在使用 fwrite 在 R 中编写一个 csv。

我注意到写入的 csv 在 POSIXct 列中具有不同的值,这些值似乎与原始值相差一个小时(尽管我不确定它是始终相差一个小时还是随机值)。

例如,如果我从以下数据开始(日期时间被归类为 POSIXct):
查看(测试)

标识 |日期
---+--------------
01 | 2016-10-26 08:19:00
02 | 2016-10-26 09:05:00
03 | 2016-10-26 09:15:00
04 | 2016-10-26 09:15:00
05 | 2016-10-26 09:28:00

之后
fwrite(test, file = "test.csv", quote = TRUE)

nexttest 查看(下一个测试)
回报是

标识 |日期
---+--------------
01 | 2016-10-26T07:19:00Z
02 | 2016-10-26T08:05:00Z
03 | 2016-10-26T08:15:00Z
04 | 2016-10-26T08:15:00Z
05 | 2016-10-26T08:28:00Z

等等等等
使用 read.table 的结果是一样的。 我想我在 fwrite 语句中遗漏了一个论点。有任何想法吗?

sessionInfo()    
R version 3.4.2 (2017-09-28)    
Platform: x86_64-w64-mingw32/x64 (64-bit)    
Running under: Windows 7 x64 (build 7601) Service Pack 1    

Matrix products: default

locale:
[1] LC_COLLATE=English_United Kingdom.1252  LC_CTYPE=English_United 
Kingdom.1252   
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C                           

[5] LC_TIME=English_United Kingdom.1252    


dput(head(test))  
Date.Created = structure(c(1477919160, 1477915320, 1477936980, 
    1477919820, 1477917780, 1477909680), class = c("POSIXct", 
    "POSIXt"), tzone = "")    

【问题讨论】:

  • 完成(如果没问题,只包括日期列)

标签: r data.table


【解决方案1】:

查看?fwritedateTimeAs 参数:

Date/IDateITimePOSIXct 项目是如何编写的。

  • "ISO"(默认)- 2016-09-12、18:12:16 和 2016-09-12T18:12:16.999999Z。为方便起见,会打印 0、3 或 6 位小数秒,无论是否有任何 R 选项,例如 digits.secs。这个想法是,如果存在毫秒和微秒,那么您很可能希望保留它们。 R 的内部 UTC 表示是忠实地编写的,以鼓励 ISO 标准、阻止时区模糊性和速度。要考虑的一种选择是在 UTC 时区中启动 R,只需在 shell 中使用“$ TZ='UTC' R”(注意:它必须是 TZ='UTC' 和 R 之间的一个或多个空格,其他任何内容都将被静默忽略;此 TZ 设置仅适用于该 R 进程)或在 R 提示符处Sys.setenv(TZ='UTC') 然后继续,就好像 UTC 是本地时间一样。

[强调我的,见ISO 8061]

您需要确保控制您的POSIXct 对象显示在哪个时区(请参阅as.POSIXcttz 参数)并谨慎操作。

困扰我的关于 R 的一些事情是,当 tzone = '' 时,您的 POSIXct 对象隐含地获取了您的本地时区(用于打印)。更明确地说,您可以在声明 POSIXct 对象时检查您的 Sys.timezone() 并将其添加到 tz 参数,然后使用 attr(Date, 'tzone') = 'UTC' 将其转换为 UTC。

在您的机器上比较以下输出:

t = Sys.time()
t
attr(t, 'tzone') = 'UTC'
t
# [1] "2017-11-09 10:43:59 UTC"

所以,如果你这样做:

attr(test$Date, 'tzone') = 'UTC'
test$Date

您应该看到这与fwrite 生成的输出相匹配。

您可以检查print.POSIXctformat.POSIXct 的代码并查看设置attr(t, 'tzone') = 'UTC' 前后的unclass(t) 以说服自己所有时区的使用都是肤浅的——日期时间的内部表示R 中的对象始终是“自纪元以来的秒数”,只是 print/format 方法应用时区差异并影响您在打印时看到的对象表面。

【讨论】:

  • 当我执行 Sys.setenv(TZ='UTC') 并重新运行脚本时,它似乎已经解决了问题。这是否与 attr(t, 'tzone')='UTC' 做同样的事情?另外,我是否需要在我计划将来写入 csv 的所有 POSIXct 列上使用 attr() 函数?谢谢
  • @SaleemKhan 我对这个领域不是很熟悉... IIUC Sys.setenv(TZ = 'UTC') 将处理您所有POSIXct 列的打印(否则您将必须lapply 对所有相关列执行此操作,但我认为可以在您首先将列声明为POSIXct 的同时处理此步骤)。除非您使用 dateTimeAs = 'write.csv',否则所有 POSIXct 列将自动写入为 UTC。
【解决方案2】:

您是否尝试过更改参数 dateTimeAs ?

查看帮助:

日期时间作为
Date/IDate、ITime 和 POSIXct 项的编写方式。

“ISO”(默认)- 2016-09-12、18:12:16 和 2016-09-12T18:12:16.999999Z。 0、3 或 6 位小数秒会在出现时打印,以方便使用,而不管任何 R 选项(例如 digits.secs)。这个想法是,如果存在毫秒和微秒,那么您很可能希望保留它们。 R 的内部 UTC 表示是忠实地编写的,以鼓励 ISO 标准、阻止时区模糊和速度。要考虑的一种选择是在 UTC 时区中启动 R,只需在 shell 中使用“$ TZ='UTC' R”(注意:它必须是 TZ='UTC' 和 R 之间的一个或多个空格,其他任何内容都将被静默忽略;此 TZ 设置仅适用于该 R 进程)或 R 提示符处的 Sys.setenv(TZ='UTC'),然后继续,就好像 UTC 是本地时间一样。

“squash” - 20160912、181216 和 20160912181216999。此选项允许使用整数 div 和 mod 操作快速简单地提取 yyyy、mm、dd 和(最常见的分组方式)yyyymm 部分。例如,在 R 中,一个行辅助函数可以分别使用 %/%10000、%/%100%%100、%%100 和 %/%100。 POSIXct UTC 被压缩为 17 位数字(始终包括 3 位毫秒,即使是 000),可以舒适地读取为 integer64(由 fread() 自动)。

“纪元”- 17056、65536 和 1473703936.999999。自相关纪元(分别为 1970-01-01、00:00:00 和 1970-01-01T00:00:00Z)以来的基础天数或秒数,在此之前为负数(参见 ?Date)。如果存在,则会打印 0、3 或 6 位小数秒。

"write.csv" - 目前仅影响 POSIXct。它通过使用 as.character 方法编写为 write.csv 所做的,该方法注意 digits.secs 并将 R 的内部 UTC 表示转换回该历史日期的本地时间(或“tzone”属性)。因此,这可能很慢。所有其他列类型(包括与时区无关的 Date、IDate 和 ITime)都使用已与 write.csv 一致的快速 C 代码编写为“ISO”选项。

由于新的专用 C 代码,前三个选项很快。纪元到日期部分的转换使用 Howard Hinnant(参见参考资料)的快速方法,使用从 3 月 1 日开始的一年中的一天。您应该不会注意到这三个选项之间的写入速度有任何差异。 Date 和 IDate 支持的日期范围是 [0000-03-01, 9999-12-31]。这 3,652,365 个日期中的每一个都经过测试,并与基准 R 进行了比较,包括该范围内的所有 2,790 个闰日。

此选项也适用于列表列单元格中的日期/时间向量。

不支持完全灵活的格式字符串(例如“%m/%d/%Y”)。这是为了鼓励使用 ISO 标准,并且因为不知道如何在 C 级快速实现这种灵活性。如果需要,我们可能能够支持一两个更具体的选项。

【讨论】:

    猜你喜欢
    • 2020-12-07
    • 2020-06-13
    • 2014-06-30
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2013-03-12
    • 2020-01-05
    • 1970-01-01
    相关资源
    最近更新 更多