Short answer: Times are integers (think milliseconds).
q)(`hh`mm`ss $ .z.T), `int $ .z.T mod 1000 16 49 2 233 q)
You can extract the hours, minutes, and seconds from a time by passing `hh, `mm, and `ss, respectively, as left arguments to $ (cast):
q)now: .z.T q)now 16:49:02.233 q)`hh $ now 16 q)`mm $ now 49 q)`ss $ now 2 q)`hh`mm`ss $ now 16 49 2 q)
Getting the milliseconds from a time is slightly less obvious. Times (type -19) are represented internally by q as 32-bit integers; typically the value counts the number of milliseconds since midnight, but it can also represent a span of time. We can cast freely back and forth between the two types and the values are preserved:
q)`time $ 0 00:00:00.000 q)`int $ 00:00:00.000 0q)`time $ 24 * 60 * 60 * 1000 24:00:00.000 q)`int $ 24:00:00.000 86400000 q)`int $ now 60542233 q)`time $ 60542233 16:49:02.233 q)
Not only is the internal representation of time simply an integer, we can mix integers and times in integer arithmetic operations, and the result is always a time:
q)01:00:00.000 + 00:01:00.000 01:01:00.000 q)01:00:00.000 + 60000 01:01:00.000 q)01:00:00.000 * 4 04:00:00.000 q)now - 01:30:20.123 15:18:42.110 q)
q)now div 3600000 // milliseconds per hour 00:00:00.016 q)now mod 1000 // just the milliseconds, please 00:00:00.233 q)
Although extracting milliseconds from a time while keeping the time type (as in the second example above) is sometimes useful, we normally want to get back these components of a time as integers, so let’s cast it:
q)`int $ now mod 1000 233 q)
By the way, there is a shortcut for getting hours, minutes, and seconds from global variables that hold times: dot notation.
q)x: .z.T q)x.hh, x.mm, x.ss 16 49 2 q)
However, we rarely use global variables to hold time values.