# [Rd] Floating Point with POSIXct

John Muschelli mu@che|||j2 @end|ng |rom gm@||@com
Thu Mar 3 17:04:05 CET 2022

```I see in ?POSIXct and I'm trying to understand the note:
> Classes "POSIXct" and "POSIXlt" are able to express fractions of a second. (Conversion of fractions between the two forms may not be exact, but will have better than microsecond accuracy.)

Mainly, I'm trying to understand printing of POSIXct with fractional
seconds.  I see print.POSIXct calls format.POSIXct and eventually
calls format.POSIXlt, which then takes into account `digits.secs` for
printing. The format uses %OS3, which strptime indicates (* added):

> Specific to R is %OSn, which for output gives the seconds *truncated* to 0 <= n <= 6 decimal places (and if %OS is not followed by a digit, it uses the setting of getOption("digits.secs"), or if that is unset, n = 0).

So I'm seeing it truncates the seconds to 3 digits, so I think that is
why the below is printing 0.024.

I think this is especially relevant even if you set
`options(digits.secs = 6)`, then the code in
format.POSIXlt would still return np=3 as the following condition
would break at i = 3

for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs,
i)) < 1e-06)) {
np <- i
break
}

as sub_seconds - round(sub_seconds,3) < 1e-06.   This seems to be
expected behavior given the docs, but would any consider this a bug?

Example:

options(digits.secs = 4)
x = structure(947016000.025, class = c("POSIXct", "POSIXt"), tzone = "UTC")
summary(x, digits = 20)
#>                      Min.                   1st Qu.                    Median
#> "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024"
#>                      Mean                   3rd Qu.                      Max.
#> "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024"
x
#> [1] "2000-01-04 20:00:00.024 UTC"
format.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS3")
#> [1] "2000-01-04 20:00:00.024"
format.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS4")
#> [1] "2000-01-04 20:00:00.0249"
sub_seconds = as.numeric(x) %% 1
sub_seconds
#> [1] 0.02499998
round(sub_seconds, 3)
#> [1] 0.025

rounded = as.POSIXct(
floor(as.numeric(x)) +
round(as.numeric(x) %% 1, 3),
origin = "1970-01-01")
rounded
#> [1] "2000-01-04 20:00:00.024 UTC"
as.numeric(rounded) %% 1
#> [1] 0.02499998

R.version
_
platform       x86_64-pc-linux-gnu
arch           x86_64
os             linux-gnu
system         x86_64, linux-gnu
status
major          4
minor          1.2
year           2021
month          11
day            01
svn rev        81115
language       R
version.string R version 4.1.2 (2021-11-01)
nickname       Bird Hippie

Best,
John

```