In testing I have noted that this issue still exists for 32bit R 3.01 and that this is due to a truncation of floating point data that is specific to the 32bit implementation of print, format and as.character operators for POSIXlt date times.
The underlying data hasn't been stored in a different type that is leading to the truncation in one case (32bit) and not the other (64bit), but the "print", "format" and "as.character" functions for the POSIXlt type specifically which are used to display the POSIXlt data as a displayable string.
Whilst the documented behaviour is that these functions truncate (ignore) extra digits (as mentioned by @Gavin Simpson), this is not true in the same way for 32 and 64 bit versions. To demonstrate; we'll generate 1000 different times and perform some comparisons operations:
> options(digits.sec=3)
> x = as.POSIXlt("13:29:56.061", format='%H:%M:%OS', tz='UTC')
> for (i in 0:999) {
> x[i+1] = as.POSIXlt(paste0("13:29:56.",sprintf("%03d",i)),format='%H:%M:%OS',tz='UTC')
> }
> sum(x[2:1000]>x[1:999])
[1] 999
Under both 32 bit and 64 bit the comparison operators are consistent, however under 32 bit I see:
> x[1:6]
[1] "2015-10-16 13:29:56.000 UTC" "2015-10-16 13:29:56.000 UTC"
[3] "2015-10-16 13:29:56.002 UTC" "2015-10-16 13:29:56.003 UTC"
[5] "2015-10-16 13:29:56.003 UTC" "2015-10-16 13:29:56.005 UTC"
So it is clearly a display issue. Looking at the actual numbers in the POSIXlt datatype, particularly the seconds we can see what appears to happen:
> y = (x[1:6]$sec)
> y
[1] 56.000 56.001 56.002 56.003 56.004 56.005
> trunc(y*1000)/1000
[1] 56.000 56.001 56.002 56.003 56.004 56.005
> trunc((y-floor(y))*1000)/1000
[1] 0.000 0.000 0.002 0.003 0.003 0.005
I would suggest that this is a bug that should be fixed in the underlying base library, as a temporary fix though, you can overwrite the "print", "as.character" and "format" functions to change the output to your desired output e.g.
format.POSIXlt = function(posix) {
return(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)))
}
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)))
}
as.character.POSIXlt = function(posix) {
return(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)))
}