[Rd] as.character.POSIXt in R devel

Suharto Anggono Suharto Anggono @uh@rto_@nggono @end|ng |rom y@hoo@com
Thu Oct 6 12:20:38 CEST 2022


In 'as.character.POSIXt' in R devel after r83010:
            if(getOption("OutDec") != OutDec) { op <- options(OutDec = OutDec); on.exit(op) }

on.exit(op)
does nothing. It should be
on.exit(options(op))


Is it OK to output the seconds using scientific notation?
Example (modified from https://bugs.r-project.org/show_bug.cgi?id=9819):
op <- options(scipen = 0) # (default setting)
as.character(as.POSIXlt("2007-07-27 16:11:00.000002"))
# "2007-07-27 16:11:02e-06"
options(op)


Example (modified from https://bugs.r-project.org/show_bug.cgi?id=14579):
op <- options(scipen = 0) # (default setting)
ct <- as.POSIXct(1302811200 - 2e-07,
origin = as.POSIXct("1970-01-01 00:00:00", tz="UTC"), tz = "UTC")
as.character(ct) # outputs "60" for seconds
# "2011-04-14 19:59:60"
options(op)


(CharleMagne.crowned <- as.POSIXlt(ISOdate(774,7,10)))
as.character(CharleMagne.crowned)

As I mentioned, they are different on OSes _other than_ Linux.

In R on Windows:
> (CharleMagne.crowned <- as.POSIXlt(ISOdate(774,7,10)))
[1] "0774-07-10 12:00:00 GMT"


-----------------------
On Monday, 3 October 2022, 11:58:53 pm GMT+7, Martin Maechler <maechler using stat.math.ethz.ch> wrote:


>>>>> Martin Maechler
>>>>>    on Mon, 3 Oct 2022 14:46:08 +0200 writes:

>>>>> Suharto Anggono Suharto Anggono via R-devel
>>>>>    on Sun, 2 Oct 2022 08:42:50 +0000 (UTC) writes:

    >> With r82904, 'as.character.POSIXt' in R devel is changed. The NEWS item:

    >> as.character(<POSIXt>) now behaves more in line with the
    >> methods for atomic vectors such as numbers, and is no longer
    >> influenced by options().

[..............]

    >> * Wrong:

    >> The result is wrong when as.character(fs[n0]) has scientific notation.

    > yes, you are right.  This is a lapsus I will fix.

    >> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=9819):
    >> op <- options(scipen = 0, OutDec = ".") # (default setting)
    >> x <- as.POSIXlt("2007-07-27 16:11:03.000002")
    >> as.character(x)
    >> # "2007-07-27 16:11:03.99999999983547e-06"
    >> as.character(x$sec - trunc(x$sec))
    >> # "1.99999999983547e-06"
    >> options(op)

    >> 'as.character.POSIXt' could temporarily set option 'scipen' large enough to prevent scientific notation in as.character(fs[n0]) .

    > Yes, something like that.

I have committed a version now of datetime.R,  svn rev 83010 ,
which does no longer depend on  'OutDec' (but gets such argument)
and which has a new 'digits' argument which defaults
to 14 for POSIXlt and
to  6 for POSIXct  .. but the user can choose a different value.

Also, it now uses the equivalent of  as.character(round(x$sec, digits))
(in case the seconds need to be shown)  which also solves the
following  "too much precision"  problem.

    >> * Too much precision:

    >> In some cases with fractional seconds with seconds close to 60, the result has many decimal places while there is an accurate representation with less decimal places. It is actually OK, just unpleasant.

    > I agree that is unpleasant.
    > To someone else I had written that we also may need to improve
    > the number of decimals shown here.
    > The design has been that it should be "full precision"
    > as it is for  as.character(<numbers>)

    > Now, we know that POSIXct cannot be very precise (in its
    > fractional seconds) but that is very different for POSIXlt where
    > fractional seconds may have 14 digits after the decimal point.

    > Ideally we could *store* with the POSIXlt object if it was
    > produced from a POSIXct one, and hence have only around 6 valid digits
    > (after the dec.) or not.  As we cannot currently store/save that
    > info, we kept using "full" precision which may be much more than
    > is sensible.

    >> Example (modified from https://bugs.r-project.org/show_bug.cgi?id=14693):
    >> op <- options(scipen = 0, OutDec = ".") # (default setting)
    >> x <- as.POSIXlt("2011-10-01 12:34:56.3")
    >> x$sec == 56.3 # TRUE

    > [which may be typical, but may also be platform dependent]

    >> print(x$sec, 17)
    >> # [1] 56.299999999999997
    >> as.character(x)
    >> # "2011-10-01 12:34:56.299999999999997"
    >> format(x, "%Y-%m-%d %H:%M:%OS1") # short and accurate
    >> # "2011-10-01 12:34:56.3"
    >> ct <- as.POSIXct(x, tz = "UTC")
    >> identical(ct,
    >> as.POSIXct("2011-10-01 12:34:56.3", tz = "UTC"))
    >> # TRUE
    >> print(as.numeric(ct), 17)
    >> # [1] 1317472496.3
    >> lct <- as.POSIXlt(ct)
    >> lct$sec == 56.3 # FALSE
    >> print(lct$sec, 17)
    >> # [1] 56.299999952316284
    >> as.character(ct)
    >> # "2011-10-01 12:34:56.299999952316284"
    >> options(op)

    >> The "POSIXct" case is a little different because some precision is already lost after converted to "POSIXct".

    > yes, indeed.

    >> In 'as.character.POSIXt', using 'as.character' on the seconds (not separating the fractional part) might be good enough, but a leading zero must be added as necessary.

    > I think you are right: that may definitely better...

indeed; part of my commit.

    >> * Different from 'format':

    >> - With fractional seconds, the result is influenced by option 'OutDec'.

this has been solved, too.
For the "freaks" allowing an explicit  'OutDec = *' argument
but *not* with default depending on options()!


    > Thank you.  I was not aware of that.
    > The reason "of course" being that  as.character(<numeric>)  is
    > *also* depending on option  OutDec.

    > I would say that is clearly wrong...  and I think we should
    > strongl consider to change that:

    > 'OutDec' should influence print()ing and format()ing  but should
    > *not* influence  as.character()  at least not for basic R types/objects.


    >> - From "Printing years" in ?strptime: "For years 0 to 999 most OSes pad with zeros or spaces to 4 characters, and Linux outputs just the number."
    >> Because (1900 + x$year) is formatted with %d in 'as.character.POSIXt', years 0 to 999 is output without padding. It is different from 'format' in OSes other than Linux.

    > Good point.  This should be  amended.

Not yet.  Actually, I'm no longer sure this needs any action.
I find it somewhat natural that

> (CharleMagne.crowned <- as.POSIXlt(ISOdate(774,7,10)))
[1] "774-07-10 12:00:00 GMT"
> as.character(CharleMagne.crowned)
[1] "774-07-10 12:00:00"


[snip]



More information about the R-devel mailing list