r语言 - 欧洲/莫斯科时区问题与strptime



我正在研究一个执行一些时间序列操作的软件。我最近发现了一个严重的问题在R脚本方面,我已经开发;意外行为被隔离在具有Europe/Moscow语言环境的特定机器上。问题归结为以下代码片段:

strange_days <- c("2/1/1984", "3/1/1984", "4/1/1984", "5/1/1984", "6/1/1984") 
Sys.setenv(TZ='Europe/Moscow')
d <- strptime(strange_days, '%m/%d/%Y')
d
[1] "1984-02-01 MSK" "1984-03-01 MSK" "1984-04-01"     "1984-05-01 MSD" "1984-06-01 MSD"

所有似乎都能被正确识别。我认为,由于这是日常数据,时区属性没有太大区别;痛苦的错误:

as.numeric(d)
[1] 444430800 446936400        NA 452203200 454881600

在转换为xts对象时明显失败。

当前的修复是通过strptime(strange_days, '%m/%d/%Y', tz='GMT')甚至Sys.setenv(TZ='GMT')强制所有时区为GMT;问题也随之消失了。

这是一个好的做法吗?代码在所有情况下都是可靠的吗?你会推荐什么技巧来避免类似的问题?

1984年4月1日发生了什么特别的事?

编辑:这个和这个问题表明这可能是夏令时导致的问题。

sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_United Kingdom.1252  LC_CTYPE=English_United Kingdom.1252    LC_MONETARY=English_United Kingdom.1252
[4] LC_NUMERIC=C                            LC_TIME=English_United Kingdom.1252    
attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
loaded via a namespace (and not attached):
[1] tools_3.1.0

编辑2:问题显然是windows特有的,而不是在linux上复制这些规格:

R version 3.1.0 (2014-04-10)
Platform: i686-pc-linux-gnu (32-bit)
locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
loaded via a namespace (and not attached):
[1] tools_3.1.0

在本例中,由于您对时间不感兴趣,而只对日期感兴趣,因此可以使用as.Date:

> as.Date(strange_days,"%m/%d/%Y")
[1] "1984-02-01" "1984-03-01" "1984-04-01" "1984-05-01" "1984-06-01"

你遇到的错误(正如你已经注意到的)很可能是由于夏令时:碰巧俄罗斯的DST在1984年特别开始于4月1日(来源)。

也就是说,在Mac OSX 10.7.5和R 2.14.2运行(是的,有点过时)这个错误是不可重复的:

> strange_days <- c("2/1/1984", "3/1/1984", "4/1/1984", "5/1/1984", "6/1/1984") 
> Sys.setenv(TZ='Europe/Moscow')
> d <- strptime(strange_days, '%m/%d/%Y')
> d
[1] "1984-02-01 MSK" "1984-03-01 MSK" "1984-04-01 MSD" "1984-05-01 MSD" "1984-06-01 MSD"
> as.numeric(d)
[1] 444430800 446936400 449611200 452203200 454881600

这表明在R版本2.14.2和3.1.0之间对strptime所做的一个更改修改了此行为。我目前正在Changelogs中寻找它,但我还没有明确的证据。另一种可能是它是特定于平台的。

此外,这里是?strptime的摘录:

请记住,在大多数时区中,有些时间不会发生,有些时间会发生两次是因为夏令时的转换。Strptime没有验证这些时间(它不假设特定的时区),但是转换为as.POSIXct)将会这样做。通过strftime和格式化/打印使用操作系统的功能和可能(在Windows上也是如此)

在DST转换时返回不存在时间的无意义结果。

相关内容

  • 没有找到相关文章

最新更新