Storing dates in Common Lisp - lisp

What's the proper way to store dates in Common Lisp? The closest thing I found to an answer is this, which doesn't really seem to cut it for me.

How about ENCODE-UNIVERSAL-TIME?
(defparameter *my-birth-date* (encode-universal-time 0 0 0 14 2 1984))

If you want to store a date converted to string, you can use the following:
(multiple-value-bind
(s m h d mm y dw dst-p tz) (get-decoded-time)
(format nil "~D\/~D\/~D" date month year))

Related

How to parse a string in format "dd/MM/yyyy" to date type in q kdb?

How would you parse a date string in format "dd/MM/yyyy" using q kdb?
It is possible when the month argument is first "MM/dd/yyyy" as follows:
"D"$"1/20/2014"
2014-01-20d
However if day is first "dd/MM/yyyy"
"D"$"20/1/2014"
0Nd
KDB supports parsing of different datetime formats. Check details here:
https://code.kx.com/q/ref/casting/#tok
For your case you need to set 'z' option which specifies the format for date parsing.
0 is "mm/dd/yyyy" and 1 is "dd/mm/yyyy".
Details: https://code.kx.com/q/ref/syscmds/#z-date-parsing
This is how you do it for your example:
q) \z 1
q) "D"$"20/1/2014"
q) 2014.01.20
If you want to avoid changing system variables and have greater control over all possible date formats you can always write a custom date parser such as this:
f:{"D"$raze"0"^neg[4 2 2]$(y vs z)iasc`YYYY`MM`DD?x}
Which takes 3 parameters; date format expected, delimiter and date string. To handle your example it would be set up as follows:
q)f[`MM`DD`YYYY;"/";"1/20/2014"]
2014.01.20
It can also handle more unconventional date formats:
q)f[`MM`YYYY`DD;"p";"1p2014p20"]
2014.01.20
Obviously the above is overkill compared to inbuilt date parsing for your example but it does give a greater degree of flexibility.
Note that you do not have to pad with zeroes (tested with 3.3):
q)"." sv ("/" vs "1/20/2014") 2 0 1
"2014.1.20"
q)"D"$ "." sv ("/" vs "1/20/2014") 2 0 1
2014.01.20
In a function:
q)f:{"D"$"."sv("/"vs x)2 0 1}
q)f "1/20/2014"
2014.01.20
If you want a function that can handle both lists and individual dates:
q)g:{"D"$$[10=type x;"."sv("/"vs x)2 0 1;"."sv/:("/"vs/:x)[;2 0 1]]}
q)g "7/20/2014"
2014.07.20
q)g ("1/20/2014";"7/20/2014";"03/20/2014")
2014.01.20 2014.07.20 2014.03.20
... which is a little better than using each:
q)\ts:100000 g ("1/20/2014";"7/20/2014";"03/20/2014")
308 1168
q)\ts:100000 f each ("1/20/2014";"7/20/2014";"03/20/2014")
327 1312
... and quicker than padding/razing:
q)h:{"D"$raze"0"^neg[4 2 2]$(y vs z)iasc`YYYY`MM`DD?x}[`MM`DD`YYYY;"/";]
q)\ts:100000 h each ("1/20/2014";"7/20/2014";"03/20/2014")
615 1312

KDB projection with multiple variables

I have a function on KDB server as test[date;sym;starttime;endtime] and I want to run this function for list of symbol with specific date, starttime and endtime. for eg Test[2014.07.02,IBM,09:30:00,"11:00:25.325"] is one such row of the list which i want to pass to the "Test" function. I understand the projection function in KDB for eg each right/left (x f/: y) but how to pass a list of specific values for all the input arguments. Please see below for the input list
Date Symbol Starttime Endtime
2014.07.02 IBM 09:30:45 15:59:59.2
2014.07.03 AAPL 09:40:50 13:52:19.125
I will appreciate any help in this regard.
Thanks,
Here is my understanding of your doubt:
You have a list of inputs as L:(inputs1;inputs2;...) , where inputs1 is a list of (date;symbol;starttime;endtime) and you want to apply 'test' function on each input list in 'L'.
For this, KDB provide 'dot' operator.
Ex:
q) f:{[a;b;c] a+b+c}
q) f . (1 2 3)
q) 6
For list of inputs:
q) f ./: ((1 2 3);(4 5 6))
q) 6 15
In your case, it would be like:
q)test ./:L
Reference: https://code.kx.com/q/ref/apply/

Converting a real into an integer in lisp

How can I convert a real number to an integer in LISP?
Is there any primitive function?
Example:
3.0 => 3
There are multiple ways.
I will be using f instead of a float number below.
If you're interested in the next-highest integer, (ceiling f) gives you that. If you are interested in the next-lowest integer, (floor f) gives you that (for values like 1.0, the two functions will return the same integer value). If you prefer having the closest integer, you can use (round f) to find it.
Those are the three simplest and most portable ways I can think of.
Other option is TRUNCATE. Examples
> (truncate 2.2)
=> 2
0.20000005
> (truncate 2.9)
=> 2
0.9000001

Using 'ash' in LISP to perform a binary search?

So, I'm reading Land of Lisp now, and Lisp is turning out to be quite different than other programming languages that I've seen.
Anyways, the book provides some code that we're meant to enter into the CLISP REPL:
(defparameter *small* 1)
(defparameter *big* 100)
(defun guess-my-number ()
(ash (+ *small* *big*) -1))
(defun smaller ()
(setf *big* (1- (guess-my-number)))
(guess-my-number))
(defun bigger ()
(setf *small* (1+ (guess-my-number)))
(guess-my-number))
Now, the basic goal is to create a number guessing game wherein the user/player chooses a number, and then the computer tries to guess the number. It performs a "binary search", to find the player's number, by having the player report whether the computer-guessed number is higher or lower than the player's number.
I'm a little bit confused about the ash function. It's my understanding that this is vital to the binary search, but I'm not really sure why. The book somewhat explains what it does, but it's a little confusing.
What does the ash function do? Why is it passed the parameters of *small* added to *big* and -1? How does it work? What purpose does it serve to the binary search?
Google gives you this page which explains that ash is an arithmetic shift operation. So (ash x -1) shift x by one bit to the right, so gives its integer half.
Thanks to Basile Starynkevitch for the help on this one...
Anyhow, ash performs an arithmetic shift operation.
In the case of (ash x -1) it shifts x by one bit to the right, which ultimately returns the integer half.
For example, consider the binary number 1101. 1101 in binary is equivalent to 13 in decimal, which can be calculated like so:
8 * 1 = 8
4 * 1 = 4
2 * 0 = 0
1 * 1 = 1
8 + 4 + 0 + 1 = 13
Running (ash 13 -1) would look at the binary representation of 13, and perform an arithmetic shift of -1, shifting all the bits to the right by 1. This would produce a binary output of 110 (chopping off the 1 at the end of the original number). 110 in binary is equivalent to 6 in decimal, which can be calculated like so:
4 * 1 = 4
2 * 1 = 2
1 * 0 = 0
4 + 2 + 0 = 6
Now, 13 divided by 2 is not equivalent to 6, it's equivalent to 6.5, however, since it will return the integer half, 6 is the acceptable answer.
This is because binary is base 2.
Q. What does the ash function do? Why is it passed the parameters of small added to big and -1? How does it work? What purpose does it serve to the binary search?
It does operation of of shifting bits, more precisely Arithmetic shifting as explained/represented graphically for particular case of Lisp:
> (ash 51 1)
102
When you do (ash 51 1) it will shift the binary of 51 i.e 110011 by 1 bit place towards left side and results in 1100110 which gives you 102 in decimal. (process of binary to decimal conversion is explained in this answer)
Here it adds 0 in the vacant most right place (called Least Significant Bit).
> (ash 51 -1)
25
When you do (ash 51 -1) it will shift the binary of 51 i.e 110011 by 1 bit place towards right side (negative value stands for opposite direction) and results in 11001 which gives you 102 in decimal.
Here it discards the redundant LSB.
In particular example of "guess-my-number" game illustrated in Land of Lisp, we are interested in halving the range or to average. So, (ash (+ *small* *big*) -1)) will do halving of 100+1 = 100 / 2 to result in 50. We can check it as follows:
> (defparameter *small* 1)
*SMALL*
> (defparameter *big* 100)
*BIG*
>
(defun guess-my-number ()
(ash (+ *small* *big*) -1))
GUESS-MY-NUMBER
> (guess-my-number)
50
An interesting thing to notice is you can double the value of integer by left shifting by 1 bit and (approximately) halve it by right shifting by 1 bit.

Lisp: decode-universal-time is void

I'm editing orgmode, a time-management mode for emacs. I'm adding some new time functions.
In my addition i need to determine the day of the week for a given date. I use the following code:
(defun org-day-of-week (day month year)
(nth-value 6 (decode-universal-time (encode-universal-time 0 0 0 day month year 0) 0)))
Executing this code gives me the error:
nth-value: Symbol's function definition is void: decode-universal-time
I'm new to lisp, and can't find any info related to this error. I presume some libraries aren't loaded or available.
Can anyone please shed a light on this?
Regards,
Erwin Vrolijk
Snow.nl
Essentially decode-universal-time is a Common Lisp function. These are not necessarily available in emacs-lisp. Some quick checking in a local emacs indicates that this is the fact.
Something close to your original implementation would be:
(defun org-day-of-week (year month day)
(nth 6
(decode-time
(date-to-time
(format "%d-%02d-%02dT00:00:00" year month day)))))
You should be able to use decode-time instead (maybe in conjuction with date-to-time):
decode-time is a built-in function in `C source code'.
(decode-time &optional specified-time)
Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
The optional specified-time should be a list of (HIGH LOW . IGNORED),
as from `current-time' and `file-attributes', or nil to use the
current time. The obsolete form (HIGH . LOW) is also still accepted.
The list has the following nine members: SEC is an integer between 0
and 60; SEC is 60 for a leap second, which only some operating systems
support. MINUTE is an integer between 0 and 59. HOUR is an integer
between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
integer between 1 and 12. YEAR is an integer indicating the
four-digit year. DOW is the day of week, an integer between 0 and 6,
where 0 is Sunday. DST is t if daylight saving time is in effect,
otherwise nil. ZONE is an integer indicating the number of seconds
east of Greenwich. (Note that Common Lisp has different meanings for
DOW and ZONE.)
A cleaner version of Vatine's answer is:
(defun day-of-week (year month day)
"Return the day of the week given a YEAR MONTH DAY"
(nth 6 (decode-time (encode-time 0 0 0 day month year))))
decode-time and encode-time are documented here.
I haven't found the source of this problem, but found a workaround:
(defun day-of-week (day month year)
"Returns the day of the week as an integer.
Sunday is 0. Works for years after 1752."
(let ((offset '(0 3 2 5 0 3 5 1 4 6 2 4)))
(when (< month 3)
(decf year 1))
(mod
(truncate (+ year
(/ year 4)
(/ (- year)
100)
(/ year 400)
(nth (1- month) offset)
day
-1))
7)))