防止意外的时区转换

时间:2011-10-05 18:03:02

标签: r timezone date

在R中,我有一堆我在GMT中测量的日期时间值。我一直遇到一些事故,其中一些功能或其他功能失去了我的价值观的时区,甚至失去了班级名称。即使是基本功能c()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

如果这种情况发生在我最不期望的时候,我觉得我的头发宽度远离真正的Mars Climate Orbiter时刻。任何人都有任何策略来确保他们的日期“保持”?

3 个答案:

答案 0 :(得分:6)

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

来自?DateTimeClasses

  

在“c”对象上使用POSIXlt会将其转换为当前时区,而“POSIXct”对象会删除所有“tzone”属性(即使他们都标有相同的时区)。*

来自?c

  

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


尽管如此,我的测试表明,尽管使用cunlist,数据的完整性仍然完好无损。例如:

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"

如果您使用R来跟踪日期,那么您的火星漫游者应该没问题。

答案 1 :(得分:4)

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

答案 2 :(得分:2)

鉴于这是记录在案的行为,并且要么应该避免这样的行为,要么就这些行为进行防御性编码,那么你需要机制来支持这两种方法。对于这样的事情,我建议写一个“穷人的棉绒”;有了这样的棉绒探测器,你就可以恢复理智了另外,对于lint探测,有几种方法可以避免火星极地轨道飞行器坠毁,有些是彼此独立的,有些依赖:

  1. 制定政策&amp;构建备选方案首先,对于您知道导致问题的所有函数,要么决定不使用它们,要么编写一个新的包装函数,它将按预期运行,并设置timezone参数你渴望。然后,确保使用该特殊包装而不是底层函数。
  2. 静态分析使用您喜欢的编辑器(例如作为宏)编写搜索功能,使用shell脚本&amp; GNU findgrep函数,或者以其他方式(例如R中的grep)来查找导致问题的特定函数。找到后,删除或使用防御性编码方法(例如#1中的包装器)。
  3. 测试使用单元测试,例如Runittestthat开发测试,确保在使用您的函数或包时保持时区属性。每次出现新错误时,都要创建一个新测试,以确保在发布的版本中不再出现错误。
  4. 弱类型检查您还可以在整个代码中包含测试,以测试是否指定了时区。最好有自己的功能进行此测试,而不是编写一整段代码。通过这种方式,您最终可以扩展检查以包括其他类型的检查,例如时区的持久性,以及测试两个或多个对象上的操作是否注意时区的差异(可能它们允许它,也许它们不会)。
  5. 将所有内容映射到一个TZ 也称为Indiana-be-damned。保留关于时区的各种政策是一项艰苦的工作,并且在处理时态数据方面基本上是摩擦。只需映射到一个TZ(UTC),然后让任何本地工作。如果您碰巧具有DST不变的本地规则性,那么在从UTC转换回来之后解决该问题。
  6. 我为#s 1-4做了其他所有问题,但是,正如它们很容易适应时区检查一样,它们可以很好地重复使用许多火星轨道飞行器避免目标。我这样做的确是为了避免编码下一个这样的火星轨道器。 (对于我们所有使用数字数据的人来说,这是一个昂贵的教训。:))