Search code examples
rdatetimelubridatenanotime

how to extract year, tz-convert and get millisecond part from a nanotime timestamp?


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!


Solution

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