防范意外的时区转换
在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时刻如果发生这种情况时,我最不希望它带走。任何人有任何确保他们的日期“保持放置”的策略?
为什么不把你的时区设置为你的R会话的GMT?如果有东西被转换为“当前”时区,它仍然是正确的。
这种行为记录在?c
,?DateTimeClasses
和?unlist
:
从?DateTimeClasses
:
的 “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"
如果您使用R来跟踪日期,则您的Mars Rover应该可以。
我认为我的漫游车实际上处于危险之中 - 因为我正在看事情发生的时间(通过“例如,x-floor_date(x,'day')'),并且如果时区被无声删除,则这些数字最终会出错。 –
再举一个例子:'strftime(unlist(list(y)),format =“%Y /%m /%d%H:%M:%S”,tz =“PST8PDT”) as.POSIXlt .numeric(x,tz = tz):必须提供'origin' –
总之,我明白这是记录的行为,我只是认为它非常容易出错,不太可能真的有帮助。如果我想转换到本地时间,我不会只调用'c()',我会让我的代码更加明确。 –
鉴于这是记录的行为和你要么避免这样的功能,或者身边有这样的行为防守的代码,那么你需要机制来支持这两种方法。对于这样的事情,我会建议写一个“穷人的皮棉”;这样的皮棉检测仪,你可以去恢复理智此外,皮棉的检测,有几种方法,以避免火星极地轨道器崩溃,有些是相互独立的,其他依赖:
- 设置策略&构建替代首先,对于所有的,你知道的功能导致您的问题,无论是决定你会不会使用它们,或者写一个新的包装函数按预期的行为,这将设置你想要的时区参数。然后,确保您使用该特殊包装而不是基础功能。
-
静态分析使用您喜欢的编辑器(如宏),写一个搜索功能使用shell脚本&的GNU
find
和grep
功能,或以其他方式(如R中grep
),找到那些特别导致你问题的功能。找到时,请移除或使用防御性编码方法(例如#1中的包装)。 -
测试使用单元测试,例如,
Runit
或testthat
,开发测试以确保在使用您的函数或包时保持时区属性。每次出现新错误时,请创建一个新测试以确保该错误不会再次出现在已发布的版本中。 - 弱类型检查您还可以在代码中包含测试是否指定时区的测试。最好有这个测试的自己的功能,而不是写一个代码块在整个复制。通过这种方式,您最终可以扩展检查以包含其他类型的检查,例如时区的持久性以及测试两个或多个对象的操作是否注意时区中的差异(可能它们允许,也许它们不)。
- 将所有内容都映射到一个TZ也被称为Indiana-be-damned。保留关于时区的各种政策是艰巨的工作,并且在处理时态数据方面本质上是摩擦。只需映射到一个TZ(UTC),然后让任何本地工作。如果您碰巧拥有DST不变的本地规则,那么在从UTC转换回来之后再解决该规则。
我做的所有其他问题#分别1-4的,但是,正如他们很容易适应时区的检查,他们对很多火星轨道,避免了目标相当重用。我这样做正是为了避免编写下一个这样的火星轨道器。 (对于我们所有人来说,这是一个昂贵的教训,使用数字数据:))
是的,我正在考虑这样做。但这并不像我只使用一个时区的数据,而且我不喜欢我的环境对我的数据的“远距离行动”。 –
你可以用'Sys.setenv(TZ =“GMT”)从R中的相关会话(脚本)中设置它' –