The .z
namespace¶
Environment and callbacks
Environment Callbacks .z.a IP address .z.bm msg validator .z.b view dependencies .z.exit action on exit .z.c cores .z.pc close .z.ex failed primitive .z.pd peach handles .z.ey arg to failed primitive .z.pg get .z.f file .z.pi input .z.h host .z.po open .z.i PID .z.pq qcon .z.K version .z.r blocked .z.k release date .z.ps set .z.l license .z.pw validate user .z.o OS version .z.ts timer .z.q quiet mode .z.vs value set .z.s self .z.u user ID Callbacks (HTTP) .z.X/x raw/parsed command line .z.ac HTTP auth .z.zd compression/encryption defaults .z.ph HTTP get .z.pm HTTP methods Environment (Connections) .z.pp HTTP post .z.e TLS connection status .z.H active sockets Callbacks (WebSockets) .z.W/w handles/handle .z.wc WebSocket close .z.wo WebSocket open Environment (Time/Date) .z.ws WebSockets .z.D/d date shortcuts .z.N/n local/UTC timespan .z.P/p local/UTC timestamp .z.T/t time shortcuts .z.Z/z local/UTC datetime
The .z
namespace contains environment variables and functions, and hooks for callbacks.
The .z
namespace is reserved for use by KX, as are all single-letter namespaces.
Consider all undocumented functions in the namespace as exposed infrastructure – and do not use them.
By default, callbacks are not defined in the session
After they have been assigned, you can restore the default using \x
to delete the definition that was made.
Callbacks,
Using .z
Q for Mortals:
§11.6 Interprocess Communication
.z.a
(IP address)¶
The IP address as a 32-bit integer
q).z.a
-1062731737i
It can be split into components as follows:
q)"i"$0x0 vs .z.a
127 0 0 1
Callbacks
When invoked inside a .z.p*
callback via a TCP/IP connection, it is the IP address of the client session, not the current session.
When invoked via a Unix Domain Socket, it is 0.
.z.ac
(HTTP auth)¶
.z.ac:(requestText;requestHeaderAsDictionary)
Lets you define custom code to authorize/authenticate an HTTP request. e.g. inspect HTTP headers representing oauth tokens, cookies, etc. Your custom code can then return different values based on what is discovered.
.z.ac
is a unary function, whose single parameter is a two-element list providing the request text and header.
If .z.ac is not defined, it uses basic access authentication as per (4;"")
below
The function should return a two-element list. The list of possible return values is:
- User not authorized/authenticated
User not authorized. Client is sent default 401 HTTP unauthorized response. An HTTP callback to handle the request will not be called.(0;"")
- User authorized/authenticated
The provided username is used to set(1;"username")
.z.u
. The relevant HTTP callback to handle this request will be allowed. - User not authorized/authenticated (custom response)
The custom response to be sent should be provided in the "response text" section. The response text should be comprised of a valid HTTP response message, for example a 401 response with a customised message. An HTTP callback to handle the original request is not called.(2;"response text")
- Fallback to basic authentication
Fallback to basic access authentication, where the username/password are base64 decoded and processed via the(4;"")
-u
/-U
file and.z.pw
(if defined). If the user is not permitted, the client is sent a default 401 HTTP unauthorized response. Since V4.0 2021.07.12.
.z.b
(view dependencies)¶
The dependency dictionary.
q)a::x+y
q)b::x+1
q).z.b
x| `a`b
y| ,`a
.z.bm
(msg validator)¶
.z.bm:x
Where x
is a unary function.
kdb+ before V2.7 was sensitive to being fed malformed data structures, sometimes resulting in a crash, but now validates incoming IPC messages to check that data structures are well formed, reporting 'badmsg
and disconnecting senders of malformed data structures. The raw message is captured for analysis via the callback .z.bm
. The sequence upon receiving such a message is
- calls
.z.bm
with a 2-item list:(handle;msgBytes)
- close the handle and call
.z.pc
- signals
'badmsg
E.g. with the callback defined
q).z.bm:{`msg set (.z.p;x);}
after a bad msg has been received, the global var msg
will contain the timestamp, the handle and the full message. Note that this check validates only the data structures, it cannot validate the data itself.
.z.c
(cores)¶
The number of physical cores.
.z.e
(TLS connection status)¶
TLS details used with a connection handle. Returns an empty dictionary if the connection is not TLS enabled. E.g. where h
is a connection handle.
q)h".z.e"
CIPHER | `AES128-GCM-SHA256
PROTOCOL| `TLSv1.2
CERT | `SUBJECT`ISSUER`SERIALNUMBER`NOTVALIDBEFORE`NOTVALIDAFTER`VERIFIED`VERIFYERROR!("/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=myname.com";"/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=examplebrooklyn.com";,"1";"Jul 6 10:08:57 2021 GMT";"May 15 10:08:57 2031 GMT";1b;0)
Since V3.4 2016.05.16. CERT
details of VERIFIED
,VERIFYERROR
available since 4.1t 2024.02.07.
.z.ex
(failed primitive)¶
In a debugger session, .z.ex
is set to the failed primitive.
Since V3.5 2017.03.15.
.z.ey
argument to failed primitive
.z.exit
(action on exit)¶
.z.exit:f
Where f
is a unary function, f
is called with the exit parameter as the argument just before exiting the kdb+ session.
The exit parameter is the argument to the exit
function, or 0 if manual exit with \\
quit
The handler cannot cancel the exit.
.z.exit
can be unset with \x .z.exit
, which restores the default behavior.
The default behavior is equivalent to setting .z.exit
to {}
, i.e. do nothing.
q).z.exit
'.z.exit
q).z.exit:{0N!x}
q)\\
0
os>..
q).z.exit:{0N!x}
q)exit 42
42
os>..
q).z.exit:{0N!x}
q)exit 0
0
os>..
If the exit behavior has an error (disk full for example if exit tries to save the current state), the session is suspended and exits after completion or manual exit from the suspension.
q).z.exit:{`thiswontwork+x}
q)\\
{`thiswontwork+x}
'type
+
`thiswontwork
0
q))x
0
q))'`up
'up
os>..
.z.ey
(argument to failed primitive)¶
In a debugger session, .z.ey
is set to the argument to failed primitive.
Since V3.5 2017.03.15.
.z.f
(file)¶
Name of the q script as a symbol.
$ q test.q
q).z.f
`test.q
.z.H
(active sockets)¶
Active sockets as a list (a low-cost method). Since v4.0 2020.06.01.
List has sorted attribute applied since v4.1 2024.07.08.
q).z.H~key .z.W
1b
.z.W
handles, .z.w
handle, -38!
socket table
.z.h
(host)¶
The host name as a symbol
q).z.h
`demo.kx.com
On Linux this should return the same as the shell command hostname
. If you require a fully qualified domain name, and the hostname
command returns a hostname only (with no domain name), this should be resolved by your system administrators. Often this can be traced to the ordering of entries in /etc/hosts
, e.g.
Non-working /etc/host
looks like :
127.0.0.1 localhost.localdomain localhost
192.168.1.1 myhost.mydomain.com myhost
Working one has this ordering :
127.0.0.1 localhost.localdomain localhost
192.168.1.1 myhost myhost.mydomain.com
One solution seems to be to flip around the entries, i.e. so the entries should be
ip hostname fqdn
A workaround from within kdb+ is
q).Q.host .z.a
.z.i
(PID)¶
The process ID as an integer.
q).z.i
23219
.z.K
(version)¶
The major version number, as a float, of the version of kdb+ being used. (A test version of 2.4t is reported as 2.4)
q).z.K
2.4
q).z.k
2006.10.30
.z.k
(release date)¶
Date on which the version of kdb+ being used was released.
q).z.k
2006.10.30
q)
This value is checked against .Q.k
as part of the startup to make sure that the executable and the version of q.k being used are compatible.
.z.l
(license)¶
License information as a list of strings; ()
for non-commercial 32-bit versions.
q)`maxCoresAllowed`expiryDate`updateDate`````bannerText`!.z.l
maxCoresAllowed| ""
expiryDate | "2021.05.27"
updateDate | "2021.05.27"
| ,"1"
| ,"1"
| ,"1"
| ,"0"
bannerText | "stephen@kx.com #59875"
| ,"0"
bannerText
is the custom text displayed at startup, and always contains the license number as the last token.
.z.N
(local timespan)¶
System local time as timespan in nanoseconds.
q).z.N
0D23:30:10.827156000
.z.n
UTC timespan, .z.P
local timestamp, .z.p
UTC timestamp, .z.Z
local datetime, .z.z
UTC datetime
.z.n
(UTC timespan)¶
System UTC time as timespan in nanoseconds.
q).z.n
0D23:30:10.827156000
Changes since 4.1t 2021.03.30,4.0 2022.07.01
Linux clock source returns a nanosecond precision timespan
.z.n
local timespan, .z.P
local timestamp, .z.p
UTC timestamp, .z.Z
local datetime, .z.z
UTC datetime
.z.o
(OS version)¶
kdb+ operating system version as a symbol.
q).z.o
`w32
Values for V3.5+ are shown below in bold type.
os | 32-bit | 64-bit |
---|---|---|
Linux | l32 | l64 |
Linux on ARM | l64 (reports l64arm since 4.1t 2022.09.02) | |
macOS | m32 | m64 |
Solaris | s32 | s64 |
Solaris on Intel | v32 | v64 |
Windows | w32 | w64 |
Note this is the version of the kdb+ executable, NOT the OS itself. You might run both 32-bit and 64-bit versions of kdb+ on the same machine to support older external interfaces.
.z.P
(local timestamp)¶
System localtime timestamp in nanoseconds.
q).z.P
2018.04.30D10:18:31.932126000
.z.p
UTC timestamp, .z.N
local timespan, .z.n
UTC timespan, .z.Z
local datetime, .z.z
UTC datetime
.z.p
(UTC timestamp)¶
UTC timestamp in nanoseconds.
q).z.p
2018.04.30D09:18:38.117667000
Changes since 4.1t 2021.03.30,4.0 2022.07.01
Linux clock source returns a nanosecond precision timestamp
.z.P
local timestamp, .z.N
local timespan, .z.n
UTC timespan, .z.Z
local datetime, .z.z
UTC datetime
.z.pc
(close)¶
.z.pc:f
Where f
is a unary function, .z.pc
is called after a connection has been closed.
As the connection has been closed by the time f
is called there are strictly no remote values that can be put into .z.a
, .z.u
or .z.w
– so the local values are returned.
To allow you to clean up things like tables of users keyed by handle, the handle that was being used is passed as a parameter to .z.pc
KDB+ 2.3 2007.03.27 Copyright (C) 1993-2007 Kx Systems
l64/ 8cpu 16026MB simon ...
q).z.pc
'.z.pc
q).z.pc:{0N!(.z.a;.z.u;.z.w;x);x}
q)\p 2021
q)(2130706433;`simon;0;4)
q).z.a
2130706433
q).z.u
`simon
q).z.w
0
q)
.z.pc
is not called by hclose
.
.z.pd
(peach handles)¶
.z.pd: x
Where q has been started with secondary processes for use in parallel processing, x
is
- an int vector of handles to secondary processes
- a function that returns a list of handles to those secondary processes
For evaluating the function passed to peach
or ':
, kdb+ gets the handles to the secondary processes by calling .z.pd[]
.
The processes with these handles must not be used for other messaging.
Each Parallel will close them if it receives anything other than a response message.
q)/open connections to 4 processes on the localhost
q).z.pd:`u#hopen each 20000+til 4
The int vector (returned by) x
must have the unique attribute set.
A more comprehensive setup might be
q).z.pd:{n:abs system"s";$[n=count handles;handles;[hclose each handles;:handles::`u#hopen each 20000+til n]]}
q).z.pc:{handles::`u#handles except x;}
q)handles:`u#`int$();
Note that (since V3.1) the worker processes are not started automatically by kdb+.
Disabled in V4.1t
Using handles within peach is not supported e.g.
q)H:hopen each 4#4000;{x""}peach H
3 4 5 6i
One-shot IPC requests can be used within peach
instead.
.z.pg
(get)¶
.z.pg:f
Where f
is a unary function, called with the object that is passed to the q session via a synchronous request. The return value, if any, is returned to the calling task.
.z.pg
can be unset with \x .z.pg
, which restores the default behavior.
The default behavior is equivalent to setting .z.pg
to value
and executes in the root context.
.z.ph
(HTTP get)¶
.z.ph:f
Where f
is a unary function, it is evaluated when a synchronous HTTP request is received by the kdb+ session.
.z.ph
is passed a single argument, a 2-item list (requestText;requestHeaderAsDictionary)
:
requestText
is parsed in.z.ph
– detecting special cases like requests for CSV, XLS output – and the result is returned to the calling task.requestHeaderAsDictionary
contains a dictionary of HTTP header names and values as sent by the client. This can be used to return content optimized for particular browsers.
The function returns a string representation of an HTTP response message e.g. HTTP/1.1 response message format.
Since V3.6 and V3.5 2019.11.13, the default implementation calls .h.val
instead of value
, allowing users to interpose their own valuation code. It is called with requestText
as the argument.
.z.pp
HTTP post, .z.pm
HTTP methods, .z.ac
HTTP auth
.h
namespace
HTTP
Q for Mortals
§11.7.1 HTTP Connections
.z.pi
(input)¶
.z.pi:f
Where f
is a unary function, it is evaluated as the default handler for input.
As this is called on every line of input it can be used to log all console input, or even to modify the output. For example, if you prefer the more compact V2.3 way of formatting tables, you can reset the output handler.
q)aa:([]a:1 2 3;b:11 22 33)
q)aa
a b
----
1 11
2 22
3 33
q).z.pi:{0N!value x;}
q)aa
+`a`b!(1 2 3;11 22 33)
q)
To return to the default display, just delete your custom handler
q)\x .z.pi
.z.pm
(HTTP methods)¶
.z.pm:f
Where f is a unary function, .z.pm is evaluated when the following HTTP request methods are received in the kdb+ session.
- OPTIONS
- PATCH (since V4.1t 2021.03.30)
- PUT (since V4.1t 2021.03.30)
- DELETE (since V4.1t 2021.03.30)
Each method is passed to f
as a 3-item list e.g.
(`OPTIONS;requestText;requestHeaderDict)
For the POST method use .z.pp, and for GET use .z.ph.
.z.ph
HTTP get, .z.pp
HTTP post, .z.ac
HTTP auth
HTTP
.z.po
(open)¶
.z.po:f
Where f
is a unary function, .z.po
is evaluated when a connection to a kdb+ session has been initialized, i.e. after it’s been validated against any -u
/-U
file and .z.pw
checks.
Its argument is the handle and is typically used to build a dictionary of handles to session information like the value of .z.a
, .z.u
.z.pc
port close,
.z.pw
validate user
Q for Mortals
§11.6 Interprocess Communication
.z.pp
(HTTP post)¶
.z.pp:f
Where f
is a unary function, .z.pp
is evaluated when an HTTP POST request is received in the kdb+ session.
There is no default implementation, but an example would be that it calls value
on the first item of its argument and returns the result to the calling task.
See .z.ph
for details of the argument and return value.
Allows empty requests since 4.1t 2021.03.30 (previously signalled length
error).
.z.ph
HTTP get, .z.pm
HTTP methods, .z.ac
HTTP auth
.h
namespace
HTTP
Q for Mortals
§11.7.1 HTTP Connections
.z.pq
(qcon)¶
.z.pq:f
Remote connections using the ‘qcon’ text protocol are routed to .z.pq
, which defaults to calling .z.pi
. (Since V3.5+3.6 2019.01.31.)
This allows a user to handle remote qcon connections (via .z.pq
) without defining special handling for console processing (via .z.pi
).
Firewalling for locking down message handlers
.z.ps
(set)¶
.z.ps:f
Where f
is a unary function, .z.ps
is evaluated with the object that is passed to this kdb+ session via an asynchronous request. The return value is discarded.
.z.ps
can be unset with \x .z.ps
, which restores the default behavior.
The default behavior is equivalent to setting .z.ps
to value
.
Note that .z.ps
is used in preference to .z.pg
when messages are sent to the local process using handle 0.
q).z.ps:{[x]0N!(`zps;x);value x}
q).z.pg:{[x]0N!(`zpg;x);value x}
q)0 "2+2"
(`zps;"2+2")
4
.z.pw
(validate user)¶
.z.pw:f
Where f
is a binary function, .z.pw
is evaluated after the -u
/-U
checks, and before .z.po
when opening a new connection to a kdb+ session.
The arguments are the user ID (as a symbol) and password (as a string) to be verified; the result is a boolean atom.
As .z.pw
is simply a function it can be used to implement rules such as “ordinary users can sign on only between 0800 and 1800 on weekdays” or can go out to external resources like an LDAP directory.
If .z.pw
returns 0b
the task attempting to establish the connection will get an 'access
error.
The default definition is {[user;pswd]1b}
.z.po
port open
Changes in 2.4
.z.q
(quiet mode)¶
1b
if Quiet Mode is set, else 0b
.
.z.r
(blocked)¶
A boolean, indicating whether an update in the current context would be blocked.
Returns 1b
- in
reval
- where the
-b
command-line option has been set - in a thread other than the main event thread
Since V4.1t 2021.04.16.
.z.s
(self)¶
A reference to the current function.
q){.z.s}[]
{.z.s}
Can be used to generate recursive function calls.
q)fact:{$[x<=0;1;x*.z.s x-1]}
q)fact[5]
120
Note this is purely an example; there are other ways to achieve the same result.
.z.ts
(timer)¶
.z.ts:f
Where f
is a unary function, .z.ts
is evaluated on intervals of the timer variable set by system command \t
. The timestamp is returned as Greenwich Mean Time (GMT).
q)/ set the timer to 1000 milliseconds
q)\t 1000
q)/ argument x is the timestamp scheduled for the callback
q)/ .z.ts is called once per second and returns the timestamp
q).z.ts:{0N!x}
q)2010.12.16D17:12:12.849442000
2010.12.16D17:12:13.849442000
2010.12.16D17:12:14.849442000
2010.12.16D17:12:15.849442000
2010.12.16D17:12:16.849442000
When kdb+ has completed executing a script passed as a command-line argument, and if there are no open sockets nor a console, kdb+ will exit. The timer alone is not enough to stop the process exiting – it must have an event source which is a file descriptor (socket, console, or some plugin registering a file descriptor and callback via the C API sd1
function).
.z.u
(user ID)¶
User ID, as a symbol, associated with the current handle.
q).z.u
`demo
For
- handle 0 (console) returns the userid under which the process is running.
- handles > 0 returns either:
- on the server end of a connection, the userid as passed to
hopen
by the client - on the client end of a connection, the null symbol
`
- on the server end of a connection, the userid as passed to
q).z.u / console is handle 0
`charlie
q)0".z.u" / explicitly using handle 0
`charlie
q)h:hopen`:localhost:5000:geoffrey:geffspasswd
q)h".z.u" / server side .z.u is as passed by the client to hopen
`geoffrey
q)h({.z.w".z.u"};::) / client side returns null symbol
`
.z.vs
(value set)¶
.z.vs:f
Where f
is a binary function, .z.vs
is evaluated after a value is set globally in the default namespace (e.g. a
, a.b
).
For function f[x;y]
, x
is the symbol of the modified variable and y
is the index.
Applies only to globals in the default namespace
This is not triggered for function-local variables, nor globals that are not in the default namespace, e.g. those prefixed with a dot such as .a.b
.
This is the same restriction that applies to logging.
The following example sets .z.vs
to display the symbol, the index and the value of the variable.
q).z.vs:{0N!(x;y;value x)}
q)m:(1 2;3 4)
(`m;();(1 2;3 4))
q)m[1;1]:0
(`m;1 1;(1 2;3 0))
.z.W
(handles)¶
Dictionary of IPC handles with the number of bytes waiting in their output queues.
q)h:hopen ...
q)h
3
q)neg[h]({};til 1000000); neg[h]({};til 10); .z.W
3| 8000030 110
q)neg[h]({};til 1000000); neg[h]({};til 10); sum each .z.W
3| 8000140
Since 4.1 2023.09.15, this returns handles!bytes
as I!J
, instead of the former handles!list
of individual msg sizes. Use sum each .z.W
if writing code targetting 4.0 and 4.1
q)h:hopen ...
q)h
6i
q)neg[h]({};til 1000000); neg[h]({};til 10); .z.W
6| 8000140
q)neg[h]({};til 1000000); neg[h]({};til 10); sum each .z.W
6| 8000140
Querying known handles can also be performed using -38!
, which can be more performant than using .z.W
to return the entire dataset of handles.
q)h:hopen 5000
q)neg[h]"11+1111111";.z.W h
24
q)neg[h]"11+1111111";(-38!h)`m
24
.z.h
active sockets, .z.w
handle, -38!
socket table
.z.w
(handle)¶
Connection handle; 0 for current session console.
q).z.w
0i
Inside a .z.p
* callback it returns the handle of the client session, not the current session.
.z.h
active sockets, .z.W
handles, -38!
socket table
.z.wc
(websocket close)¶
.z.wc:f
Where
f
is a unary functionh
is the handle to a websocket connection to a kdb+ session
f[h]
is evaluated after a websocket connection has been closed.
(Since V3.3t 2014.11.26.)
As the connection has been closed by the time .z.wc
is called, there are strictly no remote values that can be put into .z.a
, .z.u
or .z.w
so the local values are returned.
This allows you to clean up things like tables of users keyed by handle.
.z.wo
websocket open,
.z.ws
websockets,
.z.ac
HTTP auth
.z.wo
(websocket open)¶
.z.wo:f
Where
f
is a unary functionh
is the handle to a websocket connection to a kdb+ session
f[h]
is evaluated when the connection has been initialized, i.e. after it has been validated against any -u
/-U
file and .z.pw
checks.
(Since V3.3t 2014.11.26)
The handle argument is typically used by f
to build a dictionary of handles to session information such as the value of .z.a
, .z.u
.
.z.wc
websocket close,
.z.ws
websockets,
.z.ac
HTTP auth
.z.ws
(websockets)¶
z.ws:f
Where f
is a unary function, it is evaluated on a message arriving at a websocket. If the incoming message is a text message the argument is a string; if a binary message, a byte vector.
Sending a websocket message is limited to async messages only (sync is 'nyi
). A string will be sent as a text message; a byte vector as a binary message.
.z.wo
websocket open,
.z.wc
websocket close,
.z.ac
HTTP auth
WebSockets
.z.X
(raw command line)¶
.z.X
Returns a list of strings of the raw, unfiltered command line with which kdb+ was invoked, including the name under which q was invoked, as well as single-letter arguments. (Since V3.3 2015.02.12)
$ q somefile.q -customarg 42 -p localhost:17200
KDB+ 3.4 2016.09.22 Copyright (C) 1993-2016 KX Systems
m64/ 4()core 8192MB ...
q).z.X
,"q"
"somefile.q"
"-customarg"
"42"
"-p"
"localhost:17200"
.z.x
(argv), .z.f
(file), .z.q
(quiet mode), .Q.opt
(command parameters), .Q.def
(command defaults), .Q.x
(non-command parameters)
.z.x
(argv)¶
Command-line arguments as a list of strings
$ q test.q -P 0 -abc 123
q).z.x
"-abc"
"123"
The script name and the single-letter options used by q itself are not included.
Command-line options can be converted to a dictionary using the convenient .Q.opt
function.
.z.X
(raw command line), .z.f
(file), .z.q
(quiet mode), .Q.opt
(command parameters), .Q.def
(command defaults), .Q.x
(non-command parameters)
.z.Z
(local datetime)¶
Local time as a datetime atom.
q).z.Z
2006.11.13T21:16:14.601
The offset from UTC is fetched from the OS: kdb+ does not have its own time-offset database.
Which avoids problems like this.
.z.z
UTC datetime, .z.P
local timestamp, .z.p
UTC timestamp .z.N
local timespan, .z.n
UTC timespan
.z.z
(UTC datetime)¶
UTC time as a datetime atom.
q).z.z
2006.11.13T21:16:14.601
z.z
calls gettimeofday
and so has microsecond precision
.z.Z
local datetime, .z.P
local timestamp, .z.p
UTC timestamp .z.N
local timespan, .z.n
UTC timespan
.z.zd
(compression/encryption defaults)¶
.z.zd:(lbs;alg;lvl)
Integers lbs
, alg
, and lvl
are compression parameters and/or encryption parameters.
They set default values for logical block size, compression/encryption algorithm and compression level that apply when saving to files with no file extension.
Encryption available since 4.0 2019.12.12.
q).z.zd:17 2 6 / set zip defaults
q)\x .z.zd / clear zip defaults
set
File compression
Compression in kdb+
Data at rest encryption (DARE)
.z.T
.z.t
.z.D
.z.d
(time/date shortcuts)¶
Shorthand forms:
.z.T `time$.z.Z .z.D `date$.z.Z
.z.t `time$.z.z .z.d `date$.z.z
.z.Z
local datetime, .z.z
UTC datetime
Callbacks,
Using .z
Q for Mortals:
§11.6 Interprocess Communication