Rappster
Rappster

Reputation: 13070

Ambiguity with 'POSIXlt' representation when microseconds are included

I'm puzzled by an ambiguity with respect to the representation/storage of micro-/milliseconds in class POSIXlt:

Printing the POSIXlt object shows different micro-/millisecond digits as a query of the respective attribute (last digit differs)

Maybe this makes perfect sense, but I find it kind of strange. Could someone explain this to me?

Microseconds

# Change digits for seconds >> microseconds
opts <- options(digits.secs=6)
x <- "2012-07-30 12:10:09.123123"

posix <- as.POSIXlt(x, tz="Europe/Berlin")

> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"

> posix$sec
[1] 9.123123

Milliseconds

posix$sec <- round(posix$sec, 3)

> posix
[1] "2012-07-30 12:10:09.122 Europe/Berlin"

> posix$sec
[1] 9.123

# Undo option change
options(opts)

Also, this doesn't really add to claritiy (at least for me ;-))

opts <- options(digits.secs=6)
x <- "2012-07-30 12:10:09.123123"
posix <- as.POSIXlt(x, tz="Europe/Berlin")

> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"
> posix$sec
[1] 9.123123

When manually manipulating the 'sec' attribute the result seems to vary; I still don't really see the systematic here, but adding an extra digit - preferably a 5 as pointed out by Aaaron - seems to get the desired result:

# Workaround: extra digit
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123123 Europe/Berlin"

posix$sec <- 9.123122
> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"

posix$sec <- 9.123124
> posix
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix 
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"

posix$sec <- 9.123125
> posix
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123125 Europe/Berlin"

posix$sec <- 9.123126
> posix
[1] "2012-07-30 12:10:09.123125 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123126 Europe/Berlin"

options(opts)

Session Info

R version 2.14.1 (2011-12-22)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

EDIT 2012-07-31

Thanks to Aaron I think I found a workaround that does the trick for me by simply adding an extra digit that's used internally for rounding to the next-off digit to the left.

Upvotes: 1

Views: 205

Answers (1)

Aaron - mostly inactive
Aaron - mostly inactive

Reputation: 37744

This is because R rounds down for display of times (just like a stopwatch would do). So when printing the entire time object, it rounds down. But when printing just part of it, it's no longer a time object, so standard rounding applies.

Floating-point representation makes this even more obvious as if a number is represented as 0.39999999999 (or whatever the binary equivalent would be) it will display as 0.3 even though within the floating-point tolerance, it's equal to 0.4.

To get usual rounding behavior add 0.0005 (to get three decimal places) before display.

See How R formats POSIXct with fractional seconds for more details.

Upvotes: 3

Related Questions