How R Formats Posixct With Fractional Seconds

How to format fractional seconds in POSIXct in r

Because Timestamp has a : between whole seconds and fractional seconds, and there isn't a time parsing string ("conversion specification", e.g. %Y) for fractions of seconds without the whole, you need to change the last : to a . so you can parse it with %OS. sub can take care of it, looking for

  • a colon :
  • followed by 3 digits \\d{3}, captured (...)
  • followed by the end of the line $,

and replacing it with

  • a period .
  • followed by the captured group.

Further, if you want to see the fractional seconds that it's parsing, you'll need to set the digits.secs option:

options(digits.secs = 3)
strptime(sub(':(\\d{3})$', '.\\1', fx$Timestamp), '%Y%m%d %H:%M:%OS')
# [1] "2007-03-13 07:01:04.762 EDT" "2007-03-13 07:01:07.608 EDT" "2007-03-13 07:01:08.700 EDT"
# [4] "2007-03-13 07:01:11.275 EDT" "2007-03-13 07:01:13.884 EDT" "2007-03-13 07:01:16.588 EDT"

Note that strptime inserts the local timezone (EDT for me at the moment), but you can set that to whatever you like (or whatever it should be for your data) with its tz argument.

Date-Time Conversion in R with fractional seconds

The basic idea is to convert your character string to a valid POSIX*t object, and then convert that to a numeric value:

## Set a couple of printing options
options(digits = 12)
options(digits.secs = 3)

## Convert from character to POSIXlt to numeric
(a <- strptime(t, format="%H:%M:%OS", tz="GMT"))
# [1] "2013-04-09 00:00:00.00 GMT" "2013-04-09 00:00:00.34 GMT"
(b <- as.numeric(a))
# [1] 1365465600.00 1365465600.34

Note that, when converting back from numeric to POSIX*t, there are floating point issues that can change how those objects are printed. (See here for more discussion of that issue.)

## It _looks_ like you've lost 1/100 second on the second time object
(c <- as.POSIXct(as.numeric(b), origin = "1970-01-01", tz="GMT"))
# [1] "2013-04-09 00:00:00.00 GMT" "2013-04-09 00:00:00.33 GMT"

## Here's a workaround for nicer printing.
as.POSIXct(as.numeric(b+1e-6), origin = "1970-01-01", tz="GMT")
# [1] "2013-04-09 00:00:00.00 GMT" "2013-04-09 00:00:00.34 GMT"

How to extract floating point second from POSIXct object in R?

From ?strftime the following is noted:

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).

Hence we can recover up to 6 decimal places, although there seems to be some change in this information:

> tm <- as.POSIXct("2017-07-10 09:03:32.26876", tz = "BRT")
> tm
[1] "2017-07-10 09:03:32.268 BRT"
> format(tm, "%OS5")
[1] "32.26875"
> format(tm, "%OS6")
[1] "32.268759"

POSIXct micro-seconds inconsistencies in R

This question has gone on far too long -- especially considering that the question itself links to the answer.

This is an output representation problem, and is well-known. Rounding time values has implications. You cannot just round the subsecond values without getting incorrect results in some cases.

The solution is here (as linked in the question): How R formats POSIXct with fractional seconds

Stealing directly from Aaron's excellent answer:

myformat.POSIXct <- function(x, digits=0) {
x2 <- round(unclass(x), digits)
attributes(x2) <- attributes(x)
x <- as.POSIXlt(x2)
x$sec <- round(x$sec, digits)
format.POSIXlt(x, paste("%Y-%m-%d %H:%M:%OS",digits,sep=""))
}

x <- as.POSIXct("2012-12-14 15:42:04.577895 EDT")

What you are attempting:

as.POSIXlt(as.POSIXct(sprintf("%s",(format(x, "%Y-%m-%d %H:%M:%OS6")))))$sec
## [1] 4.577894

Aaron's code:

myformat.POSIXct(x, 6)
## [1] "2012-12-14 15:42:04.577895"

One might think to use sprintf with a format string of %.06f to format the subsecond value, but this will fail if the value is slightly below an integer:

sprintf('%.06f', .9999999)
## [1] "1.000000"

Converting to a POSIXlt causes the proper rollover into seconds, minutes, etc., if the subsecond value is rounded up.

To show you that this is not a data problem:

y <- as.numeric(x)
y
## [1] 1355521324.5778949261
sprintf('%06f', y - floor(y))
## [1] "0.577895"

Formatting date in R with fractional seconds and AM/PM indicator

You probably need %I

From the document,

%I - Hours as decimal number (01–12).

and

%H -Hours as decimal number (00–23).

as.POSIXct("7/30/2009 9:18:35.000000 PM", format = "%m/%d/%Y %I:%M:%OS %p")
# [1] "2009-07-30 21:18:35 IST"

Reading in a time with fractional seconds and AM/PM

For fractional seconds use %OS format (it isn't well documented, but it is one of the examples in ?strptime). You should also remember to use %I (instead of %H) when combined with %p. Also, don't forget to set tz if needed.

as.POSIXct("2014/10/20 3:00:49.324 PM", format = "%Y/%m/%d %I:%M:%OS %p")
## "2014-10-20 15:00:49 IDT"


Related Topics



Leave a reply



Submit