User:Daniel Gregoire/Unix Epoch and J Epoch

From J Wiki
Jump to navigation Jump to search

Today I was processing timestamps that were encoded as milliseconds since the Unix epoch, i.e., 1970-01-01. These were timestamps taken from java.util.Date objects using the getTime method.

I read the following on Vocabulary/Foreigns#m6:

Codes 14-17 convert between three representations of times: ISO 8601 timestamp, a list of bytes; nanosecond time, where the time is represented as a signed integer giving the offset in nanoseconds from the epoch, which is midnight on 2000/01/01; and digit time, where the time is represented as an integer whose digits are YYYYMMDDhhmmss. A time argument can be a single time or an array of times. The functions require 64-bit integers.

And I saw multiple mentions of nanoseconds in the rows of the table for codes 14–17, so I multiplied my timestamps by 1e6 but found myself confused until I read the above more closely.

J's foreigns expect nanoseconds since 2000-01-01, not 1970.

J Code

So I wrote these simple definitions to transform my Unix timestamps into J-compatible ones, and then gave a more memorable name to the foreign I wanted to use for debugging individual timestamp values:

NB. Shorten these names as you see fit.

millisToNanos=.*&1e6

millisBetween1970and2000=.946684799999
unixToJ=.millisToNanos@:(-&millisBetween1970and2000)
toIsoDt=.(6!:16)

unixToJ 1546355653000          NB. 599670853001000000
toIsoDt unixToJ 1546355653000  NB. 2019-01-01T15:14:13

With ISO-8601 date/times, I prefer having a timezone identifier on the end. As explained by User:Henry Rich in the forums, the date/time facilities only support appending a the timezone identifier Z, so we can provide that option as the left argument, or we can simply append it ourselves:

NB. Providing x to (6!:16)
'.Z0' toIsoDt unixToJ 1546355653000   NB. 2019-01-01T15:14:13Z
NB. Or just slapping a Z on the end:
'Z',~toIsoDt unixToJ 1546355653000    NB. 2019-01-01T15:14:13Z