R 防止意外时区转换

R 防止意外时区转换,r,timezone,date,R,Timezone,Date,在R中,我有一组以GMT度量的datetime值。我经常遇到一些意外情况,某些函数或其他函数丢失了我值上的时区,甚至丢失了类名。即使是像c()和unlist()这样的基本函数: 我觉得如果这一切发生在我最不期望的时候,我离真正的时刻就差一点了。任何人都有确保自己的日期“保持不变”的策略吗?此行为记录在?c、?DateTimeClasses和?unlist中: > dput(x) structure(1317830532, class = c("POSIXct", "POSIXt"), tz

在R中,我有一组以GMT度量的datetime值。我经常遇到一些意外情况,某些函数或其他函数丢失了我值上的时区,甚至丢失了类名。即使是像
c()
unlist()
这样的基本函数:


我觉得如果这一切发生在我最不期望的时候,我离真正的时刻就差一点了。任何人都有确保自己的日期“保持不变”的策略吗?

此行为记录在
?c
?DateTimeClasses
?unlist
中:

> dput(x)
structure(1317830532, class = c("POSIXct", "POSIXt"), tzone = "GMT")
> dput(c(x))
structure(1317830532, class = c("POSIXct", "POSIXt"))
> dput(list(x))
list(structure(1317830532, class = c("POSIXct", "POSIXt"), tzone = "GMT"))
> dput(unlist(list(x)))
1317830532
?日期时间类

在“
POSIXlt
”对象上使用
c
将它们转换为当前时区,在“
POSIXct
”对象上删除任何“
tzone
”属性(即使它们都标记为同一时区)*

?c

c
有时用于消除除名称以外的属性的副作用*


也就是说,我的测试表明,尽管使用了
c
unlist
,数据的完整性仍然保持不变。例如:

x <- structure(1317830532, class = c("POSIXct", "POSIXt"), 
                 tzone = "GMT")
y <- structure(1317830532+3600, class = c("POSIXct", "POSIXt"), 
                 tzone = "PST8PDT")
x
[1] "2011-10-05 16:02:12 GMT"

y
[1] "2011-10-05 10:02:12 PDT"

strftime(c(x, y), format="%Y/%m/%d %H:%M:%S", tz="GMT")
[1] "2011/10/05 16:02:12" "2011/10/05 17:02:12"

strftime(c(x, y), format="%Y/%m/%d %H:%M:%S", tz="PST8PDT")
[1] "2011/10/05 09:02:12" "2011/10/05 10:02:12"

strftime(unlist(y), format="%Y/%m/%d %H:%M:%S", tz="PST8PDT")
[1] "2011/10/05 10:02:12"

x那么,为什么不将你的R会话的时区设置为GMT呢?如果某些东西被转换为“当前”时区,它仍然是正确的。

鉴于这是有记录的行为,人们应该避免使用此类函数,或者针对此类行为进行防御性编码,那么您需要支持这两种方法的机制。对于这样的事情,我建议写一本《穷人的皮棉》;有了这样一个皮棉探测器,你就可以恢复理智了。此外,除了皮棉探测,有几种方法可以避免火星极地轨道器坠毁,有些相互独立,有些则相互依赖:

  • 设置策略和构建备选方案首先,对于您知道会导致问题的所有函数,要么决定不使用它们,要么编写一个新的包装函数,该函数将按照预期的方式运行,并设置您想要的时区参数。然后,确保使用该特殊包装器,而不是底层函数
  • 静态分析使用您最喜欢的编辑器(例如宏)编写搜索函数,使用shell脚本&GNU
    find
    grep
    函数,或以其他方式(例如R中的
    grep
    )查找导致您出现问题的特定函数。找到后,移除或使用防御编码方法(例如#1中的包装器)
  • 测试使用单元测试,例如
    Runit
    testthat
    ,开发测试,确保在使用函数或包时维护时区属性。每次出现新的bug时,创建一个新的测试,以确保bug不会再次出现在发布的版本中
  • 弱类型检查您还可以在代码中包括测试是否指定了时区的测试。最好有自己的函数来完成这个测试,而不是编写一个代码块来复制整个测试。通过这种方式,您最终可以将检查扩展到包括其他类型的检查,例如时区的持久性和测试两个或多个对象上的操作是否注意到时区的差异(可能它们允许,可能它们不允许)
  • 将所有内容映射到一个TZ也称为。保留关于时区的各种策略是一项艰巨的工作,本质上是处理时态数据时的摩擦。只需映射到一个TZ(UTC),然后让任何本地工作。如果您碰巧具有DST不变的局部规则性,则在从UTC转换回后解决该问题

  • 我为其他问题做了所有的#s 1-4,但是,正如它们很容易适应时区检查一样,它们对于许多火星轨道器目标来说是相当可重复使用的。我这样做正是为了避免对下一个这样的火星轨道器进行编码。(这对我们所有使用数字数据的人来说都是一个昂贵的教训。:)

    我认为我的漫游车实际上处于危险之中-因为我在观察事件发生的时间(例如,通过执行
    x-floor\u date(x,'day')
    ),如果时区被悄悄地移除,这些数字最终都是错误的。再举一个例子:
    strftime(unlist(list(y)),format=“%y/%m/%d%H:%m:%S”,tz=“PST8PDT”)
    as.POSIXlt.numeric(x,tz=tz)中的错误:“origin”必须提供简而言之,我确实理解这是有文档记录的行为,我只是认为它非常容易出错,不太可能真的有用。如果我想转换为本地时间,我不会只调用
    c()
    ,我会让我的代码更明确。@KenWilliams我的理解不是
    c
    将时间转换为本地时间。是的,它会删除原始的
    tz
    ,但实际时间保持不变。实际情况是,在以后的计算中会隐式转换为本地时间。如果你以后想知道当地时间是什么,而你不再有tz的记录,我可以看出这将如何导致簿记问题。很抱歉,我想不出一个简单的解决方法。正确-更准确地说,
    c
    删除任何时区属性,然后,其他各种函数将根据我的环境选择默认时区。相对于格林尼治标准时间的瞬间保持不变,但一天中的时间会发生变化。是的,我正在考虑这样做。但这并不是说我只处理来自一个时区的数据,我也不喜欢我的环境对我的数据进行的这种“远距离操作”。你可以在相关会话(脚本)中使用
    Sys.setenv(TZ=“GMT”)
    在R中设置它,另请参见