在R中调用strptime时毫秒难题

时间:2012-01-17 04:13:47

标签: r strptime

options(digits.secs = 3);

> strptime("2007-03-30 15:00:00.007", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.007"
> strptime("2007-03-30 15:00:00.008", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.008"
> strptime("2007-03-30 15:00:00.009", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.008"
> strptime("2007-03-30 15:00:00.010", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.01"
> strptime("2007-03-30 15:00:00.011", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.010"
> strptime("2007-03-30 15:00:00.999", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:00.998"

我很困惑为什么与" 009"之间存在一毫秒的差异,然后又从" 011"再次感到困惑。

2 个答案:

答案 0 :(得分:9)

这与R-FAQ 7.31有关,虽然它需要与平常不同的幌子。

您看到的行为来自以下各项的组合:(a)二进制计算机的(大多数)十进制值的不精确表示; (b)strftimestrptime的记录行为,即截断而不是舍入秒的小数部分,到指定的小数位数。

来自?strptime帮助文件(关键字是'截断'):

  

R的特定是'%OSn',输出给出秒        截断为'0< = n< = 6'小数位(如果'%OS'不是        后跟一个数字,它使用的设置        'getOption(" digits.secs")',或者如果未设置,'n = 3')。

一个例子可能比进一步解释更有效地说明了什么:

strftime('2011-10-11 07:49:36.3', format="%Y-%m-%d %H:%M:%OS6")
[1] "2011-10-11 07:49:36.299999"

strptime('2012-01-16 12:00:00.3', format="%Y-%m-%d %H:%M:%OS1")
[1] "2012-01-16 12:00:00.2"

在上面的示例中,小数' .3'必须最好用二进制数近似,该二进制数略小于' 0.300000000000000000' - 类似于' 0.29999999999999999'。因为strptimestrftime截断而不是舍入到指定的小数位,如果小数位数设置为1,则0.3将转换为0.2。同样的逻辑适用于您的示例时间,其中一半表现出这种行为,就像(平均)预期的那样。

答案 1 :(得分:3)

我知道它已被“回答”但是32位R仍然存在这个问题,32位和64位版本之间的实现存在不一致。截断问题部分正确,但它不是strptime函数的结果,而是在这种特殊情况下的print.POSIXlt方法。

这可以通过用产生预期行为的函数覆盖函数来证明。 E.g。

print.POSIXlt = function(posix) {
    print(paste0(posix$year+1900,"-",sprintf("%02d",posix$mon+1),"-",sprintf("%02d",posix$mday)," ",
       sprintf("%02d",posix$hour),":",sprintf("%02d",posix$min),":",sprintf("%002.003f",posix$sec)))
    }

现在时间按预期显示:

> strptime("2007-03-30 15:00:00.009", format = "%Y-%m-%d %H:%M:%OS");
[1] "2007-03-30 15:00:0.009"

有关详细信息,我在此处R issue with rounding milliseconds

介绍了这一点