欧洲/莫斯科时区问题与strptime

时间:2014-05-14 12:50:54

标签: r timezone 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日发生了什么?

修改thisthis问题表明这可能是导致问题的夏令时。

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

1 个答案:

答案 0 :(得分:1)

在这种情况下,由于您对时间不感兴趣,但仅在您可以使用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"

您面临的错误(正如您已经注意到的)最有可能是由于夏令时:1984年俄罗斯的DST专门于4月1日开始(source)。 / p>

话虽如此,在运行R 2.14.2的Mac OSX 10.7.5上(有点过时),此错误无法重现:

> 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所做的更改之一修改了此行为。我目前正在改变日志中寻找它,但我还没有确切的证据。另一种可能性是它是特定于平台的。

此外,摘录自?strptime

  

请记住,在大多数时区中,某些时候不会发生,有些时候会发生   两次因为往返夏季的过渡。 strptime没有   验证这样的时间(它不假设特定的时区),但是   转换为as.POSIXct)将这样做。按strftime和。转换   格式化/打印使用操作系统设施,可能(并在Windows上)   在DST过渡时返回不存在时间的无意义结果。