0

Consider this simple example

DT <- data.table::data.table(mytime =  c(nanotime('2011-12-05 08:30:00.000',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT"),
                         nanotime('2011-12-05 08:30:00.100',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT"),
                         nanotime('2011-12-05 08:30:00.825',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT")))
#convert the timestamp to string
DT[, mytime_character := strftime(mytime, format = '%Y-%m-%d %H:%M:%OS3')]

> DT
                                mytime        mytime_character
1: 2011-12-05T08:30:00.000000000+00:00 2011-12-05 03:30:00.000
2: 2011-12-05T08:30:00.100000000+00:00 2011-12-05 03:30:00.099
3: 2011-12-05T08:30:00.825000000+00:00 2011-12-05 03:30:00.825

As you can see, converting the nanotime timestamp to character (using strftime) creates a wrong millisecond part for the second timestamp: .099 instead of .100

Unfortunately, I need to convert my timestamps to string so that they can be ingested by other programming languages.

Is there a way to convert the timestamps properly to character without precision loss?

Thanks!

ℕʘʘḆḽḘ
  • 18,566
  • 34
  • 128
  • 235

2 Answers2

8

You are having an elementary misunderstanding here.

We use nanotime because the standard time formats in R only have (not-quite) microsecond resolution. So you, by using strftime() on it, are doing it wrong.

But nanotime, being a proper package, of course has a format() method:

R> DT <- data.table::data.table(mt = c(nanotime('2011-12-05 08:30:00.000',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT"),
+                                      nanotime('2011-12-05 08:30:00.100',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT"),
+                                      nanotime('2011-12-05 08:30:00.825',format ="%Y-%m-%d %H:%M:%E9S",  tz ="GMT")))
R> 
R> DT[, fmt := format(mt)]
R> DT[]
                                    mt                                 fmt
1: 2011-12-05T08:30:00.000000000+00:00 2011-12-05T08:30:00.000000000+00:00
2: 2011-12-05T08:30:00.100000000+00:00 2011-12-05T08:30:00.100000000+00:00
3: 2011-12-05T08:30:00.825000000+00:00 2011-12-05T08:30:00.825000000+00:00
R>
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • thanks Dirk again for your time. The reason I try to use `nanotime` is that it does not create rounding errors for timestamps like `'2011-12-05 08:30:00.100`. This does not happen in Pandas, for instance. My understanding is that `nanotime` manages that thanks to its microsecond precision, although I might be wrong. It would be nice to have functions to extract the other components (year, day, hour, minute, etc) from the nanotime timestamp without having to convert to posixct. Again, maybe I am foolish here. Thanks! – ℕʘʘḆḽḘ May 21 '19 at 19:20
  • 3
    @ℕʘʘḆḽḘ The point of Dirk's answer is that you should use the `format` method instead of converting to posixct. You want the year? `format(x, format = "%Y")`. You want the day? `format(x, format = "%d")`. No other functions are needed. You use `strftime`? You implicitly convert to posix and lose the advantages of nanotime. – Gregor Thomas May 21 '19 at 19:29
  • ha!!! I didnt get that! thanks for clarifying. this is pretty useful. Also, it does seem `nanotime` plays well with `tibbles` – ℕʘʘḆḽḘ May 21 '19 at 19:35
  • Not sure it does. First line of my first (ie in the other question) answer to you told you explicitly `data.table` does. It is what I use. If you read "use tibble" into that, you have a problem. Maybe `tibble` works, maybe it doesn't. Either way I (co-)wrote `nanotime` and I can assure you I do not use `tibble` with it. – Dirk Eddelbuettel May 21 '19 at 19:37
  • OK but when I print my tibble with a nanotime timestamp I get ` ` as the type. Isnt that what we want? Do you mean the computations will be affected if I use a tibble? I am asking this because making this wonderful package compatible with `tibbles` would be great (I use data.table or tibbles as needed) – ℕʘʘḆḽḘ May 21 '19 at 19:41
  • @DirkEddelbuettel that makes me hope its OK because in https://github.com/eddelbuettel/nanotime/issues/31 even the priting of the nanotime was impossible – ℕʘʘḆḽḘ May 21 '19 at 19:44
1

Maybe this works for you

DT[, mytime_character := format(mytime)]
DT %>% str()

> DT %>% str()
Classes ‘data.table’ and 'data.frame':  3 obs. of  2 variables:
 $ mytime          :integer64 1323073800000000000 1323073800100000000 1323073800825000000 
 $ mytime_character: chr  "2011-12-05T08:30:00.000000000+00:00" "2011-12-05T08:30:00.100000000+00:00" "2011-12-05T08:30:00.825000000+00:00"
 - attr(*, ".internal.selfref")=<externalptr> 
z-cool
  • 334
  • 1
  • 9