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"再次感到困惑。
答案 0 :(得分:9)
这与R-FAQ 7.31有关,虽然它需要与平常不同的幌子。
您看到的行为来自以下各项的组合:(a)二进制计算机的(大多数)十进制值的不精确表示; (b)strftime
和strptime
的记录行为,即截断而不是舍入秒的小数部分,到指定的小数位数。
来自?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'。因为strptime
和strftime
截断而不是舍入到指定的小数位,如果小数位数设置为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
介绍了这一点