0

I am using the amazing nanotime package to store my precious timestamps. Consider this:

    library(tibble)
    library(nanotime)

tibble(mytimestamp =  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"))) 
# A tibble: 3 x 1
  mytimestamp                        
  <S4: nanotime>                     
1 2011-12-05T08:30:00.000000000+00:00
2 2011-12-05T08:30:00.100000000+00:00
3 2011-12-05T08:30:00.825000000+00:00

However, I do not know what is the proper syntax to

  • extract the millisecond part from my timestamps
  • round to the closest second (like lubridate::floor_date(., '1 seconds'))
  • convert to a different timezone (say 'US/Eastern')

Do I have to use another package to do these things? For instance, using lubridate will lose the millisecond precision (note the .0999 instead of .100)

mydf %>% 
  mutate(lubritime = lubridate::as_datetime(mytimestamp))
# A tibble: 3 x 2
  mytimestamp                         lubritime                
  <S4: nanotime>                      <dttm>                   
1 2011-12-05T08:30:00.000000000+00:00 2011-12-05 08:30:00.00000
2 2011-12-05T08:30:00.100000000+00:00 2011-12-05 08:30:00.09999
3 2011-12-05T08:30:00.825000000+00:00 2011-12-05 08:30:00.82500

Similarly, directly converting to EST is not allowed

> mydf %>% 
+   mutate(mytimestamp_EST = lubridate::with_tz(mytimestamp, 'US/Eastern'))
Error in UseMethod("reclass_date", orig) : 
  no applicable method for 'reclass_date' applied to an object of class "c('nanotime', 'integer64', 'oldClass')"

Thanks!

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

1 Answers1

0

I do all of this with data.table because it is known that data.table supports the underlying bit64 package and integer64 representation that is needed here. Other containers do not.

Code

library(nanotime)
library(data.table)

DT <- data.table(ts =  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.700',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")))
DT[, pt := as.POSIXct(ts)]
DT[, millis := as.numeric(pt - trunc(pt)) * 1e3]

Result

R> DT
                                    ts                      pt millis
1: 2011-12-05T08:30:00.000000000+00:00 2011-12-05 02:30:00.000      0
2: 2011-12-05T08:30:00.700000000+00:00 2011-12-05 02:30:00.700    700
3: 2011-12-05T08:30:00.825000000+00:00 2011-12-05 02:30:00.825    825
R> 

Timezone shifts are a different (and misunderstood) topic. You can do it to POSIXct.

Note that all you have done here / asked for here was the millisecond resolution. So far no need was demonstrated for nanotime. But what I showed you can work on nanoseconds -- I use it every day from data.table.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • thanks! What I like is that the printing of the timestamps is correct. Please see my edited question (the 100 millisecond timestamp prints correctly with nanotime but not with lubridate). So what you recommend for shifting time zones is to convert to `POSIXct` and then do the conversion? – ℕʘʘḆḽḘ May 21 '19 at 14:56
  • Formatted content should not be confused with stored content. When `data.table` prints nanotime it uses UTC by default. Unless told otherwise the UTC time because local in POSIXct -- Central for me. None of that has anything to do with `nanotime` and is standard R behaviour. – Dirk Eddelbuettel May 21 '19 at 14:59
  • thanks and sorry if I am still a bit confused. Let say I want to convert the UTC nanotime to EST (in a different column of the data.table). How can I do that? – ℕʘʘḆḽḘ May 21 '19 at 15:06
  • 1
    There is no such thing as "converting". An UTC timestamp is an absolute record. You can _format_ it to _character_ given a timezome attribute. You can also _shift_ from one TZ to another (see by `RcppCCTZ` package used by `nanotime`). – Dirk Eddelbuettel May 21 '19 at 15:28
  • thanks for the clarification again. Yes, I am interested in format the timestamp into a character with a different timezone attribute. Regarding the timeshift, running `mydf %>% mutate(other = toTz(mytimestamp, 'UTC','US/Eastern', verbose = TRUE))` creates come crazy output that I think is related to the container issue you mentioned. Is that right? thanks again!! so useful – ℕʘʘḆḽḘ May 21 '19 at 15:49
  • regarding the first point, I have tried to use `mydf %>% mutate(other = strftime(mytimestamp))` but this (for `2011-12-05T08:30:00.100000000+00:00`) returns the character `2011-12-05 03:30:00.099` with the wrong millisecond part?! Do you see an easy solution here? Thanks for making all this clear for everyone. – ℕʘʘḆḽḘ May 21 '19 at 16:55
  • Perhaps this is worth another question. I accept this and create a new one – ℕʘʘḆḽḘ May 21 '19 at 17:58