How do I parse a date and time?
Short answer: “D”$, “T”$, and “Z”$
In general you can parse strings to some particular type by passing the uppercase form of the corresponding type character as the left argument to $ (cast).
q can parse dates in YYYYMMDD, YYYY-MM-DD, or YYYY.MM.DD format:
q)"D"$ ("20070809"; "2007-08-09"; "2007.08.09")
2007.08.09 2007.08.09 2007.08.09
q)
Times must have the form HH:MM:SS.mmm, but you can shorten them:
q)"T"$ ("07:08:09.010"; "07:08:09"; "07:08"; "07")
07:08:09.010 07:08:09.000 07:08:00.000 07:00:00.000
q)
In addition, “T”$ will tolerate a missing zero for hours (and hours only) less than 10:
q)"T"$ "7:08:09"
07:08:09.000
q)
“Z”$ expects (as in XML) that dates and times are joined with a T:
q)"Z"$ "2007-08-09T07:08:09.101"
2007.08.09T07:08:09.101
q)
“Z”$ usually treats the text analogously to “D”$ and “T”$; that is, the date must be complete, but the time may have its finer points elided:
q)"Z"$ "2007"
0Nz
q)"Z"$ "20070809"
2007.08.09T00:00:00.000
q)
Note, however, the “Z”$ – unlike “T”$ – requires that hours less than 10 be prepended with zero:
q)"Z"$ "20070809T7:08:09"
0Nz
q)
You can also parse months with “M”$, minutes with “U”$, and seconds with “V”$:
q)"M"$ ("2007-08"; "2007.08"; "200708")
2007.08 2007.08 2007.08m
q)"U"$ "07:08:09.010"
07:08
q)"V"$ "07:08:09.010"
07:08:09
q)
Make sure you don’t pass any extra text to “M”$, though:
q)"M"$ "2007.08.01"
2007.01m
q)
There are two more type characters for parsing temporal values. “N”$ and “P”$ are for parsing nanosecond-precise time spans and datetimes, respectively:
q)"N"$ "12D07:08:09.123456789"
12D07:08:09.123456789
q)"P"$ "2007-08-09T07:08:09.123456789"
2007.08.09D07:08:09.123456789
q)
You may have discovered that “N”$ can parse floating point numbers, as well, but beware – depending on the range of the input, you might not get what you expect:
q)"N"$ "0.123456789"
0D00:00:00.123456789
q)"N"$ "1.123456789"
0D01:00:00.123456789
q)"N"$ "12.123456789"
0D12:00:00.123456789
q)"N"$ "24.123456789"
1D00:00:00.123456789
q)"N"$ "48.123456789"
2D00:00:00.123456789
q)"N"$ "4800.123456789"
2D00:00:00.123456789
q)
Stick with strings that represent durations in the way q does, and you’ll steer clear of surprises.
Lastly, if you find yourself with a text full of times expressed as seconds (and, optionally, fractions thereof) since the Unix epoch, “P”$, and “Z”$ can parse them, too:
q)unix_time: first system "date +%s"
q)unix_time
"1311635286"
q)"Z"$ unix_time
2011.07.25T23:08:06.000
q)"P"$ unix_time , ".123456789"
2011.07.25D23:08:06.123456789
q)