[Rd] Revisit c.POSIXlt , [<-.POSIXlt , [[<-.POSIXlt ?

Suharto Anggono Suharto Anggono @uh@rto_@nggono @end|ng |rom y@hoo@com
Tue Apr 7 12:34:46 CEST 2026


As I have proposed in Bug 18989 Comment 1 (https://bugs.r-project.org/show_bug.cgi?id=18989#c1), 'c.POSIXlt' in R devel and R 4.6.0 alpha currently tries to preserve sub-second accuracy by proceeding as usual and then replacing the fractional part of the 'sec' component with the "fractional part" of the 'sec' component (x$sec - floor(x$sec), or x$sec %% 1) of the original POSIXlt object.

However, as I have raised in Bug 18989 Comment 8 (https://bugs.r-project.org/show_bug.cgi?id=18989#c8), there are boundary cases, like
c(as.POSIXlt("9999-12-31 23:59:59.99999", tz="UTC")) ,
where the result is a full second ahead of the correct time, worse than not correcting the 'sec' component.

Because of the issue and with '[<-.POSIXlt' and '[[<-.POSIXlt' still using as.POSIXlt(as.POSIXct(*), tz = *) without correction, reverting to the original code is an option for 'c.POSIXlt' for R 4.6.0.

Alternatively, if the 'c.POSIXlt' feature is to be kept, I think the fixed I have proposed in Bug 18989 Comment 9 (https://bugs.r-project.org/show_bug.cgi?id=18989#c9), applying 'floor' to the 'sec' component before converting to POSIXct, is good enough. It can be wrong only in range where not all whole seconds can be represented by POSIXct ("double" type). Or fixing the issue should wait for a future release?

As I have raised in Bug 18919 Comment 9 (https://bugs.r-project.org/show_bug.cgi?id=18919#c9), an intriguing case for me with current '[<-.POSIXlt' in R devel and R 4.6.0 alpha is that subassigning a POSIXlt object with the same time zone can have different result to subassigning a POSIXlt object with the exact same time with different, but equivalent, time zone. For example,

x1 <- as.POSIXlt(.POSIXct(0, tz = "UTC"))
x1[1L] <- as.POSIXlt("2006-02-20 11:16:16.683", tz = "UTC")

versus

x1 <- as.POSIXlt(.POSIXct(0, tz = "UTC"))
x1[1L] <- as.POSIXlt("2006-02-20 11:16:16.683", tz = "GMT")

.

Because the branching condition in '[<-.POSIXlt' uses 'identical' on 'tzone' attributes, the case is not only like "UTC" versus "GMT" or "Etc/UTC". "Non-deterministic POSIXlt tzone in Europe/London around UTC 0" was a case (has been fixed). It can also be 3-element versus 1-element 'tzone' attribute. As noted in Description of Bug 19005 (https://bugs.r-project.org/show_bug.cgi?id=19005#c0), 'as.POSIXlt.character' produces 1-element 'tzone' attribute. Example:

x1 <- as.POSIXlt(.POSIXct(1e9, tz = "Europe/London"))
x1[1L] <- strptime("2006-02-20 11:16:16.683", "%Y-%m-%d %H:%M:%OS", tz = "Europe/London")

versus

x1 <- as.POSIXlt(.POSIXct(1e9, tz = "Europe/London"))
x1[1L] <- as.POSIXlt("2006-02-20 11:16:16.683", tz = "Europe/London")

The difference can be eliminated by removing branching and using as.POSIXlt(as.POSIXct(*), tz = *) in all cases. However, I expect subassignment to be precise. Using the subassigned object as is is more expected for me. Will the issue be tackled, maybe in a future release of R?

In '[<-.POSIXlt',
as.POSIXlt(as.POSIXct(*), tz = *)
is also applied when 'value' is not a POSIXlt object. I think
as.POSIXlt(*, tz = *)
could be used instead. Bug 18919 Comment 10 says that the behaviour was chosen to be consistent with 'c.POSIXlt', which seemed desirable. Does R Core agree? For character string, yes, 'Ops.POSIXt' also uses as.POSIXct(*), which interprets it as being in the current time zone.

Finally, I think the change of

as.POSIXlt(value)

to

if(inherits(value, "POSIXlt") && identical(tz, attr(value, "tzone")))
    value
else as.POSIXlt(as.POSIXct(value), tz = tz[1L]))

in '[<-.POSIXlt' and '[[<-.POSIXlt', which is the core of PR#18919, deserves a NEWS item mentioning time zone. For example,
In subassigning 'val' to a POSIXlt object 'x', x[i] <- val and x[[i]] <- val, now 'val' is converted to the time zone of 'x'.



More information about the R-devel mailing list