From mu@che|||j2 @end|ng |rom gm@||@com  Thu Mar  3 17:04:05 2022
From: mu@che|||j2 @end|ng |rom gm@||@com (John Muschelli)
Date: Thu, 3 Mar 2022 11:04:05 -0500
Subject: [Rd] Floating Point with POSIXct
Message-ID: <CAFsq6G_cp=6pyh7CEe=rLUK47i+9LqtTyyK5zwjsdcNKnVigVg@mail.gmail.com>

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



[Rd] Floating Point with POSIXct
John Muschelli